1 /* $OpenBSD: bs_cbb.c,v 1.14 2017/03/10 15:16:20 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"
26 cbb_init(CBB
*cbb
, uint8_t *buf
, size_t cap
)
28 struct cbb_buffer_st
*base
;
30 base
= malloc(sizeof(struct cbb_buffer_st
));
40 cbb
->is_top_level
= 1;
46 CBB_init(CBB
*cbb
, size_t initial_capacity
)
50 memset(cbb
, 0, sizeof(*cbb
));
52 if (initial_capacity
> 0) {
53 if ((buf
= malloc(initial_capacity
)) == NULL
)
57 if (!cbb_init(cbb
, buf
, initial_capacity
)) {
66 CBB_init_fixed(CBB
*cbb
, uint8_t *buf
, size_t len
)
68 memset(cbb
, 0, sizeof(*cbb
));
70 if (!cbb_init(cbb
, buf
, len
))
73 cbb
->base
->can_resize
= 0;
82 if (cbb
->base
->can_resize
)
91 cbb_buffer_add(struct cbb_buffer_st
*base
, uint8_t **out
, size_t len
)
98 newlen
= base
->len
+ len
;
99 if (newlen
< base
->len
)
103 if (newlen
> base
->cap
) {
104 size_t newcap
= base
->cap
* 2;
107 if (!base
->can_resize
)
110 if (newcap
< base
->cap
|| newcap
< newlen
)
113 newbuf
= recallocarray(base
->buf
, base
->cap
, newcap
, 1);
122 *out
= base
->buf
+ base
->len
;
129 cbb_add_u(CBB
*cbb
, uint32_t v
, size_t len_len
)
140 if (!CBB_flush(cbb
) || !cbb_buffer_add(cbb
->base
, &buf
, len_len
))
143 for (i
= len_len
- 1; i
< len_len
; i
--) {
151 CBB_finish(CBB
*cbb
, uint8_t **out_data
, size_t *out_len
)
153 if (!cbb
->is_top_level
)
159 if (cbb
->base
->can_resize
&& (out_data
== NULL
|| out_len
== NULL
))
161 * |out_data| and |out_len| can only be NULL if the CBB is
166 if (out_data
!= NULL
)
167 *out_data
= cbb
->base
->buf
;
170 *out_len
= cbb
->base
->len
;
172 cbb
->base
->buf
= NULL
;
178 * CBB_flush recurses and then writes out any pending length prefix. The current
179 * length of the underlying base is taken to be the length of the
180 * length-prefixed data.
185 size_t child_start
, i
, len
;
187 if (cbb
->base
== NULL
)
190 if (cbb
->child
== NULL
|| cbb
->pending_len_len
== 0)
193 child_start
= cbb
->offset
+ cbb
->pending_len_len
;
195 if (!CBB_flush(cbb
->child
) || child_start
< cbb
->offset
||
196 cbb
->base
->len
< child_start
)
199 len
= cbb
->base
->len
- child_start
;
201 if (cbb
->pending_is_asn1
) {
203 * For ASN.1, we assumed that we were using short form which
204 * only requires a single byte for the length octet.
206 * If it turns out that we need long form, we have to move
207 * the contents along in order to make space for more length
210 size_t len_len
= 1; /* total number of length octets */
211 uint8_t initial_length_byte
;
213 /* We already wrote 1 byte for the length. */
214 assert (cbb
->pending_len_len
== 1);
216 /* Check for long form */
217 if (len
> 0xfffffffe)
218 return 0; /* 0xffffffff is reserved */
219 else if (len
> 0xffffff)
221 else if (len
> 0xffff)
229 /* For short form, the initial byte is the length. */
230 initial_length_byte
= len
;
235 * For long form, the initial byte is the number of
236 * subsequent length octets (plus bit 8 set).
238 initial_length_byte
= 0x80 | (len_len
- 1);
241 * We need to move the contents along in order to make
242 * space for the long form length octets.
244 size_t extra_bytes
= len_len
- 1;
245 if (!cbb_buffer_add(cbb
->base
, NULL
, extra_bytes
))
248 memmove(cbb
->base
->buf
+ child_start
+ extra_bytes
,
249 cbb
->base
->buf
+ child_start
, len
);
251 cbb
->base
->buf
[cbb
->offset
++] = initial_length_byte
;
252 cbb
->pending_len_len
= len_len
- 1;
255 for (i
= cbb
->pending_len_len
- 1; i
< cbb
->pending_len_len
; i
--) {
256 cbb
->base
->buf
[cbb
->offset
+ i
] = len
;
262 cbb
->child
->base
= NULL
;
264 cbb
->pending_len_len
= 0;
265 cbb
->pending_is_asn1
= 0;
273 cbb_add_length_prefixed(CBB
*cbb
, CBB
*out_contents
, size_t len_len
)
275 uint8_t *prefix_bytes
;
280 cbb
->offset
= cbb
->base
->len
;
281 if (!cbb_buffer_add(cbb
->base
, &prefix_bytes
, len_len
))
284 memset(prefix_bytes
, 0, len_len
);
285 memset(out_contents
, 0, sizeof(CBB
));
286 out_contents
->base
= cbb
->base
;
287 cbb
->child
= out_contents
;
288 cbb
->pending_len_len
= len_len
;
289 cbb
->pending_is_asn1
= 0;
295 CBB_add_u8_length_prefixed(CBB
*cbb
, CBB
*out_contents
)
297 return cbb_add_length_prefixed(cbb
, out_contents
, 1);
301 CBB_add_u16_length_prefixed(CBB
*cbb
, CBB
*out_contents
)
303 return cbb_add_length_prefixed(cbb
, out_contents
, 2);
307 CBB_add_u24_length_prefixed(CBB
*cbb
, CBB
*out_contents
)
309 return cbb_add_length_prefixed(cbb
, out_contents
, 3);
313 CBB_add_asn1(CBB
*cbb
, CBB
*out_contents
, unsigned int tag
)
318 /* Long form identifier octets are not supported. */
319 if ((tag
& 0x1f) == 0x1f)
322 /* Short-form identifier octet only needs a single byte */
323 if (!CBB_flush(cbb
) || !CBB_add_u8(cbb
, tag
))
327 * Add 1 byte to cover the short-form length octet case. If it turns
328 * out we need long-form, it will be extended later.
330 cbb
->offset
= cbb
->base
->len
;
331 if (!CBB_add_u8(cbb
, 0))
334 memset(out_contents
, 0, sizeof(CBB
));
335 out_contents
->base
= cbb
->base
;
336 cbb
->child
= out_contents
;
337 cbb
->pending_len_len
= 1;
338 cbb
->pending_is_asn1
= 1;
344 CBB_add_bytes(CBB
*cbb
, const uint8_t *data
, size_t len
)
348 if (!CBB_add_space(cbb
, &dest
, len
))
351 memcpy(dest
, data
, len
);
356 CBB_add_space(CBB
*cbb
, uint8_t **out_data
, size_t len
)
358 if (!CBB_flush(cbb
) || !cbb_buffer_add(cbb
->base
, out_data
, len
))
365 CBB_add_u8(CBB
*cbb
, size_t value
)
367 if (value
> UINT8_MAX
)
370 return cbb_add_u(cbb
, (uint32_t)value
, 1);
374 CBB_add_u16(CBB
*cbb
, size_t value
)
376 if (value
> UINT16_MAX
)
379 return cbb_add_u(cbb
, (uint32_t)value
, 2);
383 CBB_add_u24(CBB
*cbb
, size_t value
)
385 if (value
> 0xffffffUL
)
388 return cbb_add_u(cbb
, (uint32_t)value
, 3);
392 CBB_add_asn1_uint64(CBB
*cbb
, uint64_t value
)
398 if (!CBB_add_asn1(cbb
, &child
, CBS_ASN1_INTEGER
))
401 for (i
= 0; i
< 8; i
++) {
402 uint8_t byte
= (value
>> 8 * (7 - i
)) & 0xff;
405 * ASN.1 restriction: first 9 bits cannot be all zeroes or
406 * all ones. Since this function only encodes unsigned
407 * integers, the only concerns are not encoding leading
408 * zeros and adding a padding byte if necessary.
410 * In practice, this means:
411 * 1) Skip leading octets of all zero bits in the value
412 * 2) After skipping the leading zero octets, if the next 9
413 * bits are all ones, add an all zero prefix octet (and
414 * set the high bit of the prefix octet if negative).
416 * Additionally, for an unsigned value, add an all zero
417 * prefix if the high bit of the first octet would be one.
421 /* Don't encode leading zeros. */
425 * If the high bit is set, add a padding byte to make it
428 if ((byte
& 0x80) && !CBB_add_u8(&child
, 0))
433 if (!CBB_add_u8(&child
, byte
))
437 /* 0 is encoded as a single 0, not the empty string. */
438 if (!started
&& !CBB_add_u8(&child
, 0))
441 return CBB_flush(cbb
);