1*59f50346Sbeck /* $OpenBSD: bs_cbb.c,v 1.20 2019/01/23 22:20:40 beck Exp $ */ 2c4905cd3Sdoug /* 3c4905cd3Sdoug * Copyright (c) 2014, Google Inc. 4c4905cd3Sdoug * 5c4905cd3Sdoug * Permission to use, copy, modify, and/or distribute this software for any 6c4905cd3Sdoug * purpose with or without fee is hereby granted, provided that the above 7c4905cd3Sdoug * copyright notice and this permission notice appear in all copies. 8c4905cd3Sdoug * 9c4905cd3Sdoug * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10c4905cd3Sdoug * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11c4905cd3Sdoug * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 12c4905cd3Sdoug * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13c4905cd3Sdoug * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 14c4905cd3Sdoug * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15c4905cd3Sdoug * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 16c4905cd3Sdoug 17c4905cd3Sdoug #include <stdlib.h> 18c4905cd3Sdoug #include <string.h> 19c4905cd3Sdoug 20c4905cd3Sdoug #include <openssl/opensslconf.h> 21c4905cd3Sdoug 22c4905cd3Sdoug #include "bytestring.h" 23c4905cd3Sdoug 24c99575daSjsing #define CBB_INITIAL_SIZE 64 25c99575daSjsing 26732f1cb2Sdoug static int 27732f1cb2Sdoug cbb_init(CBB *cbb, uint8_t *buf, size_t cap) 28732f1cb2Sdoug { 29c4905cd3Sdoug struct cbb_buffer_st *base; 30c4905cd3Sdoug 31c4905cd3Sdoug base = malloc(sizeof(struct cbb_buffer_st)); 32d7a08d8fSdoug if (base == NULL) 33c4905cd3Sdoug return 0; 34c4905cd3Sdoug 35c4905cd3Sdoug base->buf = buf; 36c4905cd3Sdoug base->len = 0; 37c4905cd3Sdoug base->cap = cap; 38c4905cd3Sdoug base->can_resize = 1; 39c4905cd3Sdoug 40c4905cd3Sdoug cbb->base = base; 41c4905cd3Sdoug cbb->is_top_level = 1; 4228a1f398Sjsing 43c4905cd3Sdoug return 1; 44c4905cd3Sdoug } 45c4905cd3Sdoug 46732f1cb2Sdoug int 47732f1cb2Sdoug CBB_init(CBB *cbb, size_t initial_capacity) 48732f1cb2Sdoug { 493a0c64b9Sdoug uint8_t *buf = NULL; 50c4905cd3Sdoug 5128a1f398Sjsing memset(cbb, 0, sizeof(*cbb)); 5228a1f398Sjsing 53c99575daSjsing if (initial_capacity == 0) 54c99575daSjsing initial_capacity = CBB_INITIAL_SIZE; 55c99575daSjsing 563a0c64b9Sdoug if ((buf = malloc(initial_capacity)) == NULL) 57c4905cd3Sdoug return 0; 58c4905cd3Sdoug 5941724196Sdoug if (!cbb_init(cbb, buf, initial_capacity)) { 6041724196Sdoug free(buf); 6141724196Sdoug return 0; 6241724196Sdoug } 6328a1f398Sjsing 6441724196Sdoug return 1; 65c4905cd3Sdoug } 66c4905cd3Sdoug 67732f1cb2Sdoug int 68732f1cb2Sdoug CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) 69732f1cb2Sdoug { 7028a1f398Sjsing memset(cbb, 0, sizeof(*cbb)); 7128a1f398Sjsing 72732f1cb2Sdoug if (!cbb_init(cbb, buf, len)) 73c4905cd3Sdoug return 0; 74c4905cd3Sdoug 75c4905cd3Sdoug cbb->base->can_resize = 0; 7628a1f398Sjsing 77c4905cd3Sdoug return 1; 78c4905cd3Sdoug } 79c4905cd3Sdoug 80732f1cb2Sdoug void 81732f1cb2Sdoug CBB_cleanup(CBB *cbb) 82732f1cb2Sdoug { 83c4905cd3Sdoug if (cbb->base) { 843a0c64b9Sdoug if (cbb->base->can_resize) 852a6b7f1dSjsing freezero(cbb->base->buf, cbb->base->cap); 86c4905cd3Sdoug free(cbb->base); 87c4905cd3Sdoug } 88c4905cd3Sdoug cbb->base = NULL; 899234d803Sjsing cbb->child = NULL; 90c4905cd3Sdoug } 91c4905cd3Sdoug 92732f1cb2Sdoug static int 93732f1cb2Sdoug cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len) 94732f1cb2Sdoug { 95c4905cd3Sdoug size_t newlen; 96c4905cd3Sdoug 97732f1cb2Sdoug if (base == NULL) 98c4905cd3Sdoug return 0; 99c4905cd3Sdoug 100c4905cd3Sdoug newlen = base->len + len; 101732f1cb2Sdoug if (newlen < base->len) 102c4905cd3Sdoug /* Overflow */ 103c4905cd3Sdoug return 0; 104c4905cd3Sdoug 105c4905cd3Sdoug if (newlen > base->cap) { 106c4905cd3Sdoug size_t newcap = base->cap * 2; 107c4905cd3Sdoug uint8_t *newbuf; 108c4905cd3Sdoug 109732f1cb2Sdoug if (!base->can_resize) 110c4905cd3Sdoug return 0; 111c4905cd3Sdoug 112732f1cb2Sdoug if (newcap < base->cap || newcap < newlen) 113c4905cd3Sdoug newcap = newlen; 114732f1cb2Sdoug 11542ccf58dSjsing newbuf = recallocarray(base->buf, base->cap, newcap, 1); 116732f1cb2Sdoug if (newbuf == NULL) 117c4905cd3Sdoug return 0; 118c4905cd3Sdoug 119c4905cd3Sdoug base->buf = newbuf; 120c4905cd3Sdoug base->cap = newcap; 121c4905cd3Sdoug } 122c4905cd3Sdoug 123732f1cb2Sdoug if (out) 124c4905cd3Sdoug *out = base->buf + base->len; 125732f1cb2Sdoug 126c4905cd3Sdoug base->len = newlen; 127c4905cd3Sdoug return 1; 128c4905cd3Sdoug } 129c4905cd3Sdoug 130732f1cb2Sdoug static int 131f49f1317Sdoug cbb_add_u(CBB *cbb, uint32_t v, size_t len_len) 132732f1cb2Sdoug { 133c4905cd3Sdoug uint8_t *buf; 134c4905cd3Sdoug size_t i; 135c4905cd3Sdoug 136732f1cb2Sdoug if (len_len == 0) 137c4905cd3Sdoug return 1; 138732f1cb2Sdoug 139c2c0b151Sdoug if (len_len > 4) 140c2c0b151Sdoug return 0; 141c2c0b151Sdoug 142f49f1317Sdoug if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len)) 143c4905cd3Sdoug return 0; 144c4905cd3Sdoug 145c4905cd3Sdoug for (i = len_len - 1; i < len_len; i--) { 146c4905cd3Sdoug buf[i] = v; 147c4905cd3Sdoug v >>= 8; 148c4905cd3Sdoug } 149c4905cd3Sdoug return 1; 150c4905cd3Sdoug } 151c4905cd3Sdoug 152732f1cb2Sdoug int 153732f1cb2Sdoug CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) 154732f1cb2Sdoug { 155732f1cb2Sdoug if (!cbb->is_top_level) 156c4905cd3Sdoug return 0; 157c4905cd3Sdoug 158732f1cb2Sdoug if (!CBB_flush(cbb)) 159c4905cd3Sdoug return 0; 160c4905cd3Sdoug 161732f1cb2Sdoug if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) 162d7a08d8fSdoug /* 163d7a08d8fSdoug * |out_data| and |out_len| can only be NULL if the CBB is 164d7a08d8fSdoug * fixed. 165d7a08d8fSdoug */ 166c4905cd3Sdoug return 0; 167c4905cd3Sdoug 168732f1cb2Sdoug if (out_data != NULL) 169c4905cd3Sdoug *out_data = cbb->base->buf; 170732f1cb2Sdoug 171732f1cb2Sdoug if (out_len != NULL) 172c4905cd3Sdoug *out_len = cbb->base->len; 173732f1cb2Sdoug 174c4905cd3Sdoug cbb->base->buf = NULL; 175c4905cd3Sdoug CBB_cleanup(cbb); 176c4905cd3Sdoug return 1; 177c4905cd3Sdoug } 178c4905cd3Sdoug 179732f1cb2Sdoug /* 180732f1cb2Sdoug * CBB_flush recurses and then writes out any pending length prefix. The current 181732f1cb2Sdoug * length of the underlying base is taken to be the length of the 182732f1cb2Sdoug * length-prefixed data. 183732f1cb2Sdoug */ 184732f1cb2Sdoug int 185732f1cb2Sdoug CBB_flush(CBB *cbb) 186732f1cb2Sdoug { 187c4905cd3Sdoug size_t child_start, i, len; 188c4905cd3Sdoug 189732f1cb2Sdoug if (cbb->base == NULL) 190c4905cd3Sdoug return 0; 191c4905cd3Sdoug 192732f1cb2Sdoug if (cbb->child == NULL || cbb->pending_len_len == 0) 193c4905cd3Sdoug return 1; 194c4905cd3Sdoug 195c4905cd3Sdoug child_start = cbb->offset + cbb->pending_len_len; 196c4905cd3Sdoug 197732f1cb2Sdoug if (!CBB_flush(cbb->child) || child_start < cbb->offset || 198732f1cb2Sdoug cbb->base->len < child_start) 199c4905cd3Sdoug return 0; 200c4905cd3Sdoug 201c4905cd3Sdoug len = cbb->base->len - child_start; 202c4905cd3Sdoug 203c4905cd3Sdoug if (cbb->pending_is_asn1) { 204d7a08d8fSdoug /* 2056ea8e45cSdoug * For ASN.1, we assumed that we were using short form which 2066ea8e45cSdoug * only requires a single byte for the length octet. 2076ea8e45cSdoug * 2086ea8e45cSdoug * If it turns out that we need long form, we have to move 2096ea8e45cSdoug * the contents along in order to make space for more length 2106ea8e45cSdoug * octets. 211d7a08d8fSdoug */ 2126ea8e45cSdoug size_t len_len = 1; /* total number of length octets */ 213c4905cd3Sdoug uint8_t initial_length_byte; 214c4905cd3Sdoug 2156ea8e45cSdoug /* We already wrote 1 byte for the length. */ 216*59f50346Sbeck if (cbb->pending_len_len != 1) 217*59f50346Sbeck return 0; 218c4905cd3Sdoug 2196ea8e45cSdoug /* Check for long form */ 2206ea8e45cSdoug if (len > 0xfffffffe) 2216ea8e45cSdoug return 0; /* 0xffffffff is reserved */ 2226ea8e45cSdoug else if (len > 0xffffff) 223c4905cd3Sdoug len_len = 5; 2246ea8e45cSdoug else if (len > 0xffff) 225c4905cd3Sdoug len_len = 4; 2266ea8e45cSdoug else if (len > 0xff) 227c4905cd3Sdoug len_len = 3; 2286ea8e45cSdoug else if (len > 0x7f) 229c4905cd3Sdoug len_len = 2; 2306ea8e45cSdoug 2316ea8e45cSdoug if (len_len == 1) { 2326ea8e45cSdoug /* For short form, the initial byte is the length. */ 233c4905cd3Sdoug initial_length_byte = len; 234c4905cd3Sdoug len = 0; 235c4905cd3Sdoug 2366ea8e45cSdoug } else { 2376ea8e45cSdoug /* 2386ea8e45cSdoug * For long form, the initial byte is the number of 2396ea8e45cSdoug * subsequent length octets (plus bit 8 set). 2406ea8e45cSdoug */ 2416ea8e45cSdoug initial_length_byte = 0x80 | (len_len - 1); 2426ea8e45cSdoug 243d7a08d8fSdoug /* 244d7a08d8fSdoug * We need to move the contents along in order to make 2456ea8e45cSdoug * space for the long form length octets. 246d7a08d8fSdoug */ 247c4905cd3Sdoug size_t extra_bytes = len_len - 1; 248732f1cb2Sdoug if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) 249c4905cd3Sdoug return 0; 250732f1cb2Sdoug 251c4905cd3Sdoug memmove(cbb->base->buf + child_start + extra_bytes, 252c4905cd3Sdoug cbb->base->buf + child_start, len); 253c4905cd3Sdoug } 254c4905cd3Sdoug cbb->base->buf[cbb->offset++] = initial_length_byte; 255c4905cd3Sdoug cbb->pending_len_len = len_len - 1; 256c4905cd3Sdoug } 257c4905cd3Sdoug 258c4905cd3Sdoug for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) { 259c4905cd3Sdoug cbb->base->buf[cbb->offset + i] = len; 260c4905cd3Sdoug len >>= 8; 261c4905cd3Sdoug } 262732f1cb2Sdoug if (len != 0) 263c4905cd3Sdoug return 0; 264c4905cd3Sdoug 265c4905cd3Sdoug cbb->child->base = NULL; 266c4905cd3Sdoug cbb->child = NULL; 267c4905cd3Sdoug cbb->pending_len_len = 0; 268c4905cd3Sdoug cbb->pending_is_asn1 = 0; 269c4905cd3Sdoug cbb->offset = 0; 270c4905cd3Sdoug 271c4905cd3Sdoug return 1; 272c4905cd3Sdoug } 273c4905cd3Sdoug 274e87ff5aeSjsing void 275e87ff5aeSjsing CBB_discard_child(CBB *cbb) 276e87ff5aeSjsing { 277e87ff5aeSjsing if (cbb->child == NULL) 278e87ff5aeSjsing return; 279e87ff5aeSjsing 280e87ff5aeSjsing cbb->base->len = cbb->offset; 281e87ff5aeSjsing 282e87ff5aeSjsing cbb->child->base = NULL; 283e87ff5aeSjsing cbb->child = NULL; 284e87ff5aeSjsing cbb->pending_len_len = 0; 285e87ff5aeSjsing cbb->pending_is_asn1 = 0; 286e87ff5aeSjsing cbb->offset = 0; 287e87ff5aeSjsing } 288c4905cd3Sdoug 289732f1cb2Sdoug static int 290732f1cb2Sdoug cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len) 291732f1cb2Sdoug { 292c4905cd3Sdoug uint8_t *prefix_bytes; 293c4905cd3Sdoug 294732f1cb2Sdoug if (!CBB_flush(cbb)) 295c4905cd3Sdoug return 0; 296c4905cd3Sdoug 297c4905cd3Sdoug cbb->offset = cbb->base->len; 298732f1cb2Sdoug if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) 299c4905cd3Sdoug return 0; 300c4905cd3Sdoug 301c4905cd3Sdoug memset(prefix_bytes, 0, len_len); 302c4905cd3Sdoug memset(out_contents, 0, sizeof(CBB)); 303c4905cd3Sdoug out_contents->base = cbb->base; 304c4905cd3Sdoug cbb->child = out_contents; 305c4905cd3Sdoug cbb->pending_len_len = len_len; 306c4905cd3Sdoug cbb->pending_is_asn1 = 0; 307c4905cd3Sdoug 308c4905cd3Sdoug return 1; 309c4905cd3Sdoug } 310c4905cd3Sdoug 311732f1cb2Sdoug int 312732f1cb2Sdoug CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) 313732f1cb2Sdoug { 314c4905cd3Sdoug return cbb_add_length_prefixed(cbb, out_contents, 1); 315c4905cd3Sdoug } 316c4905cd3Sdoug 317732f1cb2Sdoug int 318732f1cb2Sdoug CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) 319732f1cb2Sdoug { 320c4905cd3Sdoug return cbb_add_length_prefixed(cbb, out_contents, 2); 321c4905cd3Sdoug } 322c4905cd3Sdoug 323732f1cb2Sdoug int 324732f1cb2Sdoug CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) 325732f1cb2Sdoug { 326c4905cd3Sdoug return cbb_add_length_prefixed(cbb, out_contents, 3); 327c4905cd3Sdoug } 328c4905cd3Sdoug 329732f1cb2Sdoug int 3309d4b5ca7Sdoug CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag) 331732f1cb2Sdoug { 3329d4b5ca7Sdoug if (tag > UINT8_MAX) 3339d4b5ca7Sdoug return 0; 3349d4b5ca7Sdoug 335d7a08d8fSdoug /* Long form identifier octets are not supported. */ 336d7a08d8fSdoug if ((tag & 0x1f) == 0x1f) 337d7a08d8fSdoug return 0; 338d7a08d8fSdoug 3396ea8e45cSdoug /* Short-form identifier octet only needs a single byte */ 340732f1cb2Sdoug if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag)) 341c4905cd3Sdoug return 0; 342c4905cd3Sdoug 3436ea8e45cSdoug /* 3446ea8e45cSdoug * Add 1 byte to cover the short-form length octet case. If it turns 3456ea8e45cSdoug * out we need long-form, it will be extended later. 3466ea8e45cSdoug */ 347c4905cd3Sdoug cbb->offset = cbb->base->len; 348732f1cb2Sdoug if (!CBB_add_u8(cbb, 0)) 349c4905cd3Sdoug return 0; 350c4905cd3Sdoug 351c4905cd3Sdoug memset(out_contents, 0, sizeof(CBB)); 352c4905cd3Sdoug out_contents->base = cbb->base; 353c4905cd3Sdoug cbb->child = out_contents; 354c4905cd3Sdoug cbb->pending_len_len = 1; 355c4905cd3Sdoug cbb->pending_is_asn1 = 1; 356c4905cd3Sdoug 357c4905cd3Sdoug return 1; 358c4905cd3Sdoug } 359c4905cd3Sdoug 360732f1cb2Sdoug int 361732f1cb2Sdoug CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) 362732f1cb2Sdoug { 363c4905cd3Sdoug uint8_t *dest; 364c4905cd3Sdoug 36518f8c184Sdoug if (!CBB_add_space(cbb, &dest, len)) 366c4905cd3Sdoug return 0; 367732f1cb2Sdoug 368c4905cd3Sdoug memcpy(dest, data, len); 369c4905cd3Sdoug return 1; 370c4905cd3Sdoug } 371c4905cd3Sdoug 372732f1cb2Sdoug int 373732f1cb2Sdoug CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) 374732f1cb2Sdoug { 375732f1cb2Sdoug if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len)) 376c4905cd3Sdoug return 0; 377732f1cb2Sdoug 378c4905cd3Sdoug return 1; 379c4905cd3Sdoug } 380c4905cd3Sdoug 381732f1cb2Sdoug int 3829d4b5ca7Sdoug CBB_add_u8(CBB *cbb, size_t value) 383732f1cb2Sdoug { 3849d4b5ca7Sdoug if (value > UINT8_MAX) 3859d4b5ca7Sdoug return 0; 3869d4b5ca7Sdoug 3879d4b5ca7Sdoug return cbb_add_u(cbb, (uint32_t)value, 1); 388c4905cd3Sdoug } 389c4905cd3Sdoug 390732f1cb2Sdoug int 3919d4b5ca7Sdoug CBB_add_u16(CBB *cbb, size_t value) 392732f1cb2Sdoug { 3939d4b5ca7Sdoug if (value > UINT16_MAX) 3949d4b5ca7Sdoug return 0; 3959d4b5ca7Sdoug 3969d4b5ca7Sdoug return cbb_add_u(cbb, (uint32_t)value, 2); 397c4905cd3Sdoug } 398c4905cd3Sdoug 399732f1cb2Sdoug int 4009d4b5ca7Sdoug CBB_add_u24(CBB *cbb, size_t value) 401732f1cb2Sdoug { 4029d4b5ca7Sdoug if (value > 0xffffffUL) 4039d4b5ca7Sdoug return 0; 4049d4b5ca7Sdoug 4059d4b5ca7Sdoug return cbb_add_u(cbb, (uint32_t)value, 3); 406c4905cd3Sdoug } 407c4905cd3Sdoug 408732f1cb2Sdoug int 409bd94b8a5Sjsing CBB_add_u32(CBB *cbb, size_t value) 410bd94b8a5Sjsing { 411bd94b8a5Sjsing if (value > 0xffffffffUL) 412bd94b8a5Sjsing return 0; 413bd94b8a5Sjsing 414bd94b8a5Sjsing return cbb_add_u(cbb, (uint32_t)value, 4); 415bd94b8a5Sjsing } 416bd94b8a5Sjsing 417bd94b8a5Sjsing int 418732f1cb2Sdoug CBB_add_asn1_uint64(CBB *cbb, uint64_t value) 419732f1cb2Sdoug { 420c4905cd3Sdoug CBB child; 421c4905cd3Sdoug size_t i; 422c4905cd3Sdoug int started = 0; 423c4905cd3Sdoug 424732f1cb2Sdoug if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) 425c4905cd3Sdoug return 0; 426c4905cd3Sdoug 427c4905cd3Sdoug for (i = 0; i < 8; i++) { 428c4905cd3Sdoug uint8_t byte = (value >> 8 * (7 - i)) & 0xff; 429debb3ac7Sdoug 430debb3ac7Sdoug /* 431debb3ac7Sdoug * ASN.1 restriction: first 9 bits cannot be all zeroes or 432debb3ac7Sdoug * all ones. Since this function only encodes unsigned 433debb3ac7Sdoug * integers, the only concerns are not encoding leading 434debb3ac7Sdoug * zeros and adding a padding byte if necessary. 435debb3ac7Sdoug * 436debb3ac7Sdoug * In practice, this means: 437debb3ac7Sdoug * 1) Skip leading octets of all zero bits in the value 438debb3ac7Sdoug * 2) After skipping the leading zero octets, if the next 9 439debb3ac7Sdoug * bits are all ones, add an all zero prefix octet (and 440debb3ac7Sdoug * set the high bit of the prefix octet if negative). 441debb3ac7Sdoug * 442debb3ac7Sdoug * Additionally, for an unsigned value, add an all zero 443debb3ac7Sdoug * prefix if the high bit of the first octet would be one. 444debb3ac7Sdoug */ 445c4905cd3Sdoug if (!started) { 446732f1cb2Sdoug if (byte == 0) 447c4905cd3Sdoug /* Don't encode leading zeros. */ 448c4905cd3Sdoug continue; 449732f1cb2Sdoug 450d7a08d8fSdoug /* 451d7a08d8fSdoug * If the high bit is set, add a padding byte to make it 452d7a08d8fSdoug * unsigned. 453d7a08d8fSdoug */ 454732f1cb2Sdoug if ((byte & 0x80) && !CBB_add_u8(&child, 0)) 455c4905cd3Sdoug return 0; 456732f1cb2Sdoug 457c4905cd3Sdoug started = 1; 458c4905cd3Sdoug } 459732f1cb2Sdoug if (!CBB_add_u8(&child, byte)) 460c4905cd3Sdoug return 0; 461c4905cd3Sdoug } 462c4905cd3Sdoug 463c4905cd3Sdoug /* 0 is encoded as a single 0, not the empty string. */ 464732f1cb2Sdoug if (!started && !CBB_add_u8(&child, 0)) 465c4905cd3Sdoug return 0; 466c4905cd3Sdoug 467c4905cd3Sdoug return CBB_flush(cbb); 468c4905cd3Sdoug } 469