1 /* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <openssl/bytestring.h>
16
17 #include <assert.h>
18 #include <string.h>
19
20 #include <openssl/mem.h>
21
22
cbb_init(CBB * cbb,uint8_t * buf,size_t cap)23 static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
24 struct cbb_buffer_st *base;
25
26 base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
27 if (base == NULL) {
28 return 0;
29 }
30
31 base->buf = buf;
32 base->len = 0;
33 base->cap = cap;
34 base->can_resize = 1;
35
36 memset(cbb, 0, sizeof(CBB));
37 cbb->base = base;
38 cbb->is_top_level = 1;
39 return 1;
40 }
41
CBB_init(CBB * cbb,size_t initial_capacity)42 int CBB_init(CBB *cbb, size_t initial_capacity) {
43 uint8_t *buf;
44
45 buf = OPENSSL_malloc(initial_capacity);
46 if (initial_capacity > 0 && buf == NULL) {
47 return 0;
48 }
49
50 if (!cbb_init(cbb, buf, initial_capacity)) {
51 OPENSSL_free(buf);
52 return 0;
53 }
54
55 return 1;
56 }
57
CBB_init_fixed(CBB * cbb,uint8_t * buf,size_t len)58 int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
59 if (!cbb_init(cbb, buf, len)) {
60 return 0;
61 }
62
63 cbb->base->can_resize = 0;
64 return 1;
65 }
66
CBB_cleanup(CBB * cbb)67 void CBB_cleanup(CBB *cbb) {
68 if (cbb->base) {
69 if (cbb->base->can_resize) {
70 OPENSSL_free(cbb->base->buf);
71 }
72 OPENSSL_free(cbb->base);
73 }
74 cbb->base = NULL;
75 }
76
cbb_buffer_add(struct cbb_buffer_st * base,uint8_t ** out,size_t len)77 static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
78 size_t len) {
79 size_t newlen;
80
81 if (base == NULL) {
82 return 0;
83 }
84
85 newlen = base->len + len;
86 if (newlen < base->len) {
87 /* Overflow */
88 return 0;
89 }
90
91 if (newlen > base->cap) {
92 size_t newcap = base->cap * 2;
93 uint8_t *newbuf;
94
95 if (!base->can_resize) {
96 return 0;
97 }
98
99 if (newcap < base->cap || newcap < newlen) {
100 newcap = newlen;
101 }
102 newbuf = OPENSSL_realloc(base->buf, newcap);
103 if (newbuf == NULL) {
104 return 0;
105 }
106
107 base->buf = newbuf;
108 base->cap = newcap;
109 }
110
111 if (out) {
112 *out = base->buf + base->len;
113 }
114 base->len = newlen;
115 return 1;
116 }
117
cbb_buffer_add_u(struct cbb_buffer_st * base,uint32_t v,size_t len_len)118 static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
119 size_t len_len) {
120 uint8_t *buf;
121 size_t i;
122
123 if (len_len == 0) {
124 return 1;
125 }
126 if (!cbb_buffer_add(base, &buf, len_len)) {
127 return 0;
128 }
129
130 for (i = len_len - 1; i < len_len; i--) {
131 buf[i] = v;
132 v >>= 8;
133 }
134 return 1;
135 }
136
CBB_finish(CBB * cbb,uint8_t ** out_data,size_t * out_len)137 int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
138 if (!cbb->is_top_level) {
139 return 0;
140 }
141
142 if (!CBB_flush(cbb)) {
143 return 0;
144 }
145
146 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
147 /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
148 return 0;
149 }
150
151 if (out_data != NULL) {
152 *out_data = cbb->base->buf;
153 }
154 if (out_len != NULL) {
155 *out_len = cbb->base->len;
156 }
157 cbb->base->buf = NULL;
158 CBB_cleanup(cbb);
159 return 1;
160 }
161
162 /* CBB_flush recurses and then writes out any pending length prefix. The
163 * current length of the underlying base is taken to be the length of the
164 * length-prefixed data. */
CBB_flush(CBB * cbb)165 int CBB_flush(CBB *cbb) {
166 size_t child_start, i, len;
167
168 if (cbb->base == NULL) {
169 return 0;
170 }
171
172 if (cbb->child == NULL || cbb->pending_len_len == 0) {
173 return 1;
174 }
175
176 child_start = cbb->offset + cbb->pending_len_len;
177
178 if (!CBB_flush(cbb->child) ||
179 child_start < cbb->offset ||
180 cbb->base->len < child_start) {
181 return 0;
182 }
183
184 len = cbb->base->len - child_start;
185
186 if (cbb->pending_is_asn1) {
187 /* For ASN.1 we assume that we'll only need a single byte for the length.
188 * If that turned out to be incorrect, we have to move the contents along
189 * in order to make space. */
190 size_t len_len;
191 uint8_t initial_length_byte;
192
193 assert (cbb->pending_len_len == 1);
194
195 if (len > 0xfffffffe) {
196 /* Too large. */
197 return 0;
198 } else if (len > 0xffffff) {
199 len_len = 5;
200 initial_length_byte = 0x80 | 4;
201 } else if (len > 0xffff) {
202 len_len = 4;
203 initial_length_byte = 0x80 | 3;
204 } else if (len > 0xff) {
205 len_len = 3;
206 initial_length_byte = 0x80 | 2;
207 } else if (len > 0x7f) {
208 len_len = 2;
209 initial_length_byte = 0x80 | 1;
210 } else {
211 len_len = 1;
212 initial_length_byte = len;
213 len = 0;
214 }
215
216 if (len_len != 1) {
217 /* We need to move the contents along in order to make space. */
218 size_t extra_bytes = len_len - 1;
219 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
220 return 0;
221 }
222 memmove(cbb->base->buf + child_start + extra_bytes,
223 cbb->base->buf + child_start, len);
224 }
225 cbb->base->buf[cbb->offset++] = initial_length_byte;
226 cbb->pending_len_len = len_len - 1;
227 }
228
229 for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
230 cbb->base->buf[cbb->offset + i] = len;
231 len >>= 8;
232 }
233 if (len != 0) {
234 return 0;
235 }
236
237 cbb->child->base = NULL;
238 cbb->child = NULL;
239 cbb->pending_len_len = 0;
240 cbb->pending_is_asn1 = 0;
241 cbb->offset = 0;
242
243 return 1;
244 }
245
246
cbb_add_length_prefixed(CBB * cbb,CBB * out_contents,size_t len_len)247 static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
248 size_t len_len) {
249 uint8_t *prefix_bytes;
250
251 if (!CBB_flush(cbb)) {
252 return 0;
253 }
254
255 cbb->offset = cbb->base->len;
256 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
257 return 0;
258 }
259
260 memset(prefix_bytes, 0, len_len);
261 memset(out_contents, 0, sizeof(CBB));
262 out_contents->base = cbb->base;
263 cbb->child = out_contents;
264 cbb->pending_len_len = len_len;
265 cbb->pending_is_asn1 = 0;
266
267 return 1;
268 }
269
CBB_add_u8_length_prefixed(CBB * cbb,CBB * out_contents)270 int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
271 return cbb_add_length_prefixed(cbb, out_contents, 1);
272 }
273
CBB_add_u16_length_prefixed(CBB * cbb,CBB * out_contents)274 int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
275 return cbb_add_length_prefixed(cbb, out_contents, 2);
276 }
277
CBB_add_u24_length_prefixed(CBB * cbb,CBB * out_contents)278 int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
279 return cbb_add_length_prefixed(cbb, out_contents, 3);
280 }
281
CBB_add_asn1(CBB * cbb,CBB * out_contents,uint8_t tag)282 int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
283 if ((tag & 0x1f) == 0x1f) {
284 /* Long form identifier octets are not supported. */
285 return 0;
286 }
287
288 if (!CBB_flush(cbb) ||
289 !CBB_add_u8(cbb, tag)) {
290 return 0;
291 }
292
293 cbb->offset = cbb->base->len;
294 if (!CBB_add_u8(cbb, 0)) {
295 return 0;
296 }
297
298 memset(out_contents, 0, sizeof(CBB));
299 out_contents->base = cbb->base;
300 cbb->child = out_contents;
301 cbb->pending_len_len = 1;
302 cbb->pending_is_asn1 = 1;
303
304 return 1;
305 }
306
CBB_add_bytes(CBB * cbb,const uint8_t * data,size_t len)307 int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
308 uint8_t *dest;
309
310 if (!CBB_flush(cbb) ||
311 !cbb_buffer_add(cbb->base, &dest, len)) {
312 return 0;
313 }
314 memcpy(dest, data, len);
315 return 1;
316 }
317
CBB_add_space(CBB * cbb,uint8_t ** out_data,size_t len)318 int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
319 if (!CBB_flush(cbb) ||
320 !cbb_buffer_add(cbb->base, out_data, len)) {
321 return 0;
322 }
323 return 1;
324 }
325
CBB_add_u8(CBB * cbb,uint8_t value)326 int CBB_add_u8(CBB *cbb, uint8_t value) {
327 if (!CBB_flush(cbb)) {
328 return 0;
329 }
330
331 return cbb_buffer_add_u(cbb->base, value, 1);
332 }
333
CBB_add_u16(CBB * cbb,uint16_t value)334 int CBB_add_u16(CBB *cbb, uint16_t value) {
335 if (!CBB_flush(cbb)) {
336 return 0;
337 }
338
339 return cbb_buffer_add_u(cbb->base, value, 2);
340 }
341
CBB_add_u24(CBB * cbb,uint32_t value)342 int CBB_add_u24(CBB *cbb, uint32_t value) {
343 if (!CBB_flush(cbb)) {
344 return 0;
345 }
346
347 return cbb_buffer_add_u(cbb->base, value, 3);
348 }
349
CBB_add_asn1_uint64(CBB * cbb,uint64_t value)350 int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
351 CBB child;
352 size_t i;
353 int started = 0;
354
355 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
356 return 0;
357 }
358
359 for (i = 0; i < 8; i++) {
360 uint8_t byte = (value >> 8*(7-i)) & 0xff;
361 if (!started) {
362 if (byte == 0) {
363 /* Don't encode leading zeros. */
364 continue;
365 }
366 /* If the high bit is set, add a padding byte to make it
367 * unsigned. */
368 if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
369 return 0;
370 }
371 started = 1;
372 }
373 if (!CBB_add_u8(&child, byte)) {
374 return 0;
375 }
376 }
377
378 /* 0 is encoded as a single 0, not the empty string. */
379 if (!started && !CBB_add_u8(&child, 0)) {
380 return 0;
381 }
382
383 return CBB_flush(cbb);
384 }
385