1 /* $OpenBSD: bs_cbs.c,v 1.3 2024/05/25 15:12:47 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 24 void 25 CBS_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 32 void 33 CBS_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 39 static int 40 cbs_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 51 static int 52 cbs_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 61 size_t 62 CBS_offset(const CBS *cbs) 63 { 64 return cbs->initial_len - cbs->len; 65 } 66 67 int 68 CBS_skip(CBS *cbs, size_t len) 69 { 70 const uint8_t *dummy; 71 return cbs_get(cbs, &dummy, len); 72 } 73 74 const uint8_t * 75 CBS_data(const CBS *cbs) 76 { 77 return cbs->data; 78 } 79 80 size_t 81 CBS_len(const CBS *cbs) 82 { 83 return cbs->len; 84 } 85 86 int 87 CBS_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 105 int 106 CBS_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 118 int 119 CBS_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 132 int 133 CBS_contains_zero_byte(const CBS *cbs) 134 { 135 return memchr(cbs->data, 0, cbs->len) != NULL; 136 } 137 138 int 139 CBS_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 147 static int 148 cbs_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 168 int 169 CBS_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 180 int 181 CBS_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 192 int 193 CBS_get_u24(CBS *cbs, uint32_t *out) 194 { 195 return cbs_get_u(cbs, out, 3); 196 } 197 198 int 199 CBS_get_u32(CBS *cbs, uint32_t *out) 200 { 201 return cbs_get_u(cbs, out, 4); 202 } 203 204 int 205 CBS_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 221 int 222 CBS_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 232 int 233 CBS_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 244 static int 245 cbs_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 255 int 256 CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) 257 { 258 return cbs_get_length_prefixed(cbs, out, 1); 259 } 260 261 int 262 CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) 263 { 264 return cbs_get_length_prefixed(cbs, out, 2); 265 } 266 267 int 268 CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) 269 { 270 return cbs_get_length_prefixed(cbs, out, 3); 271 } 272 273 static int 274 cbs_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 294 int 295 CBS_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 306 int 307 CBS_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 318 int 319 CBS_peek_u24(CBS *cbs, uint32_t *out) 320 { 321 return cbs_peek_u(cbs, out, 3); 322 } 323 324 int 325 CBS_peek_u32(CBS *cbs, uint32_t *out) 326 { 327 return cbs_peek_u(cbs, out, 4); 328 } 329 330 int 331 CBS_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 340 int 341 CBS_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 */ 357 int 358 cbs_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 443 static int 444 cbs_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 463 int 464 CBS_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 469 int 470 CBS_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 475 int 476 CBS_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 */ 492 int 493 CBS_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 530 int 531 CBS_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 544 int 545 CBS_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 567 int 568 CBS_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 587 int 588 CBS_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