1 |
|
|
/* $OpenBSD: bs_cbb.c,v 1.17 2017/08/12 02:50:05 jsing Exp $ */ |
2 |
|
|
/* |
3 |
|
|
* Copyright (c) 2014, Google Inc. |
4 |
|
|
* |
5 |
|
|
* Permission to use, copy, modify, and/or distribute this software for any |
6 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
7 |
|
|
* copyright notice and this permission notice appear in all copies. |
8 |
|
|
* |
9 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
12 |
|
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
14 |
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
15 |
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ |
16 |
|
|
|
17 |
|
|
#include <assert.h> |
18 |
|
|
#include <stdlib.h> |
19 |
|
|
#include <string.h> |
20 |
|
|
|
21 |
|
|
#include <openssl/opensslconf.h> |
22 |
|
|
|
23 |
|
|
#include "bytestring.h" |
24 |
|
|
|
25 |
|
|
#define CBB_INITIAL_SIZE 64 |
26 |
|
|
|
27 |
|
|
static int |
28 |
|
|
cbb_init(CBB *cbb, uint8_t *buf, size_t cap) |
29 |
|
|
{ |
30 |
|
|
struct cbb_buffer_st *base; |
31 |
|
|
|
32 |
|
57048 |
base = malloc(sizeof(struct cbb_buffer_st)); |
33 |
✗✓ |
28524 |
if (base == NULL) |
34 |
|
|
return 0; |
35 |
|
|
|
36 |
|
28524 |
base->buf = buf; |
37 |
|
28524 |
base->len = 0; |
38 |
|
28524 |
base->cap = cap; |
39 |
|
28524 |
base->can_resize = 1; |
40 |
|
|
|
41 |
|
28524 |
cbb->base = base; |
42 |
|
28524 |
cbb->is_top_level = 1; |
43 |
|
|
|
44 |
|
28524 |
return 1; |
45 |
|
28524 |
} |
46 |
|
|
|
47 |
|
|
int |
48 |
|
|
CBB_init(CBB *cbb, size_t initial_capacity) |
49 |
|
|
{ |
50 |
|
|
uint8_t *buf = NULL; |
51 |
|
|
|
52 |
|
23072 |
memset(cbb, 0, sizeof(*cbb)); |
53 |
|
|
|
54 |
✓✓ |
11536 |
if (initial_capacity == 0) |
55 |
|
1396 |
initial_capacity = CBB_INITIAL_SIZE; |
56 |
|
|
|
57 |
✗✓ |
11536 |
if ((buf = malloc(initial_capacity)) == NULL) |
58 |
|
|
return 0; |
59 |
|
|
|
60 |
✗✓ |
11536 |
if (!cbb_init(cbb, buf, initial_capacity)) { |
61 |
|
|
free(buf); |
62 |
|
|
return 0; |
63 |
|
|
} |
64 |
|
|
|
65 |
|
11536 |
return 1; |
66 |
|
11536 |
} |
67 |
|
|
|
68 |
|
|
int |
69 |
|
|
CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) |
70 |
|
|
{ |
71 |
|
33976 |
memset(cbb, 0, sizeof(*cbb)); |
72 |
|
|
|
73 |
✗✓ |
16988 |
if (!cbb_init(cbb, buf, len)) |
74 |
|
|
return 0; |
75 |
|
|
|
76 |
|
16988 |
cbb->base->can_resize = 0; |
77 |
|
|
|
78 |
|
16988 |
return 1; |
79 |
|
16988 |
} |
80 |
|
|
|
81 |
|
|
void |
82 |
|
|
CBB_cleanup(CBB *cbb) |
83 |
|
|
{ |
84 |
✓✓ |
59240 |
if (cbb->base) { |
85 |
✓✓ |
28524 |
if (cbb->base->can_resize) |
86 |
|
11536 |
freezero(cbb->base->buf, cbb->base->cap); |
87 |
|
28524 |
free(cbb->base); |
88 |
|
28524 |
} |
89 |
|
29620 |
cbb->base = NULL; |
90 |
|
29620 |
cbb->child = NULL; |
91 |
|
29620 |
} |
92 |
|
|
|
93 |
|
|
static int |
94 |
|
|
cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len) |
95 |
|
|
{ |
96 |
|
|
size_t newlen; |
97 |
|
|
|
98 |
✗✓ |
1214486 |
if (base == NULL) |
99 |
|
|
return 0; |
100 |
|
|
|
101 |
|
607243 |
newlen = base->len + len; |
102 |
✗✓ |
607243 |
if (newlen < base->len) |
103 |
|
|
/* Overflow */ |
104 |
|
|
return 0; |
105 |
|
|
|
106 |
✓✓ |
607243 |
if (newlen > base->cap) { |
107 |
|
1648 |
size_t newcap = base->cap * 2; |
108 |
|
|
uint8_t *newbuf; |
109 |
|
|
|
110 |
✓✓ |
1648 |
if (!base->can_resize) |
111 |
|
8 |
return 0; |
112 |
|
|
|
113 |
✓✗✓✓
|
3280 |
if (newcap < base->cap || newcap < newlen) |
114 |
|
240 |
newcap = newlen; |
115 |
|
|
|
116 |
|
1640 |
newbuf = recallocarray(base->buf, base->cap, newcap, 1); |
117 |
✗✓ |
1640 |
if (newbuf == NULL) |
118 |
|
|
return 0; |
119 |
|
|
|
120 |
|
1640 |
base->buf = newbuf; |
121 |
|
1640 |
base->cap = newcap; |
122 |
✓✓ |
1640 |
} |
123 |
|
|
|
124 |
✓✓ |
607235 |
if (out) |
125 |
|
606931 |
*out = base->buf + base->len; |
126 |
|
|
|
127 |
|
607235 |
base->len = newlen; |
128 |
|
607235 |
return 1; |
129 |
|
607243 |
} |
130 |
|
|
|
131 |
|
|
static int |
132 |
|
|
cbb_add_u(CBB *cbb, uint32_t v, size_t len_len) |
133 |
|
|
{ |
134 |
|
978908 |
uint8_t *buf; |
135 |
|
|
size_t i; |
136 |
|
|
|
137 |
✗✓ |
489454 |
if (len_len == 0) |
138 |
|
|
return 1; |
139 |
|
|
|
140 |
✗✓ |
489454 |
if (len_len > 4) |
141 |
|
|
return 0; |
142 |
|
|
|
143 |
✓✓✓✓
|
978896 |
if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len)) |
144 |
|
20 |
return 0; |
145 |
|
|
|
146 |
✓✓ |
2847772 |
for (i = len_len - 1; i < len_len; i--) { |
147 |
|
934452 |
buf[i] = v; |
148 |
|
934452 |
v >>= 8; |
149 |
|
|
} |
150 |
|
489434 |
return 1; |
151 |
|
489454 |
} |
152 |
|
|
|
153 |
|
|
int |
154 |
|
|
CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) |
155 |
|
|
{ |
156 |
✓✓ |
56960 |
if (!cbb->is_top_level) |
157 |
|
4 |
return 0; |
158 |
|
|
|
159 |
✗✓ |
28476 |
if (!CBB_flush(cbb)) |
160 |
|
|
return 0; |
161 |
|
|
|
162 |
✓✓✗✓
|
39964 |
if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) |
163 |
|
|
/* |
164 |
|
|
* |out_data| and |out_len| can only be NULL if the CBB is |
165 |
|
|
* fixed. |
166 |
|
|
*/ |
167 |
|
|
return 0; |
168 |
|
|
|
169 |
✓✓ |
28476 |
if (out_data != NULL) |
170 |
|
11496 |
*out_data = cbb->base->buf; |
171 |
|
|
|
172 |
✓✓ |
28476 |
if (out_len != NULL) |
173 |
|
28468 |
*out_len = cbb->base->len; |
174 |
|
|
|
175 |
|
28476 |
cbb->base->buf = NULL; |
176 |
|
28476 |
CBB_cleanup(cbb); |
177 |
|
28476 |
return 1; |
178 |
|
28480 |
} |
179 |
|
|
|
180 |
|
|
/* |
181 |
|
|
* CBB_flush recurses and then writes out any pending length prefix. The current |
182 |
|
|
* length of the underlying base is taken to be the length of the |
183 |
|
|
* length-prefixed data. |
184 |
|
|
*/ |
185 |
|
|
int |
186 |
|
|
CBB_flush(CBB *cbb) |
187 |
|
|
{ |
188 |
|
|
size_t child_start, i, len; |
189 |
|
|
|
190 |
✓✓ |
1573304 |
if (cbb->base == NULL) |
191 |
|
28 |
return 0; |
192 |
|
|
|
193 |
✓✓✗✓
|
878031 |
if (cbb->child == NULL || cbb->pending_len_len == 0) |
194 |
|
695217 |
return 1; |
195 |
|
|
|
196 |
|
91407 |
child_start = cbb->offset + cbb->pending_len_len; |
197 |
|
|
|
198 |
✓✗✓✗ ✗✓ |
274221 |
if (!CBB_flush(cbb->child) || child_start < cbb->offset || |
199 |
|
91407 |
cbb->base->len < child_start) |
200 |
|
|
return 0; |
201 |
|
|
|
202 |
|
91407 |
len = cbb->base->len - child_start; |
203 |
|
|
|
204 |
✓✓ |
91407 |
if (cbb->pending_is_asn1) { |
205 |
|
|
/* |
206 |
|
|
* For ASN.1, we assumed that we were using short form which |
207 |
|
|
* only requires a single byte for the length octet. |
208 |
|
|
* |
209 |
|
|
* If it turns out that we need long form, we have to move |
210 |
|
|
* the contents along in order to make space for more length |
211 |
|
|
* octets. |
212 |
|
|
*/ |
213 |
|
|
size_t len_len = 1; /* total number of length octets */ |
214 |
|
|
uint8_t initial_length_byte; |
215 |
|
|
|
216 |
|
|
/* We already wrote 1 byte for the length. */ |
217 |
✗✓ |
12260 |
assert (cbb->pending_len_len == 1); |
218 |
|
|
|
219 |
|
|
/* Check for long form */ |
220 |
✗✓ |
12260 |
if (len > 0xfffffffe) |
221 |
|
|
return 0; /* 0xffffffff is reserved */ |
222 |
✗✓ |
12260 |
else if (len > 0xffffff) |
223 |
|
|
len_len = 5; |
224 |
✓✓ |
12260 |
else if (len > 0xffff) |
225 |
|
8 |
len_len = 4; |
226 |
✓✓ |
12252 |
else if (len > 0xff) |
227 |
|
260 |
len_len = 3; |
228 |
✓✓ |
11992 |
else if (len > 0x7f) |
229 |
|
36 |
len_len = 2; |
230 |
|
|
|
231 |
✓✓ |
12260 |
if (len_len == 1) { |
232 |
|
|
/* For short form, the initial byte is the length. */ |
233 |
|
11956 |
initial_length_byte = len; |
234 |
|
|
len = 0; |
235 |
|
|
|
236 |
|
11956 |
} else { |
237 |
|
|
/* |
238 |
|
|
* For long form, the initial byte is the number of |
239 |
|
|
* subsequent length octets (plus bit 8 set). |
240 |
|
|
*/ |
241 |
|
304 |
initial_length_byte = 0x80 | (len_len - 1); |
242 |
|
|
|
243 |
|
|
/* |
244 |
|
|
* We need to move the contents along in order to make |
245 |
|
|
* space for the long form length octets. |
246 |
|
|
*/ |
247 |
|
|
size_t extra_bytes = len_len - 1; |
248 |
✗✓ |
304 |
if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) |
249 |
|
|
return 0; |
250 |
|
|
|
251 |
|
304 |
memmove(cbb->base->buf + child_start + extra_bytes, |
252 |
|
|
cbb->base->buf + child_start, len); |
253 |
✓✗ |
304 |
} |
254 |
|
12260 |
cbb->base->buf[cbb->offset++] = initial_length_byte; |
255 |
|
12260 |
cbb->pending_len_len = len_len - 1; |
256 |
✓✗ |
12260 |
} |
257 |
|
|
|
258 |
✓✓ |
502202 |
for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) { |
259 |
|
159694 |
cbb->base->buf[cbb->offset + i] = len; |
260 |
|
159694 |
len >>= 8; |
261 |
|
|
} |
262 |
✗✓ |
91407 |
if (len != 0) |
263 |
|
|
return 0; |
264 |
|
|
|
265 |
|
91407 |
cbb->child->base = NULL; |
266 |
|
91407 |
cbb->child = NULL; |
267 |
|
91407 |
cbb->pending_len_len = 0; |
268 |
|
91407 |
cbb->pending_is_asn1 = 0; |
269 |
|
91407 |
cbb->offset = 0; |
270 |
|
|
|
271 |
|
91407 |
return 1; |
272 |
|
786652 |
} |
273 |
|
|
|
274 |
|
|
|
275 |
|
|
static int |
276 |
|
|
cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len) |
277 |
|
|
{ |
278 |
|
158310 |
uint8_t *prefix_bytes; |
279 |
|
|
|
280 |
✓✓ |
79155 |
if (!CBB_flush(cbb)) |
281 |
|
8 |
return 0; |
282 |
|
|
|
283 |
|
79147 |
cbb->offset = cbb->base->len; |
284 |
✗✓ |
79147 |
if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) |
285 |
|
|
return 0; |
286 |
|
|
|
287 |
|
79147 |
memset(prefix_bytes, 0, len_len); |
288 |
|
79147 |
memset(out_contents, 0, sizeof(CBB)); |
289 |
|
79147 |
out_contents->base = cbb->base; |
290 |
|
79147 |
cbb->child = out_contents; |
291 |
|
79147 |
cbb->pending_len_len = len_len; |
292 |
|
79147 |
cbb->pending_is_asn1 = 0; |
293 |
|
|
|
294 |
|
79147 |
return 1; |
295 |
|
79155 |
} |
296 |
|
|
|
297 |
|
|
int |
298 |
|
|
CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) |
299 |
|
|
{ |
300 |
|
19896 |
return cbb_add_length_prefixed(cbb, out_contents, 1); |
301 |
|
|
} |
302 |
|
|
|
303 |
|
|
int |
304 |
|
|
CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) |
305 |
|
|
{ |
306 |
|
116886 |
return cbb_add_length_prefixed(cbb, out_contents, 2); |
307 |
|
|
} |
308 |
|
|
|
309 |
|
|
int |
310 |
|
|
CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) |
311 |
|
|
{ |
312 |
|
21528 |
return cbb_add_length_prefixed(cbb, out_contents, 3); |
313 |
|
|
} |
314 |
|
|
|
315 |
|
|
int |
316 |
|
|
CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag) |
317 |
|
|
{ |
318 |
✗✓ |
24560 |
if (tag > UINT8_MAX) |
319 |
|
|
return 0; |
320 |
|
|
|
321 |
|
|
/* Long form identifier octets are not supported. */ |
322 |
✗✓ |
12280 |
if ((tag & 0x1f) == 0x1f) |
323 |
|
|
return 0; |
324 |
|
|
|
325 |
|
|
/* Short-form identifier octet only needs a single byte */ |
326 |
✓✓✗✓
|
24556 |
if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag)) |
327 |
|
4 |
return 0; |
328 |
|
|
|
329 |
|
|
/* |
330 |
|
|
* Add 1 byte to cover the short-form length octet case. If it turns |
331 |
|
|
* out we need long-form, it will be extended later. |
332 |
|
|
*/ |
333 |
|
12276 |
cbb->offset = cbb->base->len; |
334 |
✗✓ |
12276 |
if (!CBB_add_u8(cbb, 0)) |
335 |
|
|
return 0; |
336 |
|
|
|
337 |
|
12276 |
memset(out_contents, 0, sizeof(CBB)); |
338 |
|
12276 |
out_contents->base = cbb->base; |
339 |
|
12276 |
cbb->child = out_contents; |
340 |
|
12276 |
cbb->pending_len_len = 1; |
341 |
|
12276 |
cbb->pending_is_asn1 = 1; |
342 |
|
|
|
343 |
|
12276 |
return 1; |
344 |
|
12280 |
} |
345 |
|
|
|
346 |
|
|
int |
347 |
|
|
CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) |
348 |
|
|
{ |
349 |
|
72518 |
uint8_t *dest; |
350 |
|
|
|
351 |
✓✓ |
36259 |
if (!CBB_add_space(cbb, &dest, len)) |
352 |
|
4 |
return 0; |
353 |
|
|
|
354 |
|
36255 |
memcpy(dest, data, len); |
355 |
|
36255 |
return 1; |
356 |
|
36259 |
} |
357 |
|
|
|
358 |
|
|
int |
359 |
|
|
CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) |
360 |
|
|
{ |
361 |
✓✓✗✓
|
115058 |
if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len)) |
362 |
|
4 |
return 0; |
363 |
|
|
|
364 |
|
38350 |
return 1; |
365 |
|
38354 |
} |
366 |
|
|
|
367 |
|
|
int |
368 |
|
|
CBB_add_u8(CBB *cbb, size_t value) |
369 |
|
|
{ |
370 |
✗✓ |
88872 |
if (value > UINT8_MAX) |
371 |
|
|
return 0; |
372 |
|
|
|
373 |
|
44436 |
return cbb_add_u(cbb, (uint32_t)value, 1); |
374 |
|
44436 |
} |
375 |
|
|
|
376 |
|
|
int |
377 |
|
|
CBB_add_u16(CBB *cbb, size_t value) |
378 |
|
|
{ |
379 |
✗✓ |
890012 |
if (value > UINT16_MAX) |
380 |
|
|
return 0; |
381 |
|
|
|
382 |
|
445006 |
return cbb_add_u(cbb, (uint32_t)value, 2); |
383 |
|
445006 |
} |
384 |
|
|
|
385 |
|
|
int |
386 |
|
|
CBB_add_u24(CBB *cbb, size_t value) |
387 |
|
|
{ |
388 |
✗✓ |
24 |
if (value > 0xffffffUL) |
389 |
|
|
return 0; |
390 |
|
|
|
391 |
|
12 |
return cbb_add_u(cbb, (uint32_t)value, 3); |
392 |
|
12 |
} |
393 |
|
|
|
394 |
|
|
int |
395 |
|
|
CBB_add_asn1_uint64(CBB *cbb, uint64_t value) |
396 |
|
|
{ |
397 |
|
8056 |
CBB child; |
398 |
|
|
size_t i; |
399 |
|
|
int started = 0; |
400 |
|
|
|
401 |
✗✓ |
4028 |
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) |
402 |
|
|
return 0; |
403 |
|
|
|
404 |
✓✓ |
72504 |
for (i = 0; i < 8; i++) { |
405 |
|
32224 |
uint8_t byte = (value >> 8 * (7 - i)) & 0xff; |
406 |
|
|
|
407 |
|
|
/* |
408 |
|
|
* ASN.1 restriction: first 9 bits cannot be all zeroes or |
409 |
|
|
* all ones. Since this function only encodes unsigned |
410 |
|
|
* integers, the only concerns are not encoding leading |
411 |
|
|
* zeros and adding a padding byte if necessary. |
412 |
|
|
* |
413 |
|
|
* In practice, this means: |
414 |
|
|
* 1) Skip leading octets of all zero bits in the value |
415 |
|
|
* 2) After skipping the leading zero octets, if the next 9 |
416 |
|
|
* bits are all ones, add an all zero prefix octet (and |
417 |
|
|
* set the high bit of the prefix octet if negative). |
418 |
|
|
* |
419 |
|
|
* Additionally, for an unsigned value, add an all zero |
420 |
|
|
* prefix if the high bit of the first octet would be one. |
421 |
|
|
*/ |
422 |
✓✓ |
32224 |
if (!started) { |
423 |
✓✓ |
27228 |
if (byte == 0) |
424 |
|
|
/* Don't encode leading zeros. */ |
425 |
|
23204 |
continue; |
426 |
|
|
|
427 |
|
|
/* |
428 |
|
|
* If the high bit is set, add a padding byte to make it |
429 |
|
|
* unsigned. |
430 |
|
|
*/ |
431 |
✓✓✗✓
|
4228 |
if ((byte & 0x80) && !CBB_add_u8(&child, 0)) |
432 |
|
|
return 0; |
433 |
|
|
|
434 |
|
|
started = 1; |
435 |
|
4024 |
} |
436 |
✗✓ |
9020 |
if (!CBB_add_u8(&child, byte)) |
437 |
|
|
return 0; |
438 |
✗✓✓ |
9020 |
} |
439 |
|
|
|
440 |
|
|
/* 0 is encoded as a single 0, not the empty string. */ |
441 |
✓✓✗✓
|
4032 |
if (!started && !CBB_add_u8(&child, 0)) |
442 |
|
|
return 0; |
443 |
|
|
|
444 |
|
4028 |
return CBB_flush(cbb); |
445 |
|
4028 |
} |