1 /* $OpenBSD: bs_cbb.c,v 1.17.4.1 2017/12/09 13:43:25 jsing Exp $ */
3 * Copyright (c) 2014, Google Inc.
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.
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. */
21 #include <openssl/opensslconf.h>
23 #include "bytestring.h"
25 #define CBB_INITIAL_SIZE 64
28 cbb_init(CBB
*cbb
, uint8_t *buf
, size_t cap
)
30 struct cbb_buffer_st
*base
;
32 base
= malloc(sizeof(struct cbb_buffer_st
));
42 cbb
->is_top_level
= 1;
48 CBB_init(CBB
*cbb
, size_t initial_capacity
)
52 memset(cbb
, 0, sizeof(*cbb
));
54 if (initial_capacity
== 0)
55 initial_capacity
= CBB_INITIAL_SIZE
;
57 if ((buf
= malloc(initial_capacity
)) == NULL
)
60 if (!cbb_init(cbb
, buf
, initial_capacity
)) {
69 CBB_init_fixed(CBB
*cbb
, uint8_t *buf
, size_t len
)
71 memset(cbb
, 0, sizeof(*cbb
));
73 if (!cbb_init(cbb
, buf
, len
))
76 cbb
->base
->can_resize
= 0;
85 if (cbb
->base
->can_resize
)
86 freezero(cbb
->base
->buf
, cbb
->base
->cap
);
94 cbb_buffer_add(struct cbb_buffer_st
*base
, uint8_t **out
, size_t len
)
101 newlen
= base
->len
+ len
;
102 if (newlen
< base
->len
)
106 if (newlen
> base
->cap
) {
107 size_t newcap
= base
->cap
* 2;
110 if (!base
->can_resize
)
113 if (newcap
< base
->cap
|| newcap
< newlen
)
116 newbuf
= recallocarray(base
->buf
, base
->cap
, newcap
, 1);
125 *out
= base
->buf
+ base
->len
;
132 cbb_add_u(CBB
*cbb
, uint32_t v
, size_t len_len
)
143 if (!CBB_flush(cbb
) || !cbb_buffer_add(cbb
->base
, &buf
, len_len
))
146 for (i
= len_len
- 1; i
< len_len
; i
--) {
154 CBB_finish(CBB
*cbb
, uint8_t **out_data
, size_t *out_len
)
156 if (!cbb
->is_top_level
)
162 if (cbb
->base
->can_resize
&& (out_data
== NULL
|| out_len
== NULL
))
164 * |out_data| and |out_len| can only be NULL if the CBB is
169 if (out_data
!= NULL
)
170 *out_data
= cbb
->base
->buf
;
173 *out_len
= cbb
->base
->len
;
175 cbb
->base
->buf
= NULL
;
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.
188 size_t child_start
, i
, len
;
190 if (cbb
->base
== NULL
)
193 if (cbb
->child
== NULL
|| cbb
->pending_len_len
== 0)
196 child_start
= cbb
->offset
+ cbb
->pending_len_len
;
198 if (!CBB_flush(cbb
->child
) || child_start
< cbb
->offset
||
199 cbb
->base
->len
< child_start
)
202 len
= cbb
->base
->len
- child_start
;
204 if (cbb
->pending_is_asn1
) {
206 * For ASN.1, we assumed that we were using short form which
207 * only requires a single byte for the length octet.
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
213 size_t len_len
= 1; /* total number of length octets */
214 uint8_t initial_length_byte
;
216 /* We already wrote 1 byte for the length. */
217 assert (cbb
->pending_len_len
== 1);
219 /* Check for long form */
220 if (len
> 0xfffffffe)
221 return 0; /* 0xffffffff is reserved */
222 else if (len
> 0xffffff)
224 else if (len
> 0xffff)
232 /* For short form, the initial byte is the length. */
233 initial_length_byte
= len
;
238 * For long form, the initial byte is the number of
239 * subsequent length octets (plus bit 8 set).
241 initial_length_byte
= 0x80 | (len_len
- 1);
244 * We need to move the contents along in order to make
245 * space for the long form length octets.
247 size_t extra_bytes
= len_len
- 1;
248 if (!cbb_buffer_add(cbb
->base
, NULL
, extra_bytes
))
251 memmove(cbb
->base
->buf
+ child_start
+ extra_bytes
,
252 cbb
->base
->buf
+ child_start
, len
);
254 cbb
->base
->buf
[cbb
->offset
++] = initial_length_byte
;
255 cbb
->pending_len_len
= len_len
- 1;
258 for (i
= cbb
->pending_len_len
- 1; i
< cbb
->pending_len_len
; i
--) {
259 cbb
->base
->buf
[cbb
->offset
+ i
] = len
;
265 cbb
->child
->base
= NULL
;
267 cbb
->pending_len_len
= 0;
268 cbb
->pending_is_asn1
= 0;
275 CBB_discard_child(CBB
*cbb
)
277 if (cbb
->child
== NULL
)
280 cbb
->base
->len
= cbb
->offset
;
282 cbb
->child
->base
= NULL
;
284 cbb
->pending_len_len
= 0;
285 cbb
->pending_is_asn1
= 0;
290 cbb_add_length_prefixed(CBB
*cbb
, CBB
*out_contents
, size_t len_len
)
292 uint8_t *prefix_bytes
;
297 cbb
->offset
= cbb
->base
->len
;
298 if (!cbb_buffer_add(cbb
->base
, &prefix_bytes
, len_len
))
301 memset(prefix_bytes
, 0, len_len
);
302 memset(out_contents
, 0, sizeof(CBB
));
303 out_contents
->base
= cbb
->base
;
304 cbb
->child
= out_contents
;
305 cbb
->pending_len_len
= len_len
;
306 cbb
->pending_is_asn1
= 0;
312 CBB_add_u8_length_prefixed(CBB
*cbb
, CBB
*out_contents
)
314 return cbb_add_length_prefixed(cbb
, out_contents
, 1);
318 CBB_add_u16_length_prefixed(CBB
*cbb
, CBB
*out_contents
)
320 return cbb_add_length_prefixed(cbb
, out_contents
, 2);
324 CBB_add_u24_length_prefixed(CBB
*cbb
, CBB
*out_contents
)
326 return cbb_add_length_prefixed(cbb
, out_contents
, 3);
330 CBB_add_asn1(CBB
*cbb
, CBB
*out_contents
, unsigned int tag
)
335 /* Long form identifier octets are not supported. */
336 if ((tag
& 0x1f) == 0x1f)
339 /* Short-form identifier octet only needs a single byte */
340 if (!CBB_flush(cbb
) || !CBB_add_u8(cbb
, tag
))
344 * Add 1 byte to cover the short-form length octet case. If it turns
345 * out we need long-form, it will be extended later.
347 cbb
->offset
= cbb
->base
->len
;
348 if (!CBB_add_u8(cbb
, 0))
351 memset(out_contents
, 0, sizeof(CBB
));
352 out_contents
->base
= cbb
->base
;
353 cbb
->child
= out_contents
;
354 cbb
->pending_len_len
= 1;
355 cbb
->pending_is_asn1
= 1;
361 CBB_add_bytes(CBB
*cbb
, const uint8_t *data
, size_t len
)
365 if (!CBB_add_space(cbb
, &dest
, len
))
368 memcpy(dest
, data
, len
);
373 CBB_add_space(CBB
*cbb
, uint8_t **out_data
, size_t len
)
375 if (!CBB_flush(cbb
) || !cbb_buffer_add(cbb
->base
, out_data
, len
))
382 CBB_add_u8(CBB
*cbb
, size_t value
)
384 if (value
> UINT8_MAX
)
387 return cbb_add_u(cbb
, (uint32_t)value
, 1);
391 CBB_add_u16(CBB
*cbb
, size_t value
)
393 if (value
> UINT16_MAX
)
396 return cbb_add_u(cbb
, (uint32_t)value
, 2);
400 CBB_add_u24(CBB
*cbb
, size_t value
)
402 if (value
> 0xffffffUL
)
405 return cbb_add_u(cbb
, (uint32_t)value
, 3);
409 CBB_add_asn1_uint64(CBB
*cbb
, uint64_t value
)
415 if (!CBB_add_asn1(cbb
, &child
, CBS_ASN1_INTEGER
))
418 for (i
= 0; i
< 8; i
++) {
419 uint8_t byte
= (value
>> 8 * (7 - i
)) & 0xff;
422 * ASN.1 restriction: first 9 bits cannot be all zeroes or
423 * all ones. Since this function only encodes unsigned
424 * integers, the only concerns are not encoding leading
425 * zeros and adding a padding byte if necessary.
427 * In practice, this means:
428 * 1) Skip leading octets of all zero bits in the value
429 * 2) After skipping the leading zero octets, if the next 9
430 * bits are all ones, add an all zero prefix octet (and
431 * set the high bit of the prefix octet if negative).
433 * Additionally, for an unsigned value, add an all zero
434 * prefix if the high bit of the first octet would be one.
438 /* Don't encode leading zeros. */
442 * If the high bit is set, add a padding byte to make it
445 if ((byte
& 0x80) && !CBB_add_u8(&child
, 0))
450 if (!CBB_add_u8(&child
, byte
))
454 /* 0 is encoded as a single 0, not the empty string. */
455 if (!started
&& !CBB_add_u8(&child
, 0))
458 return CBB_flush(cbb
);