xref: /aosp_15_r20/system/teeui/libteeui/src/cbor.cpp (revision 20bfefbe1966c142a35ae1ab84a8af250b3fd403)
1*20bfefbeSAndroid Build Coastguard Worker /*
2*20bfefbeSAndroid Build Coastguard Worker  *
3*20bfefbeSAndroid Build Coastguard Worker  * Copyright 2017, The Android Open Source Project
4*20bfefbeSAndroid Build Coastguard Worker  *
5*20bfefbeSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*20bfefbeSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*20bfefbeSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
8*20bfefbeSAndroid Build Coastguard Worker  *
9*20bfefbeSAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
10*20bfefbeSAndroid Build Coastguard Worker  *
11*20bfefbeSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*20bfefbeSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*20bfefbeSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*20bfefbeSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*20bfefbeSAndroid Build Coastguard Worker  * limitations under the License.
16*20bfefbeSAndroid Build Coastguard Worker  */
17*20bfefbeSAndroid Build Coastguard Worker 
18*20bfefbeSAndroid Build Coastguard Worker #include <teeui/cbor.h>
19*20bfefbeSAndroid Build Coastguard Worker 
20*20bfefbeSAndroid Build Coastguard Worker namespace teeui {
21*20bfefbeSAndroid Build Coastguard Worker namespace cbor {
22*20bfefbeSAndroid Build Coastguard Worker 
23*20bfefbeSAndroid Build Coastguard Worker namespace {
24*20bfefbeSAndroid Build Coastguard Worker 
getByte(const uint64_t & v,const uint8_t index)25*20bfefbeSAndroid Build Coastguard Worker inline uint8_t getByte(const uint64_t& v, const uint8_t index) {
26*20bfefbeSAndroid Build Coastguard Worker     return (v >> (index * 8)) & 0xff;
27*20bfefbeSAndroid Build Coastguard Worker }
28*20bfefbeSAndroid Build Coastguard Worker 
writeBytes(WriteState state,uint64_t value,uint8_t size)29*20bfefbeSAndroid Build Coastguard Worker WriteState writeBytes(WriteState state, uint64_t value, uint8_t size) {
30*20bfefbeSAndroid Build Coastguard Worker     auto pos = state.data_;
31*20bfefbeSAndroid Build Coastguard Worker     if (!(state += size)) return state;
32*20bfefbeSAndroid Build Coastguard Worker     switch (size) {
33*20bfefbeSAndroid Build Coastguard Worker     case 8:
34*20bfefbeSAndroid Build Coastguard Worker         *pos++ = getByte(value, 7);
35*20bfefbeSAndroid Build Coastguard Worker         *pos++ = getByte(value, 6);
36*20bfefbeSAndroid Build Coastguard Worker         *pos++ = getByte(value, 5);
37*20bfefbeSAndroid Build Coastguard Worker         *pos++ = getByte(value, 4);
38*20bfefbeSAndroid Build Coastguard Worker         [[fallthrough]];
39*20bfefbeSAndroid Build Coastguard Worker     case 4:
40*20bfefbeSAndroid Build Coastguard Worker         *pos++ = getByte(value, 3);
41*20bfefbeSAndroid Build Coastguard Worker         *pos++ = getByte(value, 2);
42*20bfefbeSAndroid Build Coastguard Worker         [[fallthrough]];
43*20bfefbeSAndroid Build Coastguard Worker     case 2:
44*20bfefbeSAndroid Build Coastguard Worker         *pos++ = getByte(value, 1);
45*20bfefbeSAndroid Build Coastguard Worker         [[fallthrough]];
46*20bfefbeSAndroid Build Coastguard Worker     case 1:
47*20bfefbeSAndroid Build Coastguard Worker         *pos++ = getByte(value, 0);
48*20bfefbeSAndroid Build Coastguard Worker         break;
49*20bfefbeSAndroid Build Coastguard Worker     default:
50*20bfefbeSAndroid Build Coastguard Worker         state.error_ = Error::MALFORMED;
51*20bfefbeSAndroid Build Coastguard Worker     }
52*20bfefbeSAndroid Build Coastguard Worker     return state;
53*20bfefbeSAndroid Build Coastguard Worker }
54*20bfefbeSAndroid Build Coastguard Worker 
55*20bfefbeSAndroid Build Coastguard Worker }  // anonymous namespace
56*20bfefbeSAndroid Build Coastguard Worker 
writeHeader(WriteState wState,Type type,const uint64_t value)57*20bfefbeSAndroid Build Coastguard Worker WriteState writeHeader(WriteState wState, Type type, const uint64_t value) {
58*20bfefbeSAndroid Build Coastguard Worker     if (!wState) return wState;
59*20bfefbeSAndroid Build Coastguard Worker     uint8_t& header = *wState.data_;
60*20bfefbeSAndroid Build Coastguard Worker     if (!++wState) return wState;
61*20bfefbeSAndroid Build Coastguard Worker     header = static_cast<uint8_t>(type) << 5;
62*20bfefbeSAndroid Build Coastguard Worker     if (value < 24) {
63*20bfefbeSAndroid Build Coastguard Worker         header |= static_cast<uint8_t>(value);
64*20bfefbeSAndroid Build Coastguard Worker     } else if (value < 0x100) {
65*20bfefbeSAndroid Build Coastguard Worker         header |= 24;
66*20bfefbeSAndroid Build Coastguard Worker         wState = writeBytes(wState, value, 1);
67*20bfefbeSAndroid Build Coastguard Worker     } else if (value < 0x10000) {
68*20bfefbeSAndroid Build Coastguard Worker         header |= 25;
69*20bfefbeSAndroid Build Coastguard Worker         wState = writeBytes(wState, value, 2);
70*20bfefbeSAndroid Build Coastguard Worker     } else if (value < 0x100000000) {
71*20bfefbeSAndroid Build Coastguard Worker         header |= 26;
72*20bfefbeSAndroid Build Coastguard Worker         wState = writeBytes(wState, value, 4);
73*20bfefbeSAndroid Build Coastguard Worker     } else {
74*20bfefbeSAndroid Build Coastguard Worker         header |= 27;
75*20bfefbeSAndroid Build Coastguard Worker         wState = writeBytes(wState, value, 8);
76*20bfefbeSAndroid Build Coastguard Worker     }
77*20bfefbeSAndroid Build Coastguard Worker     return wState;
78*20bfefbeSAndroid Build Coastguard Worker }
79*20bfefbeSAndroid Build Coastguard Worker 
byteCount(char c)80*20bfefbeSAndroid Build Coastguard Worker static size_t byteCount(char c) {
81*20bfefbeSAndroid Build Coastguard Worker     if ((0xc0 & c) == 0x80) {
82*20bfefbeSAndroid Build Coastguard Worker         return 0;  // this is a multibyte payload byte
83*20bfefbeSAndroid Build Coastguard Worker     } else if (0x80 & c) {
84*20bfefbeSAndroid Build Coastguard Worker         /*
85*20bfefbeSAndroid Build Coastguard Worker          * CLZ - count leading zeroes.
86*20bfefbeSAndroid Build Coastguard Worker          * __builtin_clz promotes the argument to unsigned int.
87*20bfefbeSAndroid Build Coastguard Worker          * We invert c to turn leading ones into leading zeroes.
88*20bfefbeSAndroid Build Coastguard Worker          * We subtract additional leading zeroes due to the type promotion from the result.
89*20bfefbeSAndroid Build Coastguard Worker          */
90*20bfefbeSAndroid Build Coastguard Worker         return __builtin_clz((unsigned char)(~c)) - (sizeof(unsigned int) * 8 - 8);
91*20bfefbeSAndroid Build Coastguard Worker     } else {
92*20bfefbeSAndroid Build Coastguard Worker         return 1;
93*20bfefbeSAndroid Build Coastguard Worker     }
94*20bfefbeSAndroid Build Coastguard Worker }
95*20bfefbeSAndroid Build Coastguard Worker 
checkUTF8Copy(const char * begin,const char * const end,uint8_t * out)96*20bfefbeSAndroid Build Coastguard Worker bool checkUTF8Copy(const char* begin, const char* const end, uint8_t* out) {
97*20bfefbeSAndroid Build Coastguard Worker     while (begin != end) {
98*20bfefbeSAndroid Build Coastguard Worker         auto bc = byteCount(*begin);
99*20bfefbeSAndroid Build Coastguard Worker         // if the string ends in the middle of a multi byte char it is invalid
100*20bfefbeSAndroid Build Coastguard Worker         if (begin + bc > end) return false;
101*20bfefbeSAndroid Build Coastguard Worker         switch (bc) {
102*20bfefbeSAndroid Build Coastguard Worker         case 4:
103*20bfefbeSAndroid Build Coastguard Worker             if (out) *out++ = *reinterpret_cast<const uint8_t*>(begin++);
104*20bfefbeSAndroid Build Coastguard Worker             [[fallthrough]];
105*20bfefbeSAndroid Build Coastguard Worker         case 3:
106*20bfefbeSAndroid Build Coastguard Worker             if (out) *out++ = *reinterpret_cast<const uint8_t*>(begin++);
107*20bfefbeSAndroid Build Coastguard Worker             [[fallthrough]];
108*20bfefbeSAndroid Build Coastguard Worker         case 2:
109*20bfefbeSAndroid Build Coastguard Worker             if (out) *out++ = *reinterpret_cast<const uint8_t*>(begin++);
110*20bfefbeSAndroid Build Coastguard Worker             [[fallthrough]];
111*20bfefbeSAndroid Build Coastguard Worker         case 1:
112*20bfefbeSAndroid Build Coastguard Worker             if (out) *out++ = *reinterpret_cast<const uint8_t*>(begin++);
113*20bfefbeSAndroid Build Coastguard Worker             break;
114*20bfefbeSAndroid Build Coastguard Worker         default:
115*20bfefbeSAndroid Build Coastguard Worker             // case 0 means we encounted a payload byte when we expected a header.
116*20bfefbeSAndroid Build Coastguard Worker             // case > 4 is malformed.
117*20bfefbeSAndroid Build Coastguard Worker             return false;
118*20bfefbeSAndroid Build Coastguard Worker         }
119*20bfefbeSAndroid Build Coastguard Worker     }
120*20bfefbeSAndroid Build Coastguard Worker     return true;
121*20bfefbeSAndroid Build Coastguard Worker }
122*20bfefbeSAndroid Build Coastguard Worker 
123*20bfefbeSAndroid Build Coastguard Worker }  // namespace cbor
124*20bfefbeSAndroid Build Coastguard Worker }  // namespace teeui
125