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