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