xref: /aosp_15_r20/external/open-dice/src/cbor_writer.c (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
1*60b67249SAndroid Build Coastguard Worker // Copyright 2021 Google LLC
2*60b67249SAndroid Build Coastguard Worker //
3*60b67249SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*60b67249SAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*60b67249SAndroid Build Coastguard Worker // the License at
6*60b67249SAndroid Build Coastguard Worker //
7*60b67249SAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*60b67249SAndroid Build Coastguard Worker //
9*60b67249SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*60b67249SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*60b67249SAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*60b67249SAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*60b67249SAndroid Build Coastguard Worker // the License.
14*60b67249SAndroid Build Coastguard Worker 
15*60b67249SAndroid Build Coastguard Worker #include "dice/cbor_writer.h"
16*60b67249SAndroid Build Coastguard Worker 
17*60b67249SAndroid Build Coastguard Worker #include <stdbool.h>
18*60b67249SAndroid Build Coastguard Worker #include <stddef.h>
19*60b67249SAndroid Build Coastguard Worker #include <stdint.h>
20*60b67249SAndroid Build Coastguard Worker #include <string.h>
21*60b67249SAndroid Build Coastguard Worker 
22*60b67249SAndroid Build Coastguard Worker enum CborType {
23*60b67249SAndroid Build Coastguard Worker   CBOR_TYPE_UINT = 0,
24*60b67249SAndroid Build Coastguard Worker   CBOR_TYPE_NINT = 1,
25*60b67249SAndroid Build Coastguard Worker   CBOR_TYPE_BSTR = 2,
26*60b67249SAndroid Build Coastguard Worker   CBOR_TYPE_TSTR = 3,
27*60b67249SAndroid Build Coastguard Worker   CBOR_TYPE_ARRAY = 4,
28*60b67249SAndroid Build Coastguard Worker   CBOR_TYPE_MAP = 5,
29*60b67249SAndroid Build Coastguard Worker   CBOR_TYPE_TAG = 6,
30*60b67249SAndroid Build Coastguard Worker   CBOR_TYPE_SIMPLE = 7,
31*60b67249SAndroid Build Coastguard Worker };
32*60b67249SAndroid Build Coastguard Worker 
CborWriteWouldOverflowCursor(size_t size,struct CborOut * out)33*60b67249SAndroid Build Coastguard Worker static bool CborWriteWouldOverflowCursor(size_t size, struct CborOut* out) {
34*60b67249SAndroid Build Coastguard Worker   return size > SIZE_MAX - out->cursor;
35*60b67249SAndroid Build Coastguard Worker }
36*60b67249SAndroid Build Coastguard Worker 
CborWriteFitsInBuffer(size_t size,struct CborOut * out)37*60b67249SAndroid Build Coastguard Worker static bool CborWriteFitsInBuffer(size_t size, struct CborOut* out) {
38*60b67249SAndroid Build Coastguard Worker   return out->cursor <= out->buffer_size &&
39*60b67249SAndroid Build Coastguard Worker          size <= out->buffer_size - out->cursor;
40*60b67249SAndroid Build Coastguard Worker }
41*60b67249SAndroid Build Coastguard Worker 
CborWriteType(enum CborType type,uint64_t val,struct CborOut * out)42*60b67249SAndroid Build Coastguard Worker static void CborWriteType(enum CborType type, uint64_t val,
43*60b67249SAndroid Build Coastguard Worker                           struct CborOut* out) {
44*60b67249SAndroid Build Coastguard Worker   size_t size;
45*60b67249SAndroid Build Coastguard Worker   if (val <= 23) {
46*60b67249SAndroid Build Coastguard Worker     size = 1;
47*60b67249SAndroid Build Coastguard Worker   } else if (val <= 0xff) {
48*60b67249SAndroid Build Coastguard Worker     size = 2;
49*60b67249SAndroid Build Coastguard Worker   } else if (val <= 0xffff) {
50*60b67249SAndroid Build Coastguard Worker     size = 3;
51*60b67249SAndroid Build Coastguard Worker   } else if (val <= 0xffffffff) {
52*60b67249SAndroid Build Coastguard Worker     size = 5;
53*60b67249SAndroid Build Coastguard Worker   } else {
54*60b67249SAndroid Build Coastguard Worker     size = 9;
55*60b67249SAndroid Build Coastguard Worker   }
56*60b67249SAndroid Build Coastguard Worker   if (CborWriteWouldOverflowCursor(size, out)) {
57*60b67249SAndroid Build Coastguard Worker     out->cursor = SIZE_MAX;
58*60b67249SAndroid Build Coastguard Worker     return;
59*60b67249SAndroid Build Coastguard Worker   }
60*60b67249SAndroid Build Coastguard Worker   if (CborWriteFitsInBuffer(size, out)) {
61*60b67249SAndroid Build Coastguard Worker     if (size == 1) {
62*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor] = (uint8_t)((type << 5) | val);
63*60b67249SAndroid Build Coastguard Worker     } else if (size == 2) {
64*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor] = (uint8_t)((type << 5) | 24);
65*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 1] = val & 0xff;
66*60b67249SAndroid Build Coastguard Worker     } else if (size == 3) {
67*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor] = (uint8_t)((type << 5) | 25);
68*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 1] = (val >> 8) & 0xff;
69*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 2] = val & 0xff;
70*60b67249SAndroid Build Coastguard Worker     } else if (size == 5) {
71*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor] = (uint8_t)((type << 5) | 26);
72*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 1] = (val >> 24) & 0xff;
73*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 2] = (val >> 16) & 0xff;
74*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 3] = (val >> 8) & 0xff;
75*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 4] = val & 0xff;
76*60b67249SAndroid Build Coastguard Worker     } else if (size == 9) {
77*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor] = (uint8_t)((type << 5) | 27);
78*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 1] = (val >> 56) & 0xff;
79*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 2] = (val >> 48) & 0xff;
80*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 3] = (val >> 40) & 0xff;
81*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 4] = (val >> 32) & 0xff;
82*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 5] = (val >> 24) & 0xff;
83*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 6] = (val >> 16) & 0xff;
84*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 7] = (val >> 8) & 0xff;
85*60b67249SAndroid Build Coastguard Worker       out->buffer[out->cursor + 8] = val & 0xff;
86*60b67249SAndroid Build Coastguard Worker     }
87*60b67249SAndroid Build Coastguard Worker   }
88*60b67249SAndroid Build Coastguard Worker   out->cursor += size;
89*60b67249SAndroid Build Coastguard Worker }
90*60b67249SAndroid Build Coastguard Worker 
CborAllocStr(enum CborType type,size_t data_size,struct CborOut * out)91*60b67249SAndroid Build Coastguard Worker static void* CborAllocStr(enum CborType type, size_t data_size,
92*60b67249SAndroid Build Coastguard Worker                           struct CborOut* out) {
93*60b67249SAndroid Build Coastguard Worker   CborWriteType(type, data_size, out);
94*60b67249SAndroid Build Coastguard Worker   bool overflow = CborWriteWouldOverflowCursor(data_size, out);
95*60b67249SAndroid Build Coastguard Worker   bool fit = CborWriteFitsInBuffer(data_size, out);
96*60b67249SAndroid Build Coastguard Worker   void* ptr = (overflow || !fit) ? NULL : &out->buffer[out->cursor];
97*60b67249SAndroid Build Coastguard Worker   out->cursor = overflow ? SIZE_MAX : out->cursor + data_size;
98*60b67249SAndroid Build Coastguard Worker   return ptr;
99*60b67249SAndroid Build Coastguard Worker }
100*60b67249SAndroid Build Coastguard Worker 
CborWriteStr(enum CborType type,size_t data_size,const void * data,struct CborOut * out)101*60b67249SAndroid Build Coastguard Worker static void CborWriteStr(enum CborType type, size_t data_size, const void* data,
102*60b67249SAndroid Build Coastguard Worker                          struct CborOut* out) {
103*60b67249SAndroid Build Coastguard Worker   uint8_t* ptr = CborAllocStr(type, data_size, out);
104*60b67249SAndroid Build Coastguard Worker   if (ptr && data_size) {
105*60b67249SAndroid Build Coastguard Worker     memcpy(ptr, data, data_size);
106*60b67249SAndroid Build Coastguard Worker   }
107*60b67249SAndroid Build Coastguard Worker }
108*60b67249SAndroid Build Coastguard Worker 
CborWriteInt(int64_t val,struct CborOut * out)109*60b67249SAndroid Build Coastguard Worker void CborWriteInt(int64_t val, struct CborOut* out) {
110*60b67249SAndroid Build Coastguard Worker   if (val < 0) {
111*60b67249SAndroid Build Coastguard Worker     CborWriteType(CBOR_TYPE_NINT, (uint64_t)(-1 - val), out);
112*60b67249SAndroid Build Coastguard Worker   } else {
113*60b67249SAndroid Build Coastguard Worker     CborWriteType(CBOR_TYPE_UINT, (uint64_t)val, out);
114*60b67249SAndroid Build Coastguard Worker   }
115*60b67249SAndroid Build Coastguard Worker }
116*60b67249SAndroid Build Coastguard Worker 
CborWriteUint(uint64_t val,struct CborOut * out)117*60b67249SAndroid Build Coastguard Worker void CborWriteUint(uint64_t val, struct CborOut* out) {
118*60b67249SAndroid Build Coastguard Worker   CborWriteType(CBOR_TYPE_UINT, val, out);
119*60b67249SAndroid Build Coastguard Worker }
120*60b67249SAndroid Build Coastguard Worker 
CborWriteBstr(size_t data_size,const uint8_t * data,struct CborOut * out)121*60b67249SAndroid Build Coastguard Worker void CborWriteBstr(size_t data_size, const uint8_t* data, struct CborOut* out) {
122*60b67249SAndroid Build Coastguard Worker   CborWriteStr(CBOR_TYPE_BSTR, data_size, data, out);
123*60b67249SAndroid Build Coastguard Worker }
124*60b67249SAndroid Build Coastguard Worker 
CborAllocBstr(size_t data_size,struct CborOut * out)125*60b67249SAndroid Build Coastguard Worker uint8_t* CborAllocBstr(size_t data_size, struct CborOut* out) {
126*60b67249SAndroid Build Coastguard Worker   return CborAllocStr(CBOR_TYPE_BSTR, data_size, out);
127*60b67249SAndroid Build Coastguard Worker }
128*60b67249SAndroid Build Coastguard Worker 
CborWriteTstr(const char * str,struct CborOut * out)129*60b67249SAndroid Build Coastguard Worker void CborWriteTstr(const char* str, struct CborOut* out) {
130*60b67249SAndroid Build Coastguard Worker   CborWriteStr(CBOR_TYPE_TSTR, strlen(str), str, out);
131*60b67249SAndroid Build Coastguard Worker }
132*60b67249SAndroid Build Coastguard Worker 
CborAllocTstr(size_t size,struct CborOut * out)133*60b67249SAndroid Build Coastguard Worker char* CborAllocTstr(size_t size, struct CborOut* out) {
134*60b67249SAndroid Build Coastguard Worker   return CborAllocStr(CBOR_TYPE_TSTR, size, out);
135*60b67249SAndroid Build Coastguard Worker }
136*60b67249SAndroid Build Coastguard Worker 
CborWriteArray(size_t num_elements,struct CborOut * out)137*60b67249SAndroid Build Coastguard Worker void CborWriteArray(size_t num_elements, struct CborOut* out) {
138*60b67249SAndroid Build Coastguard Worker   CborWriteType(CBOR_TYPE_ARRAY, num_elements, out);
139*60b67249SAndroid Build Coastguard Worker }
140*60b67249SAndroid Build Coastguard Worker 
CborWriteMap(size_t num_pairs,struct CborOut * out)141*60b67249SAndroid Build Coastguard Worker void CborWriteMap(size_t num_pairs, struct CborOut* out) {
142*60b67249SAndroid Build Coastguard Worker   CborWriteType(CBOR_TYPE_MAP, num_pairs, out);
143*60b67249SAndroid Build Coastguard Worker }
144*60b67249SAndroid Build Coastguard Worker 
CborWriteTag(uint64_t tag,struct CborOut * out)145*60b67249SAndroid Build Coastguard Worker void CborWriteTag(uint64_t tag, struct CborOut* out) {
146*60b67249SAndroid Build Coastguard Worker   CborWriteType(CBOR_TYPE_TAG, tag, out);
147*60b67249SAndroid Build Coastguard Worker }
148*60b67249SAndroid Build Coastguard Worker 
CborWriteFalse(struct CborOut * out)149*60b67249SAndroid Build Coastguard Worker void CborWriteFalse(struct CborOut* out) {
150*60b67249SAndroid Build Coastguard Worker   CborWriteType(CBOR_TYPE_SIMPLE, /*val=*/20, out);
151*60b67249SAndroid Build Coastguard Worker }
152*60b67249SAndroid Build Coastguard Worker 
CborWriteTrue(struct CborOut * out)153*60b67249SAndroid Build Coastguard Worker void CborWriteTrue(struct CborOut* out) {
154*60b67249SAndroid Build Coastguard Worker   CborWriteType(CBOR_TYPE_SIMPLE, /*val=*/21, out);
155*60b67249SAndroid Build Coastguard Worker }
156*60b67249SAndroid Build Coastguard Worker 
CborWriteNull(struct CborOut * out)157*60b67249SAndroid Build Coastguard Worker void CborWriteNull(struct CborOut* out) {
158*60b67249SAndroid Build Coastguard Worker   CborWriteType(CBOR_TYPE_SIMPLE, /*val=*/22, out);
159*60b67249SAndroid Build Coastguard Worker }
160