1*42ccf58dSjsing /* $OpenBSD: bs_cbb.c,v 1.14 2017/03/10 15:16:20 jsing 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 <assert.h> 18c4905cd3Sdoug #include <stdlib.h> 19c4905cd3Sdoug #include <string.h> 20c4905cd3Sdoug 21c4905cd3Sdoug #include <openssl/opensslconf.h> 22c4905cd3Sdoug 23c4905cd3Sdoug #include "bytestring.h" 24c4905cd3Sdoug 25732f1cb2Sdoug static int 26732f1cb2Sdoug cbb_init(CBB *cbb, uint8_t *buf, size_t cap) 27732f1cb2Sdoug { 28c4905cd3Sdoug struct cbb_buffer_st *base; 29c4905cd3Sdoug 30c4905cd3Sdoug base = malloc(sizeof(struct cbb_buffer_st)); 31d7a08d8fSdoug if (base == NULL) 32c4905cd3Sdoug return 0; 33c4905cd3Sdoug 34c4905cd3Sdoug base->buf = buf; 35c4905cd3Sdoug base->len = 0; 36c4905cd3Sdoug base->cap = cap; 37c4905cd3Sdoug base->can_resize = 1; 38c4905cd3Sdoug 39c4905cd3Sdoug cbb->base = base; 40c4905cd3Sdoug cbb->is_top_level = 1; 4128a1f398Sjsing 42c4905cd3Sdoug return 1; 43c4905cd3Sdoug } 44c4905cd3Sdoug 45732f1cb2Sdoug int 46732f1cb2Sdoug CBB_init(CBB *cbb, size_t initial_capacity) 47732f1cb2Sdoug { 483a0c64b9Sdoug uint8_t *buf = NULL; 49c4905cd3Sdoug 5028a1f398Sjsing memset(cbb, 0, sizeof(*cbb)); 5128a1f398Sjsing 523a0c64b9Sdoug if (initial_capacity > 0) { 533a0c64b9Sdoug if ((buf = malloc(initial_capacity)) == NULL) 54c4905cd3Sdoug return 0; 553a0c64b9Sdoug } 56c4905cd3Sdoug 5741724196Sdoug if (!cbb_init(cbb, buf, initial_capacity)) { 5841724196Sdoug free(buf); 5941724196Sdoug return 0; 6041724196Sdoug } 6128a1f398Sjsing 6241724196Sdoug return 1; 63c4905cd3Sdoug } 64c4905cd3Sdoug 65732f1cb2Sdoug int 66732f1cb2Sdoug CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) 67732f1cb2Sdoug { 6828a1f398Sjsing memset(cbb, 0, sizeof(*cbb)); 6928a1f398Sjsing 70732f1cb2Sdoug if (!cbb_init(cbb, buf, len)) 71c4905cd3Sdoug return 0; 72c4905cd3Sdoug 73c4905cd3Sdoug cbb->base->can_resize = 0; 7428a1f398Sjsing 75c4905cd3Sdoug return 1; 76c4905cd3Sdoug } 77c4905cd3Sdoug 78732f1cb2Sdoug void 79732f1cb2Sdoug CBB_cleanup(CBB *cbb) 80732f1cb2Sdoug { 81c4905cd3Sdoug if (cbb->base) { 823a0c64b9Sdoug if (cbb->base->can_resize) 83c4905cd3Sdoug free(cbb->base->buf); 84732f1cb2Sdoug 85c4905cd3Sdoug free(cbb->base); 86c4905cd3Sdoug } 87c4905cd3Sdoug cbb->base = NULL; 88c4905cd3Sdoug } 89c4905cd3Sdoug 90732f1cb2Sdoug static int 91732f1cb2Sdoug cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len) 92732f1cb2Sdoug { 93c4905cd3Sdoug size_t newlen; 94c4905cd3Sdoug 95732f1cb2Sdoug if (base == NULL) 96c4905cd3Sdoug return 0; 97c4905cd3Sdoug 98c4905cd3Sdoug newlen = base->len + len; 99732f1cb2Sdoug if (newlen < base->len) 100c4905cd3Sdoug /* Overflow */ 101c4905cd3Sdoug return 0; 102c4905cd3Sdoug 103c4905cd3Sdoug if (newlen > base->cap) { 104c4905cd3Sdoug size_t newcap = base->cap * 2; 105c4905cd3Sdoug uint8_t *newbuf; 106c4905cd3Sdoug 107732f1cb2Sdoug if (!base->can_resize) 108c4905cd3Sdoug return 0; 109c4905cd3Sdoug 110732f1cb2Sdoug if (newcap < base->cap || newcap < newlen) 111c4905cd3Sdoug newcap = newlen; 112732f1cb2Sdoug 113*42ccf58dSjsing newbuf = recallocarray(base->buf, base->cap, newcap, 1); 114732f1cb2Sdoug if (newbuf == NULL) 115c4905cd3Sdoug return 0; 116c4905cd3Sdoug 117c4905cd3Sdoug base->buf = newbuf; 118c4905cd3Sdoug base->cap = newcap; 119c4905cd3Sdoug } 120c4905cd3Sdoug 121732f1cb2Sdoug if (out) 122c4905cd3Sdoug *out = base->buf + base->len; 123732f1cb2Sdoug 124c4905cd3Sdoug base->len = newlen; 125c4905cd3Sdoug return 1; 126c4905cd3Sdoug } 127c4905cd3Sdoug 128732f1cb2Sdoug static int 129f49f1317Sdoug cbb_add_u(CBB *cbb, uint32_t v, size_t len_len) 130732f1cb2Sdoug { 131c4905cd3Sdoug uint8_t *buf; 132c4905cd3Sdoug size_t i; 133c4905cd3Sdoug 134732f1cb2Sdoug if (len_len == 0) 135c4905cd3Sdoug return 1; 136732f1cb2Sdoug 137c2c0b151Sdoug if (len_len > 4) 138c2c0b151Sdoug return 0; 139c2c0b151Sdoug 140f49f1317Sdoug if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len)) 141c4905cd3Sdoug return 0; 142c4905cd3Sdoug 143c4905cd3Sdoug for (i = len_len - 1; i < len_len; i--) { 144c4905cd3Sdoug buf[i] = v; 145c4905cd3Sdoug v >>= 8; 146c4905cd3Sdoug } 147c4905cd3Sdoug return 1; 148c4905cd3Sdoug } 149c4905cd3Sdoug 150732f1cb2Sdoug int 151732f1cb2Sdoug CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) 152732f1cb2Sdoug { 153732f1cb2Sdoug if (!cbb->is_top_level) 154c4905cd3Sdoug return 0; 155c4905cd3Sdoug 156732f1cb2Sdoug if (!CBB_flush(cbb)) 157c4905cd3Sdoug return 0; 158c4905cd3Sdoug 159732f1cb2Sdoug if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) 160d7a08d8fSdoug /* 161d7a08d8fSdoug * |out_data| and |out_len| can only be NULL if the CBB is 162d7a08d8fSdoug * fixed. 163d7a08d8fSdoug */ 164c4905cd3Sdoug return 0; 165c4905cd3Sdoug 166732f1cb2Sdoug if (out_data != NULL) 167c4905cd3Sdoug *out_data = cbb->base->buf; 168732f1cb2Sdoug 169732f1cb2Sdoug if (out_len != NULL) 170c4905cd3Sdoug *out_len = cbb->base->len; 171732f1cb2Sdoug 172c4905cd3Sdoug cbb->base->buf = NULL; 173c4905cd3Sdoug CBB_cleanup(cbb); 174c4905cd3Sdoug return 1; 175c4905cd3Sdoug } 176c4905cd3Sdoug 177732f1cb2Sdoug /* 178732f1cb2Sdoug * CBB_flush recurses and then writes out any pending length prefix. The current 179732f1cb2Sdoug * length of the underlying base is taken to be the length of the 180732f1cb2Sdoug * length-prefixed data. 181732f1cb2Sdoug */ 182732f1cb2Sdoug int 183732f1cb2Sdoug CBB_flush(CBB *cbb) 184732f1cb2Sdoug { 185c4905cd3Sdoug size_t child_start, i, len; 186c4905cd3Sdoug 187732f1cb2Sdoug if (cbb->base == NULL) 188c4905cd3Sdoug return 0; 189c4905cd3Sdoug 190732f1cb2Sdoug if (cbb->child == NULL || cbb->pending_len_len == 0) 191c4905cd3Sdoug return 1; 192c4905cd3Sdoug 193c4905cd3Sdoug child_start = cbb->offset + cbb->pending_len_len; 194c4905cd3Sdoug 195732f1cb2Sdoug if (!CBB_flush(cbb->child) || child_start < cbb->offset || 196732f1cb2Sdoug cbb->base->len < child_start) 197c4905cd3Sdoug return 0; 198c4905cd3Sdoug 199c4905cd3Sdoug len = cbb->base->len - child_start; 200c4905cd3Sdoug 201c4905cd3Sdoug if (cbb->pending_is_asn1) { 202d7a08d8fSdoug /* 2036ea8e45cSdoug * For ASN.1, we assumed that we were using short form which 2046ea8e45cSdoug * only requires a single byte for the length octet. 2056ea8e45cSdoug * 2066ea8e45cSdoug * If it turns out that we need long form, we have to move 2076ea8e45cSdoug * the contents along in order to make space for more length 2086ea8e45cSdoug * octets. 209d7a08d8fSdoug */ 2106ea8e45cSdoug size_t len_len = 1; /* total number of length octets */ 211c4905cd3Sdoug uint8_t initial_length_byte; 212c4905cd3Sdoug 2136ea8e45cSdoug /* We already wrote 1 byte for the length. */ 214c4905cd3Sdoug assert (cbb->pending_len_len == 1); 215c4905cd3Sdoug 2166ea8e45cSdoug /* Check for long form */ 2176ea8e45cSdoug if (len > 0xfffffffe) 2186ea8e45cSdoug return 0; /* 0xffffffff is reserved */ 2196ea8e45cSdoug else if (len > 0xffffff) 220c4905cd3Sdoug len_len = 5; 2216ea8e45cSdoug else if (len > 0xffff) 222c4905cd3Sdoug len_len = 4; 2236ea8e45cSdoug else if (len > 0xff) 224c4905cd3Sdoug len_len = 3; 2256ea8e45cSdoug else if (len > 0x7f) 226c4905cd3Sdoug len_len = 2; 2276ea8e45cSdoug 2286ea8e45cSdoug if (len_len == 1) { 2296ea8e45cSdoug /* For short form, the initial byte is the length. */ 230c4905cd3Sdoug initial_length_byte = len; 231c4905cd3Sdoug len = 0; 232c4905cd3Sdoug 2336ea8e45cSdoug } else { 2346ea8e45cSdoug /* 2356ea8e45cSdoug * For long form, the initial byte is the number of 2366ea8e45cSdoug * subsequent length octets (plus bit 8 set). 2376ea8e45cSdoug */ 2386ea8e45cSdoug initial_length_byte = 0x80 | (len_len - 1); 2396ea8e45cSdoug 240d7a08d8fSdoug /* 241d7a08d8fSdoug * We need to move the contents along in order to make 2426ea8e45cSdoug * space for the long form length octets. 243d7a08d8fSdoug */ 244c4905cd3Sdoug size_t extra_bytes = len_len - 1; 245732f1cb2Sdoug if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) 246c4905cd3Sdoug return 0; 247732f1cb2Sdoug 248c4905cd3Sdoug memmove(cbb->base->buf + child_start + extra_bytes, 249c4905cd3Sdoug cbb->base->buf + child_start, len); 250c4905cd3Sdoug } 251c4905cd3Sdoug cbb->base->buf[cbb->offset++] = initial_length_byte; 252c4905cd3Sdoug cbb->pending_len_len = len_len - 1; 253c4905cd3Sdoug } 254c4905cd3Sdoug 255c4905cd3Sdoug for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) { 256c4905cd3Sdoug cbb->base->buf[cbb->offset + i] = len; 257c4905cd3Sdoug len >>= 8; 258c4905cd3Sdoug } 259732f1cb2Sdoug if (len != 0) 260c4905cd3Sdoug return 0; 261c4905cd3Sdoug 262c4905cd3Sdoug cbb->child->base = NULL; 263c4905cd3Sdoug cbb->child = NULL; 264c4905cd3Sdoug cbb->pending_len_len = 0; 265c4905cd3Sdoug cbb->pending_is_asn1 = 0; 266c4905cd3Sdoug cbb->offset = 0; 267c4905cd3Sdoug 268c4905cd3Sdoug return 1; 269c4905cd3Sdoug } 270c4905cd3Sdoug 271c4905cd3Sdoug 272732f1cb2Sdoug static int 273732f1cb2Sdoug cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len) 274732f1cb2Sdoug { 275c4905cd3Sdoug uint8_t *prefix_bytes; 276c4905cd3Sdoug 277732f1cb2Sdoug if (!CBB_flush(cbb)) 278c4905cd3Sdoug return 0; 279c4905cd3Sdoug 280c4905cd3Sdoug cbb->offset = cbb->base->len; 281732f1cb2Sdoug if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) 282c4905cd3Sdoug return 0; 283c4905cd3Sdoug 284c4905cd3Sdoug memset(prefix_bytes, 0, len_len); 285c4905cd3Sdoug memset(out_contents, 0, sizeof(CBB)); 286c4905cd3Sdoug out_contents->base = cbb->base; 287c4905cd3Sdoug cbb->child = out_contents; 288c4905cd3Sdoug cbb->pending_len_len = len_len; 289c4905cd3Sdoug cbb->pending_is_asn1 = 0; 290c4905cd3Sdoug 291c4905cd3Sdoug return 1; 292c4905cd3Sdoug } 293c4905cd3Sdoug 294732f1cb2Sdoug int 295732f1cb2Sdoug CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) 296732f1cb2Sdoug { 297c4905cd3Sdoug return cbb_add_length_prefixed(cbb, out_contents, 1); 298c4905cd3Sdoug } 299c4905cd3Sdoug 300732f1cb2Sdoug int 301732f1cb2Sdoug CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) 302732f1cb2Sdoug { 303c4905cd3Sdoug return cbb_add_length_prefixed(cbb, out_contents, 2); 304c4905cd3Sdoug } 305c4905cd3Sdoug 306732f1cb2Sdoug int 307732f1cb2Sdoug CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) 308732f1cb2Sdoug { 309c4905cd3Sdoug return cbb_add_length_prefixed(cbb, out_contents, 3); 310c4905cd3Sdoug } 311c4905cd3Sdoug 312732f1cb2Sdoug int 3139d4b5ca7Sdoug CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag) 314732f1cb2Sdoug { 3159d4b5ca7Sdoug if (tag > UINT8_MAX) 3169d4b5ca7Sdoug return 0; 3179d4b5ca7Sdoug 318d7a08d8fSdoug /* Long form identifier octets are not supported. */ 319d7a08d8fSdoug if ((tag & 0x1f) == 0x1f) 320d7a08d8fSdoug return 0; 321d7a08d8fSdoug 3226ea8e45cSdoug /* Short-form identifier octet only needs a single byte */ 323732f1cb2Sdoug if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag)) 324c4905cd3Sdoug return 0; 325c4905cd3Sdoug 3266ea8e45cSdoug /* 3276ea8e45cSdoug * Add 1 byte to cover the short-form length octet case. If it turns 3286ea8e45cSdoug * out we need long-form, it will be extended later. 3296ea8e45cSdoug */ 330c4905cd3Sdoug cbb->offset = cbb->base->len; 331732f1cb2Sdoug if (!CBB_add_u8(cbb, 0)) 332c4905cd3Sdoug return 0; 333c4905cd3Sdoug 334c4905cd3Sdoug memset(out_contents, 0, sizeof(CBB)); 335c4905cd3Sdoug out_contents->base = cbb->base; 336c4905cd3Sdoug cbb->child = out_contents; 337c4905cd3Sdoug cbb->pending_len_len = 1; 338c4905cd3Sdoug cbb->pending_is_asn1 = 1; 339c4905cd3Sdoug 340c4905cd3Sdoug return 1; 341c4905cd3Sdoug } 342c4905cd3Sdoug 343732f1cb2Sdoug int 344732f1cb2Sdoug CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) 345732f1cb2Sdoug { 346c4905cd3Sdoug uint8_t *dest; 347c4905cd3Sdoug 34818f8c184Sdoug if (!CBB_add_space(cbb, &dest, len)) 349c4905cd3Sdoug return 0; 350732f1cb2Sdoug 351c4905cd3Sdoug memcpy(dest, data, len); 352c4905cd3Sdoug return 1; 353c4905cd3Sdoug } 354c4905cd3Sdoug 355732f1cb2Sdoug int 356732f1cb2Sdoug CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) 357732f1cb2Sdoug { 358732f1cb2Sdoug if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len)) 359c4905cd3Sdoug return 0; 360732f1cb2Sdoug 361c4905cd3Sdoug return 1; 362c4905cd3Sdoug } 363c4905cd3Sdoug 364732f1cb2Sdoug int 3659d4b5ca7Sdoug CBB_add_u8(CBB *cbb, size_t value) 366732f1cb2Sdoug { 3679d4b5ca7Sdoug if (value > UINT8_MAX) 3689d4b5ca7Sdoug return 0; 3699d4b5ca7Sdoug 3709d4b5ca7Sdoug return cbb_add_u(cbb, (uint32_t)value, 1); 371c4905cd3Sdoug } 372c4905cd3Sdoug 373732f1cb2Sdoug int 3749d4b5ca7Sdoug CBB_add_u16(CBB *cbb, size_t value) 375732f1cb2Sdoug { 3769d4b5ca7Sdoug if (value > UINT16_MAX) 3779d4b5ca7Sdoug return 0; 3789d4b5ca7Sdoug 3799d4b5ca7Sdoug return cbb_add_u(cbb, (uint32_t)value, 2); 380c4905cd3Sdoug } 381c4905cd3Sdoug 382732f1cb2Sdoug int 3839d4b5ca7Sdoug CBB_add_u24(CBB *cbb, size_t value) 384732f1cb2Sdoug { 3859d4b5ca7Sdoug if (value > 0xffffffUL) 3869d4b5ca7Sdoug return 0; 3879d4b5ca7Sdoug 3889d4b5ca7Sdoug return cbb_add_u(cbb, (uint32_t)value, 3); 389c4905cd3Sdoug } 390c4905cd3Sdoug 391732f1cb2Sdoug int 392732f1cb2Sdoug CBB_add_asn1_uint64(CBB *cbb, uint64_t value) 393732f1cb2Sdoug { 394c4905cd3Sdoug CBB child; 395c4905cd3Sdoug size_t i; 396c4905cd3Sdoug int started = 0; 397c4905cd3Sdoug 398732f1cb2Sdoug if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) 399c4905cd3Sdoug return 0; 400c4905cd3Sdoug 401c4905cd3Sdoug for (i = 0; i < 8; i++) { 402c4905cd3Sdoug uint8_t byte = (value >> 8 * (7 - i)) & 0xff; 403debb3ac7Sdoug 404debb3ac7Sdoug /* 405debb3ac7Sdoug * ASN.1 restriction: first 9 bits cannot be all zeroes or 406debb3ac7Sdoug * all ones. Since this function only encodes unsigned 407debb3ac7Sdoug * integers, the only concerns are not encoding leading 408debb3ac7Sdoug * zeros and adding a padding byte if necessary. 409debb3ac7Sdoug * 410debb3ac7Sdoug * In practice, this means: 411debb3ac7Sdoug * 1) Skip leading octets of all zero bits in the value 412debb3ac7Sdoug * 2) After skipping the leading zero octets, if the next 9 413debb3ac7Sdoug * bits are all ones, add an all zero prefix octet (and 414debb3ac7Sdoug * set the high bit of the prefix octet if negative). 415debb3ac7Sdoug * 416debb3ac7Sdoug * Additionally, for an unsigned value, add an all zero 417debb3ac7Sdoug * prefix if the high bit of the first octet would be one. 418debb3ac7Sdoug */ 419c4905cd3Sdoug if (!started) { 420732f1cb2Sdoug if (byte == 0) 421c4905cd3Sdoug /* Don't encode leading zeros. */ 422c4905cd3Sdoug continue; 423732f1cb2Sdoug 424d7a08d8fSdoug /* 425d7a08d8fSdoug * If the high bit is set, add a padding byte to make it 426d7a08d8fSdoug * unsigned. 427d7a08d8fSdoug */ 428732f1cb2Sdoug if ((byte & 0x80) && !CBB_add_u8(&child, 0)) 429c4905cd3Sdoug return 0; 430732f1cb2Sdoug 431c4905cd3Sdoug started = 1; 432c4905cd3Sdoug } 433732f1cb2Sdoug if (!CBB_add_u8(&child, byte)) 434c4905cd3Sdoug return 0; 435c4905cd3Sdoug } 436c4905cd3Sdoug 437c4905cd3Sdoug /* 0 is encoded as a single 0, not the empty string. */ 438732f1cb2Sdoug if (!started && !CBB_add_u8(&child, 0)) 439c4905cd3Sdoug return 0; 440c4905cd3Sdoug 441c4905cd3Sdoug return CBB_flush(cbb); 442c4905cd3Sdoug } 443