1 /*
2 **
3 ** Copyright 2017, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include <android/hardware/confirmationui/support/cbor.h>
19
20 namespace android {
21 namespace hardware {
22 namespace confirmationui {
23 namespace support {
24 namespace {
25
getByte(const uint64_t & v,const uint8_t index)26 inline uint8_t getByte(const uint64_t& v, const uint8_t index) {
27 return v >> (index * 8);
28 }
29
writeBytes(WriteState state,uint64_t value,uint8_t size)30 WriteState writeBytes(WriteState state, uint64_t value, uint8_t size) {
31 auto pos = state.data_;
32 if (!(state += size)) return state;
33 switch (size) {
34 case 8:
35 *pos++ = getByte(value, 7);
36 *pos++ = getByte(value, 6);
37 *pos++ = getByte(value, 5);
38 *pos++ = getByte(value, 4);
39 [[fallthrough]];
40 case 4:
41 *pos++ = getByte(value, 3);
42 *pos++ = getByte(value, 2);
43 [[fallthrough]];
44 case 2:
45 *pos++ = getByte(value, 1);
46 [[fallthrough]];
47 case 1:
48 *pos++ = value;
49 break;
50 default:
51 state.error_ = Error::MALFORMED;
52 }
53 return state;
54 }
55
56 } // anonymous namespace
57
writeHeader(WriteState wState,Type type,const uint64_t value)58 WriteState writeHeader(WriteState wState, Type type, const uint64_t value) {
59 if (!wState) return wState;
60 uint8_t& header = *wState.data_;
61 if (!++wState) return wState;
62 header = static_cast<uint8_t>(type) << 5;
63 if (value < 24) {
64 header |= static_cast<uint8_t>(value);
65 } else if (value < 0x100) {
66 header |= 24;
67 wState = writeBytes(wState, value, 1);
68 } else if (value < 0x10000) {
69 header |= 25;
70 wState = writeBytes(wState, value, 2);
71 } else if (value < 0x100000000) {
72 header |= 26;
73 wState = writeBytes(wState, value, 4);
74 } else {
75 header |= 27;
76 wState = writeBytes(wState, value, 8);
77 }
78 return wState;
79 }
80
checkUTF8Copy(const char * begin,const char * const end,uint8_t * out)81 bool checkUTF8Copy(const char* begin, const char* const end, uint8_t* out) {
82 uint32_t multi_byte_length = 0;
83 while (begin != end) {
84 if (multi_byte_length) {
85 // parsing multi byte character - must start with 10xxxxxx
86 --multi_byte_length;
87 if ((*begin & 0xc0) != 0x80) return false;
88 } else if (!((*begin) & 0x80)) {
89 // 7bit character -> nothing to be done
90 } else {
91 // msb is set and we were not parsing a multi byte character
92 // so this must be a header byte
93 char c = *begin << 1;
94 while (c & 0x80) {
95 ++multi_byte_length;
96 c <<= 1;
97 }
98 // headers of the form 10xxxxxx are not allowed
99 if (multi_byte_length < 1) return false;
100 // chars longer than 4 bytes are not allowed (multi_byte_length does not count the
101 // header thus > 3
102 if (multi_byte_length > 3) return false;
103 }
104 if (out) *out++ = *reinterpret_cast<const uint8_t*>(begin++);
105 }
106 // if the string ends in the middle of a multi byte char it is invalid
107 if (multi_byte_length) return false;
108 return true;
109 }
110
111 } // namespace support
112 } // namespace confirmationui
113 } // namespace hardware
114 } // namespace android
115