1/* $OpenBSD: bs_cbs.c,v 1.25 2024/05/25 15:14:26 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 <stdint.h> 19#include <stdlib.h> 20#include <string.h> 21 22#include "bytestring.h" 23 24void 25CBS_init(CBS *cbs, const uint8_t *data, size_t len) 26{ 27 cbs->data = data; 28 cbs->initial_len = len; 29 cbs->len = len; 30} 31 32void 33CBS_dup(const CBS *cbs, CBS *out) 34{ 35 CBS_init(out, CBS_data(cbs), CBS_len(cbs)); 36 out->initial_len = cbs->initial_len; 37} 38 39static int 40cbs_get(CBS *cbs, const uint8_t **p, size_t n) 41{ 42 if (cbs->len < n) 43 return 0; 44 45 *p = cbs->data; 46 cbs->data += n; 47 cbs->len -= n; 48 return 1; 49} 50 51static int 52cbs_peek(CBS *cbs, const uint8_t **p, size_t n) 53{ 54 if (cbs->len < n) 55 return 0; 56 57 *p = cbs->data; 58 return 1; 59} 60 61size_t 62CBS_offset(const CBS *cbs) 63{ 64 return cbs->initial_len - cbs->len; 65} 66 67int 68CBS_skip(CBS *cbs, size_t len) 69{ 70 const uint8_t *dummy; 71 return cbs_get(cbs, &dummy, len); 72} 73 74const uint8_t * 75CBS_data(const CBS *cbs) 76{ 77 return cbs->data; 78} 79 80size_t 81CBS_len(const CBS *cbs) 82{ 83 return cbs->len; 84} 85 86int 87CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) 88{ 89 free(*out_ptr); 90 *out_ptr = NULL; 91 *out_len = 0; 92 93 if (cbs->len == 0) 94 return 1; 95 96 if ((*out_ptr = malloc(cbs->len)) == NULL) 97 return 0; 98 99 memcpy(*out_ptr, cbs->data, cbs->len); 100 101 *out_len = cbs->len; 102 return 1; 103} 104 105int 106CBS_strdup(const CBS *cbs, char **out_ptr) 107{ 108 free(*out_ptr); 109 *out_ptr = NULL; 110 111 if (CBS_contains_zero_byte(cbs)) 112 return 0; 113 114 *out_ptr = strndup((const char *)cbs->data, cbs->len); 115 return (*out_ptr != NULL); 116} 117 118int 119CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len, size_t *copied) 120{ 121 if (dst_len < cbs->len) 122 return 0; 123 124 memmove(dst, cbs->data, cbs->len); 125 126 if (copied != NULL) 127 *copied = cbs->len; 128 129 return 1; 130} 131 132int 133CBS_contains_zero_byte(const CBS *cbs) 134{ 135 return memchr(cbs->data, 0, cbs->len) != NULL; 136} 137 138int 139CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) 140{ 141 if (len != cbs->len) 142 return 0; 143 144 return timingsafe_memcmp(cbs->data, data, len) == 0; 145} 146 147static int 148cbs_get_u(CBS *cbs, uint32_t *out, size_t len) 149{ 150 uint32_t result = 0; 151 size_t i; 152 const uint8_t *data; 153 154 if (len < 1 || len > 4) 155 return 0; 156 157 if (!cbs_get(cbs, &data, len)) 158 return 0; 159 160 for (i = 0; i < len; i++) { 161 result <<= 8; 162 result |= data[i]; 163 } 164 *out = result; 165 return 1; 166} 167 168int 169CBS_get_u8(CBS *cbs, uint8_t *out) 170{ 171 const uint8_t *v; 172 173 if (!cbs_get(cbs, &v, 1)) 174 return 0; 175 176 *out = *v; 177 return 1; 178} 179 180int 181CBS_get_u16(CBS *cbs, uint16_t *out) 182{ 183 uint32_t v; 184 185 if (!cbs_get_u(cbs, &v, 2)) 186 return 0; 187 188 *out = v; 189 return 1; 190} 191 192int 193CBS_get_u24(CBS *cbs, uint32_t *out) 194{ 195 return cbs_get_u(cbs, out, 3); 196} 197 198int 199CBS_get_u32(CBS *cbs, uint32_t *out) 200{ 201 return cbs_get_u(cbs, out, 4); 202} 203 204int 205CBS_get_u64(CBS *cbs, uint64_t *out) 206{ 207 uint32_t a, b; 208 209 if (cbs->len < 8) 210 return 0; 211 212 if (!CBS_get_u32(cbs, &a)) 213 return 0; 214 if (!CBS_get_u32(cbs, &b)) 215 return 0; 216 217 *out = (uint64_t)a << 32 | b; 218 return 1; 219} 220 221int 222CBS_get_last_u8(CBS *cbs, uint8_t *out) 223{ 224 if (cbs->len == 0) 225 return 0; 226 227 *out = cbs->data[cbs->len - 1]; 228 cbs->len--; 229 return 1; 230} 231 232int 233CBS_get_bytes(CBS *cbs, CBS *out, size_t len) 234{ 235 const uint8_t *v; 236 237 if (!cbs_get(cbs, &v, len)) 238 return 0; 239 240 CBS_init(out, v, len); 241 return 1; 242} 243 244static int 245cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) 246{ 247 uint32_t len; 248 249 if (!cbs_get_u(cbs, &len, len_len)) 250 return 0; 251 252 return CBS_get_bytes(cbs, out, len); 253} 254 255int 256CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) 257{ 258 return cbs_get_length_prefixed(cbs, out, 1); 259} 260 261int 262CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) 263{ 264 return cbs_get_length_prefixed(cbs, out, 2); 265} 266 267int 268CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) 269{ 270 return cbs_get_length_prefixed(cbs, out, 3); 271} 272 273static int 274cbs_peek_u(CBS *cbs, uint32_t *out, size_t len) 275{ 276 uint32_t result = 0; 277 size_t i; 278 const uint8_t *data; 279 280 if (len < 1 || len > 4) 281 return 0; 282 283 if (!cbs_peek(cbs, &data, len)) 284 return 0; 285 286 for (i = 0; i < len; i++) { 287 result <<= 8; 288 result |= data[i]; 289 } 290 *out = result; 291 return 1; 292} 293 294int 295CBS_peek_u8(CBS *cbs, uint8_t *out) 296{ 297 const uint8_t *v; 298 299 if (!cbs_peek(cbs, &v, 1)) 300 return 0; 301 302 *out = *v; 303 return 1; 304} 305 306int 307CBS_peek_u16(CBS *cbs, uint16_t *out) 308{ 309 uint32_t v; 310 311 if (!cbs_peek_u(cbs, &v, 2)) 312 return 0; 313 314 *out = v; 315 return 1; 316} 317 318int 319CBS_peek_u24(CBS *cbs, uint32_t *out) 320{ 321 return cbs_peek_u(cbs, out, 3); 322} 323 324int 325CBS_peek_u32(CBS *cbs, uint32_t *out) 326{ 327 return cbs_peek_u(cbs, out, 4); 328} 329 330int 331CBS_peek_last_u8(CBS *cbs, uint8_t *out) 332{ 333 if (cbs->len == 0) 334 return 0; 335 336 *out = cbs->data[cbs->len - 1]; 337 return 1; 338} 339 340int 341CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, 342 size_t *out_header_len) 343{ 344 return cbs_get_any_asn1_element_internal(cbs, out, out_tag, 345 out_header_len, 1); 346} 347 348/* 349 * Review X.690 for details on ASN.1 DER encoding. 350 * 351 * If non-strict mode is enabled, then DER rules are relaxed 352 * for indefinite constructs (violates DER but a little closer to BER). 353 * Non-strict mode should only be used by bs_ber.c 354 * 355 * Sections 8, 10 and 11 for DER encoding 356 */ 357int 358cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag, 359 size_t *out_header_len, int strict) 360{ 361 uint8_t tag, length_byte; 362 CBS header = *cbs; 363 CBS throwaway; 364 size_t len; 365 366 if (out == NULL) 367 out = &throwaway; 368 369 /* 370 * Get identifier octet and length octet. Only 1 octet for each 371 * is a CBS limitation. 372 */ 373 if (!CBS_get_u8(&header, &tag) || !CBS_get_u8(&header, &length_byte)) 374 return 0; 375 376 /* CBS limitation: long form tags are not supported. */ 377 if ((tag & 0x1f) == 0x1f) 378 return 0; 379 380 if (out_tag != NULL) 381 *out_tag = tag; 382 383 if ((length_byte & 0x80) == 0) { 384 /* Short form length. */ 385 len = ((size_t) length_byte) + 2; 386 if (out_header_len != NULL) 387 *out_header_len = 2; 388 389 } else { 390 /* Long form length. */ 391 const size_t num_bytes = length_byte & 0x7f; 392 uint32_t len32; 393 394 /* ASN.1 reserved value for future extensions */ 395 if (num_bytes == 0x7f) 396 return 0; 397 398 /* Handle indefinite form length */ 399 if (num_bytes == 0) { 400 /* DER encoding doesn't allow for indefinite form. */ 401 if (strict) 402 return 0; 403 404 /* Primitive cannot use indefinite in BER or DER. */ 405 if ((tag & CBS_ASN1_CONSTRUCTED) == 0) 406 return 0; 407 408 /* Constructed, indefinite length allowed in BER. */ 409 if (out_header_len != NULL) 410 *out_header_len = 2; 411 return CBS_get_bytes(cbs, out, 2); 412 } 413 414 /* CBS limitation. */ 415 if (num_bytes > 4) 416 return 0; 417 418 if (!cbs_get_u(&header, &len32, num_bytes)) 419 return 0; 420 421 /* DER has a minimum length octet requirement. */ 422 if (len32 < 128) 423 /* Should have used short form instead */ 424 return 0; 425 426 if ((len32 >> ((num_bytes - 1) * 8)) == 0) 427 /* Length should have been at least one byte shorter. */ 428 return 0; 429 430 len = len32; 431 if (len + 2 + num_bytes < len) 432 /* Overflow. */ 433 return 0; 434 435 len += 2 + num_bytes; 436 if (out_header_len != NULL) 437 *out_header_len = 2 + num_bytes; 438 } 439 440 return CBS_get_bytes(cbs, out, len); 441} 442 443static int 444cbs_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value, int skip_header) 445{ 446 size_t header_len; 447 unsigned int tag; 448 CBS throwaway; 449 450 if (out == NULL) 451 out = &throwaway; 452 453 if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) || 454 tag != tag_value) 455 return 0; 456 457 if (skip_header && !CBS_skip(out, header_len)) 458 return 0; 459 460 return 1; 461} 462 463int 464CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value) 465{ 466 return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */); 467} 468 469int 470CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value) 471{ 472 return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */); 473} 474 475int 476CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value) 477{ 478 if (CBS_len(cbs) < 1) 479 return 0; 480 481 /* 482 * Tag number 31 indicates the start of a long form number. 483 * This is valid in ASN.1, but CBS only supports short form. 484 */ 485 if ((tag_value & 0x1f) == 0x1f) 486 return 0; 487 488 return CBS_data(cbs)[0] == tag_value; 489} 490 491/* Encoding details are in ASN.1: X.690 section 8.3 */ 492int 493CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) 494{ 495 CBS bytes; 496 const uint8_t *data; 497 size_t i, len; 498 499 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) 500 return 0; 501 502 *out = 0; 503 data = CBS_data(&bytes); 504 len = CBS_len(&bytes); 505 506 if (len == 0) 507 /* An INTEGER is encoded with at least one content octet. */ 508 return 0; 509 510 if ((data[0] & 0x80) != 0) 511 /* Negative number. */ 512 return 0; 513 514 if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) 515 /* Violates smallest encoding rule: excessive leading zeros. */ 516 return 0; 517 518 for (i = 0; i < len; i++) { 519 if ((*out >> 56) != 0) 520 /* Too large to represent as a uint64_t. */ 521 return 0; 522 523 *out <<= 8; 524 *out |= data[i]; 525 } 526 527 return 1; 528} 529 530int 531CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned int tag) 532{ 533 if (CBS_peek_asn1_tag(cbs, tag)) { 534 if (!CBS_get_asn1(cbs, out, tag)) 535 return 0; 536 537 *out_present = 1; 538 } else { 539 *out_present = 0; 540 } 541 return 1; 542} 543 544int 545CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, 546 unsigned int tag) 547{ 548 CBS child; 549 int present; 550 551 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) 552 return 0; 553 554 if (present) { 555 if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || 556 CBS_len(&child) != 0) 557 return 0; 558 } else { 559 CBS_init(out, NULL, 0); 560 } 561 if (out_present) 562 *out_present = present; 563 564 return 1; 565} 566 567int 568CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag, 569 uint64_t default_value) 570{ 571 CBS child; 572 int present; 573 574 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) 575 return 0; 576 577 if (present) { 578 if (!CBS_get_asn1_uint64(&child, out) || 579 CBS_len(&child) != 0) 580 return 0; 581 } else { 582 *out = default_value; 583 } 584 return 1; 585} 586 587int 588CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag, 589 int default_value) 590{ 591 CBS child, child2; 592 int present; 593 594 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) 595 return 0; 596 597 if (present) { 598 uint8_t boolean; 599 600 if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || 601 CBS_len(&child2) != 1 || CBS_len(&child) != 0) 602 return 0; 603 604 boolean = CBS_data(&child2)[0]; 605 if (boolean == 0) 606 *out = 0; 607 else if (boolean == 0xff) 608 *out = 1; 609 else 610 return 0; 611 612 } else { 613 *out = default_value; 614 } 615 return 1; 616} 617