1*9d4b5ca7Sdoug /* $OpenBSD: bs_cbb.c,v 1.12 2015/06/18 23:25:07 doug 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 393a0c64b9Sdoug memset(cbb, 0, sizeof(*cbb)); 40c4905cd3Sdoug cbb->base = base; 41c4905cd3Sdoug cbb->is_top_level = 1; 42c4905cd3Sdoug return 1; 43c4905cd3Sdoug } 44c4905cd3Sdoug 45732f1cb2Sdoug int 46732f1cb2Sdoug CBB_init(CBB *cbb, size_t initial_capacity) 47732f1cb2Sdoug { 483a0c64b9Sdoug uint8_t *buf = NULL; 49c4905cd3Sdoug 503a0c64b9Sdoug if (initial_capacity > 0) { 513a0c64b9Sdoug if ((buf = malloc(initial_capacity)) == NULL) 52c4905cd3Sdoug return 0; 533a0c64b9Sdoug } 54c4905cd3Sdoug 5541724196Sdoug if (!cbb_init(cbb, buf, initial_capacity)) { 5641724196Sdoug free(buf); 5741724196Sdoug return 0; 5841724196Sdoug } 5941724196Sdoug return 1; 60c4905cd3Sdoug } 61c4905cd3Sdoug 62732f1cb2Sdoug int 63732f1cb2Sdoug CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) 64732f1cb2Sdoug { 65732f1cb2Sdoug if (!cbb_init(cbb, buf, len)) 66c4905cd3Sdoug return 0; 67c4905cd3Sdoug 68c4905cd3Sdoug cbb->base->can_resize = 0; 69c4905cd3Sdoug return 1; 70c4905cd3Sdoug } 71c4905cd3Sdoug 72732f1cb2Sdoug void 73732f1cb2Sdoug CBB_cleanup(CBB *cbb) 74732f1cb2Sdoug { 75c4905cd3Sdoug if (cbb->base) { 763a0c64b9Sdoug if (cbb->base->can_resize) 77c4905cd3Sdoug free(cbb->base->buf); 78732f1cb2Sdoug 79c4905cd3Sdoug free(cbb->base); 80c4905cd3Sdoug } 81c4905cd3Sdoug cbb->base = NULL; 82c4905cd3Sdoug } 83c4905cd3Sdoug 84732f1cb2Sdoug static int 85732f1cb2Sdoug cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len) 86732f1cb2Sdoug { 87c4905cd3Sdoug size_t newlen; 88c4905cd3Sdoug 89732f1cb2Sdoug if (base == NULL) 90c4905cd3Sdoug return 0; 91c4905cd3Sdoug 92c4905cd3Sdoug newlen = base->len + len; 93732f1cb2Sdoug if (newlen < base->len) 94c4905cd3Sdoug /* Overflow */ 95c4905cd3Sdoug return 0; 96c4905cd3Sdoug 97c4905cd3Sdoug if (newlen > base->cap) { 98c4905cd3Sdoug size_t newcap = base->cap * 2; 99c4905cd3Sdoug uint8_t *newbuf; 100c4905cd3Sdoug 101732f1cb2Sdoug if (!base->can_resize) 102c4905cd3Sdoug return 0; 103c4905cd3Sdoug 104732f1cb2Sdoug if (newcap < base->cap || newcap < newlen) 105c4905cd3Sdoug newcap = newlen; 106732f1cb2Sdoug 107c4905cd3Sdoug newbuf = realloc(base->buf, newcap); 108732f1cb2Sdoug if (newbuf == NULL) 109c4905cd3Sdoug return 0; 110c4905cd3Sdoug 111c4905cd3Sdoug base->buf = newbuf; 112c4905cd3Sdoug base->cap = newcap; 113c4905cd3Sdoug } 114c4905cd3Sdoug 115732f1cb2Sdoug if (out) 116c4905cd3Sdoug *out = base->buf + base->len; 117732f1cb2Sdoug 118c4905cd3Sdoug base->len = newlen; 119c4905cd3Sdoug return 1; 120c4905cd3Sdoug } 121c4905cd3Sdoug 122732f1cb2Sdoug static int 123f49f1317Sdoug cbb_add_u(CBB *cbb, uint32_t v, size_t len_len) 124732f1cb2Sdoug { 125c4905cd3Sdoug uint8_t *buf; 126c4905cd3Sdoug size_t i; 127c4905cd3Sdoug 128732f1cb2Sdoug if (len_len == 0) 129c4905cd3Sdoug return 1; 130732f1cb2Sdoug 131c2c0b151Sdoug if (len_len > 4) 132c2c0b151Sdoug return 0; 133c2c0b151Sdoug 134f49f1317Sdoug if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len)) 135c4905cd3Sdoug return 0; 136c4905cd3Sdoug 137c4905cd3Sdoug for (i = len_len - 1; i < len_len; i--) { 138c4905cd3Sdoug buf[i] = v; 139c4905cd3Sdoug v >>= 8; 140c4905cd3Sdoug } 141c4905cd3Sdoug return 1; 142c4905cd3Sdoug } 143c4905cd3Sdoug 144732f1cb2Sdoug int 145732f1cb2Sdoug CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) 146732f1cb2Sdoug { 147732f1cb2Sdoug if (!cbb->is_top_level) 148c4905cd3Sdoug return 0; 149c4905cd3Sdoug 150732f1cb2Sdoug if (!CBB_flush(cbb)) 151c4905cd3Sdoug return 0; 152c4905cd3Sdoug 153732f1cb2Sdoug if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) 154d7a08d8fSdoug /* 155d7a08d8fSdoug * |out_data| and |out_len| can only be NULL if the CBB is 156d7a08d8fSdoug * fixed. 157d7a08d8fSdoug */ 158c4905cd3Sdoug return 0; 159c4905cd3Sdoug 160732f1cb2Sdoug if (out_data != NULL) 161c4905cd3Sdoug *out_data = cbb->base->buf; 162732f1cb2Sdoug 163732f1cb2Sdoug if (out_len != NULL) 164c4905cd3Sdoug *out_len = cbb->base->len; 165732f1cb2Sdoug 166c4905cd3Sdoug cbb->base->buf = NULL; 167c4905cd3Sdoug CBB_cleanup(cbb); 168c4905cd3Sdoug return 1; 169c4905cd3Sdoug } 170c4905cd3Sdoug 171732f1cb2Sdoug /* 172732f1cb2Sdoug * CBB_flush recurses and then writes out any pending length prefix. The current 173732f1cb2Sdoug * length of the underlying base is taken to be the length of the 174732f1cb2Sdoug * length-prefixed data. 175732f1cb2Sdoug */ 176732f1cb2Sdoug int 177732f1cb2Sdoug CBB_flush(CBB *cbb) 178732f1cb2Sdoug { 179c4905cd3Sdoug size_t child_start, i, len; 180c4905cd3Sdoug 181732f1cb2Sdoug if (cbb->base == NULL) 182c4905cd3Sdoug return 0; 183c4905cd3Sdoug 184732f1cb2Sdoug if (cbb->child == NULL || cbb->pending_len_len == 0) 185c4905cd3Sdoug return 1; 186c4905cd3Sdoug 187c4905cd3Sdoug child_start = cbb->offset + cbb->pending_len_len; 188c4905cd3Sdoug 189732f1cb2Sdoug if (!CBB_flush(cbb->child) || child_start < cbb->offset || 190732f1cb2Sdoug cbb->base->len < child_start) 191c4905cd3Sdoug return 0; 192c4905cd3Sdoug 193c4905cd3Sdoug len = cbb->base->len - child_start; 194c4905cd3Sdoug 195c4905cd3Sdoug if (cbb->pending_is_asn1) { 196d7a08d8fSdoug /* 1976ea8e45cSdoug * For ASN.1, we assumed that we were using short form which 1986ea8e45cSdoug * only requires a single byte for the length octet. 1996ea8e45cSdoug * 2006ea8e45cSdoug * If it turns out that we need long form, we have to move 2016ea8e45cSdoug * the contents along in order to make space for more length 2026ea8e45cSdoug * octets. 203d7a08d8fSdoug */ 2046ea8e45cSdoug size_t len_len = 1; /* total number of length octets */ 205c4905cd3Sdoug uint8_t initial_length_byte; 206c4905cd3Sdoug 2076ea8e45cSdoug /* We already wrote 1 byte for the length. */ 208c4905cd3Sdoug assert (cbb->pending_len_len == 1); 209c4905cd3Sdoug 2106ea8e45cSdoug /* Check for long form */ 2116ea8e45cSdoug if (len > 0xfffffffe) 2126ea8e45cSdoug return 0; /* 0xffffffff is reserved */ 2136ea8e45cSdoug else if (len > 0xffffff) 214c4905cd3Sdoug len_len = 5; 2156ea8e45cSdoug else if (len > 0xffff) 216c4905cd3Sdoug len_len = 4; 2176ea8e45cSdoug else if (len > 0xff) 218c4905cd3Sdoug len_len = 3; 2196ea8e45cSdoug else if (len > 0x7f) 220c4905cd3Sdoug len_len = 2; 2216ea8e45cSdoug 2226ea8e45cSdoug if (len_len == 1) { 2236ea8e45cSdoug /* For short form, the initial byte is the length. */ 224c4905cd3Sdoug initial_length_byte = len; 225c4905cd3Sdoug len = 0; 226c4905cd3Sdoug 2276ea8e45cSdoug } else { 2286ea8e45cSdoug /* 2296ea8e45cSdoug * For long form, the initial byte is the number of 2306ea8e45cSdoug * subsequent length octets (plus bit 8 set). 2316ea8e45cSdoug */ 2326ea8e45cSdoug initial_length_byte = 0x80 | (len_len - 1); 2336ea8e45cSdoug 234d7a08d8fSdoug /* 235d7a08d8fSdoug * We need to move the contents along in order to make 2366ea8e45cSdoug * space for the long form length octets. 237d7a08d8fSdoug */ 238c4905cd3Sdoug size_t extra_bytes = len_len - 1; 239732f1cb2Sdoug if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) 240c4905cd3Sdoug return 0; 241732f1cb2Sdoug 242c4905cd3Sdoug memmove(cbb->base->buf + child_start + extra_bytes, 243c4905cd3Sdoug cbb->base->buf + child_start, len); 244c4905cd3Sdoug } 245c4905cd3Sdoug cbb->base->buf[cbb->offset++] = initial_length_byte; 246c4905cd3Sdoug cbb->pending_len_len = len_len - 1; 247c4905cd3Sdoug } 248c4905cd3Sdoug 249c4905cd3Sdoug for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) { 250c4905cd3Sdoug cbb->base->buf[cbb->offset + i] = len; 251c4905cd3Sdoug len >>= 8; 252c4905cd3Sdoug } 253732f1cb2Sdoug if (len != 0) 254c4905cd3Sdoug return 0; 255c4905cd3Sdoug 256c4905cd3Sdoug cbb->child->base = NULL; 257c4905cd3Sdoug cbb->child = NULL; 258c4905cd3Sdoug cbb->pending_len_len = 0; 259c4905cd3Sdoug cbb->pending_is_asn1 = 0; 260c4905cd3Sdoug cbb->offset = 0; 261c4905cd3Sdoug 262c4905cd3Sdoug return 1; 263c4905cd3Sdoug } 264c4905cd3Sdoug 265c4905cd3Sdoug 266732f1cb2Sdoug static int 267732f1cb2Sdoug cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len) 268732f1cb2Sdoug { 269c4905cd3Sdoug uint8_t *prefix_bytes; 270c4905cd3Sdoug 271732f1cb2Sdoug if (!CBB_flush(cbb)) 272c4905cd3Sdoug return 0; 273c4905cd3Sdoug 274c4905cd3Sdoug cbb->offset = cbb->base->len; 275732f1cb2Sdoug if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) 276c4905cd3Sdoug return 0; 277c4905cd3Sdoug 278c4905cd3Sdoug memset(prefix_bytes, 0, len_len); 279c4905cd3Sdoug memset(out_contents, 0, sizeof(CBB)); 280c4905cd3Sdoug out_contents->base = cbb->base; 281c4905cd3Sdoug cbb->child = out_contents; 282c4905cd3Sdoug cbb->pending_len_len = len_len; 283c4905cd3Sdoug cbb->pending_is_asn1 = 0; 284c4905cd3Sdoug 285c4905cd3Sdoug return 1; 286c4905cd3Sdoug } 287c4905cd3Sdoug 288732f1cb2Sdoug int 289732f1cb2Sdoug CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) 290732f1cb2Sdoug { 291c4905cd3Sdoug return cbb_add_length_prefixed(cbb, out_contents, 1); 292c4905cd3Sdoug } 293c4905cd3Sdoug 294732f1cb2Sdoug int 295732f1cb2Sdoug CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) 296732f1cb2Sdoug { 297c4905cd3Sdoug return cbb_add_length_prefixed(cbb, out_contents, 2); 298c4905cd3Sdoug } 299c4905cd3Sdoug 300732f1cb2Sdoug int 301732f1cb2Sdoug CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) 302732f1cb2Sdoug { 303c4905cd3Sdoug return cbb_add_length_prefixed(cbb, out_contents, 3); 304c4905cd3Sdoug } 305c4905cd3Sdoug 306732f1cb2Sdoug int 307*9d4b5ca7Sdoug CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag) 308732f1cb2Sdoug { 309*9d4b5ca7Sdoug if (tag > UINT8_MAX) 310*9d4b5ca7Sdoug return 0; 311*9d4b5ca7Sdoug 312d7a08d8fSdoug /* Long form identifier octets are not supported. */ 313d7a08d8fSdoug if ((tag & 0x1f) == 0x1f) 314d7a08d8fSdoug return 0; 315d7a08d8fSdoug 3166ea8e45cSdoug /* Short-form identifier octet only needs a single byte */ 317732f1cb2Sdoug if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag)) 318c4905cd3Sdoug return 0; 319c4905cd3Sdoug 3206ea8e45cSdoug /* 3216ea8e45cSdoug * Add 1 byte to cover the short-form length octet case. If it turns 3226ea8e45cSdoug * out we need long-form, it will be extended later. 3236ea8e45cSdoug */ 324c4905cd3Sdoug cbb->offset = cbb->base->len; 325732f1cb2Sdoug if (!CBB_add_u8(cbb, 0)) 326c4905cd3Sdoug return 0; 327c4905cd3Sdoug 328c4905cd3Sdoug memset(out_contents, 0, sizeof(CBB)); 329c4905cd3Sdoug out_contents->base = cbb->base; 330c4905cd3Sdoug cbb->child = out_contents; 331c4905cd3Sdoug cbb->pending_len_len = 1; 332c4905cd3Sdoug cbb->pending_is_asn1 = 1; 333c4905cd3Sdoug 334c4905cd3Sdoug return 1; 335c4905cd3Sdoug } 336c4905cd3Sdoug 337732f1cb2Sdoug int 338732f1cb2Sdoug CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) 339732f1cb2Sdoug { 340c4905cd3Sdoug uint8_t *dest; 341c4905cd3Sdoug 34218f8c184Sdoug if (!CBB_add_space(cbb, &dest, len)) 343c4905cd3Sdoug return 0; 344732f1cb2Sdoug 345c4905cd3Sdoug memcpy(dest, data, len); 346c4905cd3Sdoug return 1; 347c4905cd3Sdoug } 348c4905cd3Sdoug 349732f1cb2Sdoug int 350732f1cb2Sdoug CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) 351732f1cb2Sdoug { 352732f1cb2Sdoug if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len)) 353c4905cd3Sdoug return 0; 354732f1cb2Sdoug 355c4905cd3Sdoug return 1; 356c4905cd3Sdoug } 357c4905cd3Sdoug 358732f1cb2Sdoug int 359*9d4b5ca7Sdoug CBB_add_u8(CBB *cbb, size_t value) 360732f1cb2Sdoug { 361*9d4b5ca7Sdoug if (value > UINT8_MAX) 362*9d4b5ca7Sdoug return 0; 363*9d4b5ca7Sdoug 364*9d4b5ca7Sdoug return cbb_add_u(cbb, (uint32_t)value, 1); 365c4905cd3Sdoug } 366c4905cd3Sdoug 367732f1cb2Sdoug int 368*9d4b5ca7Sdoug CBB_add_u16(CBB *cbb, size_t value) 369732f1cb2Sdoug { 370*9d4b5ca7Sdoug if (value > UINT16_MAX) 371*9d4b5ca7Sdoug return 0; 372*9d4b5ca7Sdoug 373*9d4b5ca7Sdoug return cbb_add_u(cbb, (uint32_t)value, 2); 374c4905cd3Sdoug } 375c4905cd3Sdoug 376732f1cb2Sdoug int 377*9d4b5ca7Sdoug CBB_add_u24(CBB *cbb, size_t value) 378732f1cb2Sdoug { 379*9d4b5ca7Sdoug if (value > 0xffffffUL) 380*9d4b5ca7Sdoug return 0; 381*9d4b5ca7Sdoug 382*9d4b5ca7Sdoug return cbb_add_u(cbb, (uint32_t)value, 3); 383c4905cd3Sdoug } 384c4905cd3Sdoug 385732f1cb2Sdoug int 386732f1cb2Sdoug CBB_add_asn1_uint64(CBB *cbb, uint64_t value) 387732f1cb2Sdoug { 388c4905cd3Sdoug CBB child; 389c4905cd3Sdoug size_t i; 390c4905cd3Sdoug int started = 0; 391c4905cd3Sdoug 392732f1cb2Sdoug if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) 393c4905cd3Sdoug return 0; 394c4905cd3Sdoug 395c4905cd3Sdoug for (i = 0; i < 8; i++) { 396c4905cd3Sdoug uint8_t byte = (value >> 8 * (7 - i)) & 0xff; 397debb3ac7Sdoug 398debb3ac7Sdoug /* 399debb3ac7Sdoug * ASN.1 restriction: first 9 bits cannot be all zeroes or 400debb3ac7Sdoug * all ones. Since this function only encodes unsigned 401debb3ac7Sdoug * integers, the only concerns are not encoding leading 402debb3ac7Sdoug * zeros and adding a padding byte if necessary. 403debb3ac7Sdoug * 404debb3ac7Sdoug * In practice, this means: 405debb3ac7Sdoug * 1) Skip leading octets of all zero bits in the value 406debb3ac7Sdoug * 2) After skipping the leading zero octets, if the next 9 407debb3ac7Sdoug * bits are all ones, add an all zero prefix octet (and 408debb3ac7Sdoug * set the high bit of the prefix octet if negative). 409debb3ac7Sdoug * 410debb3ac7Sdoug * Additionally, for an unsigned value, add an all zero 411debb3ac7Sdoug * prefix if the high bit of the first octet would be one. 412debb3ac7Sdoug */ 413c4905cd3Sdoug if (!started) { 414732f1cb2Sdoug if (byte == 0) 415c4905cd3Sdoug /* Don't encode leading zeros. */ 416c4905cd3Sdoug continue; 417732f1cb2Sdoug 418d7a08d8fSdoug /* 419d7a08d8fSdoug * If the high bit is set, add a padding byte to make it 420d7a08d8fSdoug * unsigned. 421d7a08d8fSdoug */ 422732f1cb2Sdoug if ((byte & 0x80) && !CBB_add_u8(&child, 0)) 423c4905cd3Sdoug return 0; 424732f1cb2Sdoug 425c4905cd3Sdoug started = 1; 426c4905cd3Sdoug } 427732f1cb2Sdoug if (!CBB_add_u8(&child, byte)) 428c4905cd3Sdoug return 0; 429c4905cd3Sdoug } 430c4905cd3Sdoug 431c4905cd3Sdoug /* 0 is encoded as a single 0, not the empty string. */ 432732f1cb2Sdoug if (!started && !CBB_add_u8(&child, 0)) 433c4905cd3Sdoug return 0; 434c4905cd3Sdoug 435c4905cd3Sdoug return CBB_flush(cbb); 436c4905cd3Sdoug } 437