1/* Copyright (c) 2014, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15#include <openssl/bytestring.h> 16 17#include <assert.h> 18#include <string.h> 19 20#include <openssl/mem.h> 21 22#include "../internal.h" 23 24 25void CBB_zero(CBB *cbb) { 26 OPENSSL_memset(cbb, 0, sizeof(CBB)); 27} 28 29static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) { 30 /* This assumes that |cbb| has already been zeroed. */ 31 struct cbb_buffer_st *base; 32 33 base = OPENSSL_malloc(sizeof(struct cbb_buffer_st)); 34 if (base == NULL) { 35 return 0; 36 } 37 38 base->buf = buf; 39 base->len = 0; 40 base->cap = cap; 41 base->can_resize = 1; 42 base->error = 0; 43 44 cbb->base = base; 45 cbb->is_top_level = 1; 46 return 1; 47} 48 49int CBB_init(CBB *cbb, size_t initial_capacity) { 50 CBB_zero(cbb); 51 52 uint8_t *buf = OPENSSL_malloc(initial_capacity); 53 if (initial_capacity > 0 && buf == NULL) { 54 return 0; 55 } 56 57 if (!cbb_init(cbb, buf, initial_capacity)) { 58 OPENSSL_free(buf); 59 return 0; 60 } 61 62 return 1; 63} 64 65int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) { 66 CBB_zero(cbb); 67 68 if (!cbb_init(cbb, buf, len)) { 69 return 0; 70 } 71 72 cbb->base->can_resize = 0; 73 return 1; 74} 75 76void CBB_cleanup(CBB *cbb) { 77 if (cbb->base) { 78 /* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They 79 * are implicitly discarded when the parent is flushed or cleaned up. */ 80 assert(cbb->is_top_level); 81 82 if (cbb->base->can_resize) { 83 OPENSSL_free(cbb->base->buf); 84 } 85 OPENSSL_free(cbb->base); 86 } 87 cbb->base = NULL; 88} 89 90static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out, 91 size_t len) { 92 size_t newlen; 93 94 if (base == NULL) { 95 return 0; 96 } 97 98 newlen = base->len + len; 99 if (newlen < base->len) { 100 /* Overflow */ 101 goto err; 102 } 103 104 if (newlen > base->cap) { 105 size_t newcap = base->cap * 2; 106 uint8_t *newbuf; 107 108 if (!base->can_resize) { 109 goto err; 110 } 111 112 if (newcap < base->cap || newcap < newlen) { 113 newcap = newlen; 114 } 115 newbuf = OPENSSL_realloc(base->buf, newcap); 116 if (newbuf == NULL) { 117 goto err; 118 } 119 120 base->buf = newbuf; 121 base->cap = newcap; 122 } 123 124 if (out) { 125 *out = base->buf + base->len; 126 } 127 128 return 1; 129 130err: 131 base->error = 1; 132 return 0; 133} 134 135static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, 136 size_t len) { 137 if (!cbb_buffer_reserve(base, out, len)) { 138 return 0; 139 } 140 /* This will not overflow or |cbb_buffer_reserve| would have failed. */ 141 base->len += len; 142 return 1; 143} 144 145static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v, 146 size_t len_len) { 147 if (len_len == 0) { 148 return 1; 149 } 150 151 uint8_t *buf; 152 if (!cbb_buffer_add(base, &buf, len_len)) { 153 return 0; 154 } 155 156 for (size_t i = len_len - 1; i < len_len; i--) { 157 buf[i] = v; 158 v >>= 8; 159 } 160 161 if (v != 0) { 162 base->error = 1; 163 return 0; 164 } 165 166 return 1; 167} 168 169int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) { 170 if (!cbb->is_top_level) { 171 return 0; 172 } 173 174 if (!CBB_flush(cbb)) { 175 return 0; 176 } 177 178 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) { 179 /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */ 180 return 0; 181 } 182 183 if (out_data != NULL) { 184 *out_data = cbb->base->buf; 185 } 186 if (out_len != NULL) { 187 *out_len = cbb->base->len; 188 } 189 cbb->base->buf = NULL; 190 CBB_cleanup(cbb); 191 return 1; 192} 193 194/* CBB_flush recurses and then writes out any pending length prefix. The 195 * current length of the underlying base is taken to be the length of the 196 * length-prefixed data. */ 197int CBB_flush(CBB *cbb) { 198 size_t child_start, i, len; 199 200 /* If |cbb->base| has hit an error, the buffer is in an undefined state, so 201 * fail all following calls. In particular, |cbb->child| may point to invalid 202 * memory. */ 203 if (cbb->base == NULL || cbb->base->error) { 204 return 0; 205 } 206 207 if (cbb->child == NULL || cbb->child->pending_len_len == 0) { 208 return 1; 209 } 210 211 child_start = cbb->child->offset + cbb->child->pending_len_len; 212 213 if (!CBB_flush(cbb->child) || 214 child_start < cbb->child->offset || 215 cbb->base->len < child_start) { 216 goto err; 217 } 218 219 len = cbb->base->len - child_start; 220 221 if (cbb->child->pending_is_asn1) { 222 /* For ASN.1 we assume that we'll only need a single byte for the length. 223 * If that turned out to be incorrect, we have to move the contents along 224 * in order to make space. */ 225 uint8_t len_len; 226 uint8_t initial_length_byte; 227 228 assert (cbb->child->pending_len_len == 1); 229 230 if (len > 0xfffffffe) { 231 /* Too large. */ 232 goto err; 233 } else if (len > 0xffffff) { 234 len_len = 5; 235 initial_length_byte = 0x80 | 4; 236 } else if (len > 0xffff) { 237 len_len = 4; 238 initial_length_byte = 0x80 | 3; 239 } else if (len > 0xff) { 240 len_len = 3; 241 initial_length_byte = 0x80 | 2; 242 } else if (len > 0x7f) { 243 len_len = 2; 244 initial_length_byte = 0x80 | 1; 245 } else { 246 len_len = 1; 247 initial_length_byte = (uint8_t)len; 248 len = 0; 249 } 250 251 if (len_len != 1) { 252 /* We need to move the contents along in order to make space. */ 253 size_t extra_bytes = len_len - 1; 254 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) { 255 goto err; 256 } 257 OPENSSL_memmove(cbb->base->buf + child_start + extra_bytes, 258 cbb->base->buf + child_start, len); 259 } 260 cbb->base->buf[cbb->child->offset++] = initial_length_byte; 261 cbb->child->pending_len_len = len_len - 1; 262 } 263 264 for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len; 265 i--) { 266 cbb->base->buf[cbb->child->offset + i] = (uint8_t)len; 267 len >>= 8; 268 } 269 if (len != 0) { 270 goto err; 271 } 272 273 cbb->child->base = NULL; 274 cbb->child = NULL; 275 276 return 1; 277 278err: 279 cbb->base->error = 1; 280 return 0; 281} 282 283const uint8_t *CBB_data(const CBB *cbb) { 284 assert(cbb->child == NULL); 285 return cbb->base->buf + cbb->offset + cbb->pending_len_len; 286} 287 288size_t CBB_len(const CBB *cbb) { 289 assert(cbb->child == NULL); 290 assert(cbb->offset + cbb->pending_len_len <= cbb->base->len); 291 292 return cbb->base->len - cbb->offset - cbb->pending_len_len; 293} 294 295static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, 296 uint8_t len_len) { 297 uint8_t *prefix_bytes; 298 299 if (!CBB_flush(cbb)) { 300 return 0; 301 } 302 303 size_t offset = cbb->base->len; 304 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) { 305 return 0; 306 } 307 308 OPENSSL_memset(prefix_bytes, 0, len_len); 309 OPENSSL_memset(out_contents, 0, sizeof(CBB)); 310 out_contents->base = cbb->base; 311 cbb->child = out_contents; 312 cbb->child->offset = offset; 313 cbb->child->pending_len_len = len_len; 314 cbb->child->pending_is_asn1 = 0; 315 316 return 1; 317} 318 319int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) { 320 return cbb_add_length_prefixed(cbb, out_contents, 1); 321} 322 323int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) { 324 return cbb_add_length_prefixed(cbb, out_contents, 2); 325} 326 327int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) { 328 return cbb_add_length_prefixed(cbb, out_contents, 3); 329} 330 331int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) { 332 if (tag > 0xff || 333 (tag & 0x1f) == 0x1f) { 334 /* Long form identifier octets are not supported. Further, all current valid 335 * tag serializations are 8 bits. */ 336 cbb->base->error = 1; 337 return 0; 338 } 339 340 if (!CBB_flush(cbb) || 341 /* |tag|'s representation matches the DER encoding. */ 342 !CBB_add_u8(cbb, (uint8_t)tag)) { 343 return 0; 344 } 345 346 size_t offset = cbb->base->len; 347 if (!CBB_add_u8(cbb, 0)) { 348 return 0; 349 } 350 351 OPENSSL_memset(out_contents, 0, sizeof(CBB)); 352 out_contents->base = cbb->base; 353 cbb->child = out_contents; 354 cbb->child->offset = offset; 355 cbb->child->pending_len_len = 1; 356 cbb->child->pending_is_asn1 = 1; 357 358 return 1; 359} 360 361int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) { 362 uint8_t *dest; 363 364 if (!CBB_flush(cbb) || 365 !cbb_buffer_add(cbb->base, &dest, len)) { 366 return 0; 367 } 368 OPENSSL_memcpy(dest, data, len); 369 return 1; 370} 371 372int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) { 373 if (!CBB_flush(cbb) || 374 !cbb_buffer_add(cbb->base, out_data, len)) { 375 return 0; 376 } 377 return 1; 378} 379 380int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) { 381 if (!CBB_flush(cbb) || 382 !cbb_buffer_reserve(cbb->base, out_data, len)) { 383 return 0; 384 } 385 return 1; 386} 387 388int CBB_did_write(CBB *cbb, size_t len) { 389 size_t newlen = cbb->base->len + len; 390 if (cbb->child != NULL || 391 newlen < cbb->base->len || 392 newlen > cbb->base->cap) { 393 return 0; 394 } 395 cbb->base->len = newlen; 396 return 1; 397} 398 399int CBB_add_u8(CBB *cbb, uint8_t value) { 400 if (!CBB_flush(cbb)) { 401 return 0; 402 } 403 404 return cbb_buffer_add_u(cbb->base, value, 1); 405} 406 407int CBB_add_u16(CBB *cbb, uint16_t value) { 408 if (!CBB_flush(cbb)) { 409 return 0; 410 } 411 412 return cbb_buffer_add_u(cbb->base, value, 2); 413} 414 415int CBB_add_u24(CBB *cbb, uint32_t value) { 416 if (!CBB_flush(cbb)) { 417 return 0; 418 } 419 420 return cbb_buffer_add_u(cbb->base, value, 3); 421} 422 423int CBB_add_u32(CBB *cbb, uint32_t value) { 424 if (!CBB_flush(cbb)) { 425 return 0; 426 } 427 428 return cbb_buffer_add_u(cbb->base, value, 4); 429} 430 431void CBB_discard_child(CBB *cbb) { 432 if (cbb->child == NULL) { 433 return; 434 } 435 436 cbb->base->len = cbb->child->offset; 437 438 cbb->child->base = NULL; 439 cbb->child = NULL; 440} 441 442int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) { 443 CBB child; 444 int started = 0; 445 446 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) { 447 return 0; 448 } 449 450 for (size_t i = 0; i < 8; i++) { 451 uint8_t byte = (value >> 8*(7-i)) & 0xff; 452 if (!started) { 453 if (byte == 0) { 454 /* Don't encode leading zeros. */ 455 continue; 456 } 457 /* If the high bit is set, add a padding byte to make it 458 * unsigned. */ 459 if ((byte & 0x80) && !CBB_add_u8(&child, 0)) { 460 return 0; 461 } 462 started = 1; 463 } 464 if (!CBB_add_u8(&child, byte)) { 465 return 0; 466 } 467 } 468 469 /* 0 is encoded as a single 0, not the empty string. */ 470 if (!started && !CBB_add_u8(&child, 0)) { 471 return 0; 472 } 473 474 return CBB_flush(cbb); 475} 476