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 23 void CBB_zero(CBB *cbb) { 24 memset(cbb, 0, sizeof(CBB)); 25 } 26 27 static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) { 28 /* This assumes that |cbb| has already been zeroed. */ 29 struct cbb_buffer_st *base; 30 31 base = OPENSSL_malloc(sizeof(struct cbb_buffer_st)); 32 if (base == NULL) { 33 return 0; 34 } 35 36 base->buf = buf; 37 base->len = 0; 38 base->cap = cap; 39 base->can_resize = 1; 40 41 cbb->base = base; 42 cbb->is_top_level = 1; 43 return 1; 44 } 45 46 int CBB_init(CBB *cbb, size_t initial_capacity) { 47 CBB_zero(cbb); 48 49 uint8_t *buf = OPENSSL_malloc(initial_capacity); 50 if (initial_capacity > 0 && buf == NULL) { 51 return 0; 52 } 53 54 if (!cbb_init(cbb, buf, initial_capacity)) { 55 OPENSSL_free(buf); 56 return 0; 57 } 58 59 return 1; 60 } 61 62 int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) { 63 CBB_zero(cbb); 64 65 if (!cbb_init(cbb, buf, len)) { 66 return 0; 67 } 68 69 cbb->base->can_resize = 0; 70 return 1; 71 } 72 73 void CBB_cleanup(CBB *cbb) { 74 if (cbb->base) { 75 /* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They 76 * are implicitly discarded when the parent is flushed or cleaned up. */ 77 assert(cbb->is_top_level); 78 79 if (cbb->base->can_resize) { 80 OPENSSL_free(cbb->base->buf); 81 } 82 OPENSSL_free(cbb->base); 83 } 84 cbb->base = NULL; 85 } 86 87 static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out, 88 size_t len) { 89 size_t newlen; 90 91 if (base == NULL) { 92 return 0; 93 } 94 95 newlen = base->len + len; 96 if (newlen < base->len) { 97 /* Overflow */ 98 return 0; 99 } 100 101 if (newlen > base->cap) { 102 size_t newcap = base->cap * 2; 103 uint8_t *newbuf; 104 105 if (!base->can_resize) { 106 return 0; 107 } 108 109 if (newcap < base->cap || newcap < newlen) { 110 newcap = newlen; 111 } 112 newbuf = OPENSSL_realloc(base->buf, newcap); 113 if (newbuf == NULL) { 114 return 0; 115 } 116 117 base->buf = newbuf; 118 base->cap = newcap; 119 } 120 121 if (out) { 122 *out = base->buf + base->len; 123 } 124 125 return 1; 126 } 127 128 static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, 129 size_t len) { 130 if (!cbb_buffer_reserve(base, out, len)) { 131 return 0; 132 } 133 /* This will not overflow or |cbb_buffer_reserve| would have failed. */ 134 base->len += len; 135 return 1; 136 } 137 138 static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v, 139 size_t len_len) { 140 uint8_t *buf; 141 size_t i; 142 143 if (len_len == 0) { 144 return 1; 145 } 146 if (!cbb_buffer_add(base, &buf, len_len)) { 147 return 0; 148 } 149 150 for (i = len_len - 1; i < len_len; i--) { 151 buf[i] = v; 152 v >>= 8; 153 } 154 return 1; 155 } 156 157 int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) { 158 if (!cbb->is_top_level) { 159 return 0; 160 } 161 162 if (!CBB_flush(cbb)) { 163 return 0; 164 } 165 166 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) { 167 /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */ 168 return 0; 169 } 170 171 if (out_data != NULL) { 172 *out_data = cbb->base->buf; 173 } 174 if (out_len != NULL) { 175 *out_len = cbb->base->len; 176 } 177 cbb->base->buf = NULL; 178 CBB_cleanup(cbb); 179 return 1; 180 } 181 182 /* CBB_flush recurses and then writes out any pending length prefix. The 183 * current length of the underlying base is taken to be the length of the 184 * length-prefixed data. */ 185 int CBB_flush(CBB *cbb) { 186 size_t child_start, i, len; 187 188 if (cbb->base == NULL) { 189 return 0; 190 } 191 192 if (cbb->child == NULL || cbb->child->pending_len_len == 0) { 193 return 1; 194 } 195 196 child_start = cbb->child->offset + cbb->child->pending_len_len; 197 198 if (!CBB_flush(cbb->child) || 199 child_start < cbb->child->offset || 200 cbb->base->len < child_start) { 201 return 0; 202 } 203 204 len = cbb->base->len - child_start; 205 206 if (cbb->child->pending_is_asn1) { 207 /* For ASN.1 we assume that we'll only need a single byte for the length. 208 * If that turned out to be incorrect, we have to move the contents along 209 * in order to make space. */ 210 size_t len_len; 211 uint8_t initial_length_byte; 212 213 assert (cbb->child->pending_len_len == 1); 214 215 if (len > 0xfffffffe) { 216 /* Too large. */ 217 return 0; 218 } else if (len > 0xffffff) { 219 len_len = 5; 220 initial_length_byte = 0x80 | 4; 221 } else if (len > 0xffff) { 222 len_len = 4; 223 initial_length_byte = 0x80 | 3; 224 } else if (len > 0xff) { 225 len_len = 3; 226 initial_length_byte = 0x80 | 2; 227 } else if (len > 0x7f) { 228 len_len = 2; 229 initial_length_byte = 0x80 | 1; 230 } else { 231 len_len = 1; 232 initial_length_byte = len; 233 len = 0; 234 } 235 236 if (len_len != 1) { 237 /* We need to move the contents along in order to make space. */ 238 size_t extra_bytes = len_len - 1; 239 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) { 240 return 0; 241 } 242 memmove(cbb->base->buf + child_start + extra_bytes, 243 cbb->base->buf + child_start, len); 244 } 245 cbb->base->buf[cbb->child->offset++] = initial_length_byte; 246 cbb->child->pending_len_len = len_len - 1; 247 } 248 249 for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len; 250 i--) { 251 cbb->base->buf[cbb->child->offset + i] = len; 252 len >>= 8; 253 } 254 if (len != 0) { 255 return 0; 256 } 257 258 cbb->child->base = NULL; 259 cbb->child = NULL; 260 261 return 1; 262 } 263 264 const uint8_t *CBB_data(const CBB *cbb) { 265 assert(cbb->child == NULL); 266 return cbb->base->buf + cbb->offset + cbb->pending_len_len; 267 } 268 269 size_t CBB_len(const CBB *cbb) { 270 assert(cbb->child == NULL); 271 assert(cbb->offset + cbb->pending_len_len <= cbb->base->len); 272 273 return cbb->base->len - cbb->offset - cbb->pending_len_len; 274 } 275 276 static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, 277 size_t len_len) { 278 uint8_t *prefix_bytes; 279 280 if (!CBB_flush(cbb)) { 281 return 0; 282 } 283 284 size_t offset = cbb->base->len; 285 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) { 286 return 0; 287 } 288 289 memset(prefix_bytes, 0, len_len); 290 memset(out_contents, 0, sizeof(CBB)); 291 out_contents->base = cbb->base; 292 cbb->child = out_contents; 293 cbb->child->offset = offset; 294 cbb->child->pending_len_len = len_len; 295 cbb->child->pending_is_asn1 = 0; 296 297 return 1; 298 } 299 300 int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) { 301 return cbb_add_length_prefixed(cbb, out_contents, 1); 302 } 303 304 int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) { 305 return cbb_add_length_prefixed(cbb, out_contents, 2); 306 } 307 308 int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) { 309 return cbb_add_length_prefixed(cbb, out_contents, 3); 310 } 311 312 int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) { 313 if ((tag & 0x1f) == 0x1f) { 314 /* Long form identifier octets are not supported. */ 315 return 0; 316 } 317 318 if (!CBB_flush(cbb) || 319 !CBB_add_u8(cbb, tag)) { 320 return 0; 321 } 322 323 size_t offset = cbb->base->len; 324 if (!CBB_add_u8(cbb, 0)) { 325 return 0; 326 } 327 328 memset(out_contents, 0, sizeof(CBB)); 329 out_contents->base = cbb->base; 330 cbb->child = out_contents; 331 cbb->child->offset = offset; 332 cbb->child->pending_len_len = 1; 333 cbb->child->pending_is_asn1 = 1; 334 335 return 1; 336 } 337 338 int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) { 339 uint8_t *dest; 340 341 if (!CBB_flush(cbb) || 342 !cbb_buffer_add(cbb->base, &dest, len)) { 343 return 0; 344 } 345 memcpy(dest, data, len); 346 return 1; 347 } 348 349 int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) { 350 if (!CBB_flush(cbb) || 351 !cbb_buffer_add(cbb->base, out_data, len)) { 352 return 0; 353 } 354 return 1; 355 } 356 357 int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) { 358 if (!CBB_flush(cbb) || 359 !cbb_buffer_reserve(cbb->base, out_data, len)) { 360 return 0; 361 } 362 return 1; 363 } 364 365 int CBB_did_write(CBB *cbb, size_t len) { 366 size_t newlen = cbb->base->len + len; 367 if (cbb->child != NULL || 368 newlen < cbb->base->len || 369 newlen > cbb->base->cap) { 370 return 0; 371 } 372 cbb->base->len = newlen; 373 return 1; 374 } 375 376 int CBB_add_u8(CBB *cbb, uint8_t value) { 377 if (!CBB_flush(cbb)) { 378 return 0; 379 } 380 381 return cbb_buffer_add_u(cbb->base, value, 1); 382 } 383 384 int CBB_add_u16(CBB *cbb, uint16_t value) { 385 if (!CBB_flush(cbb)) { 386 return 0; 387 } 388 389 return cbb_buffer_add_u(cbb->base, value, 2); 390 } 391 392 int CBB_add_u24(CBB *cbb, uint32_t value) { 393 if (!CBB_flush(cbb)) { 394 return 0; 395 } 396 397 return cbb_buffer_add_u(cbb->base, value, 3); 398 } 399 400 void CBB_discard_child(CBB *cbb) { 401 if (cbb->child == NULL) { 402 return; 403 } 404 405 cbb->base->len = cbb->child->offset; 406 407 cbb->child->base = NULL; 408 cbb->child = NULL; 409 } 410 411 int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) { 412 CBB child; 413 size_t i; 414 int started = 0; 415 416 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) { 417 return 0; 418 } 419 420 for (i = 0; i < 8; i++) { 421 uint8_t byte = (value >> 8*(7-i)) & 0xff; 422 if (!started) { 423 if (byte == 0) { 424 /* Don't encode leading zeros. */ 425 continue; 426 } 427 /* If the high bit is set, add a padding byte to make it 428 * unsigned. */ 429 if ((byte & 0x80) && !CBB_add_u8(&child, 0)) { 430 return 0; 431 } 432 started = 1; 433 } 434 if (!CBB_add_u8(&child, byte)) { 435 return 0; 436 } 437 } 438 439 /* 0 is encoded as a single 0, not the empty string. */ 440 if (!started && !CBB_add_u8(&child, 0)) { 441 return 0; 442 } 443 444 return CBB_flush(cbb); 445 } 446