1 /* $NetBSD: der_get.c,v 1.3 2023/06/19 21:41:42 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "der_locl.h" 37 38 /* 39 * All decoding functions take a pointer `p' to first position in 40 * which to read, from the left, `len' which means the maximum number 41 * of characters we are able to read, `ret' were the value will be 42 * returned and `size' where the number of used bytes is stored. 43 * Either 0 or an error code is returned. 44 */ 45 46 int 47 der_get_unsigned (const unsigned char *p, size_t len, 48 unsigned *ret, size_t *size) 49 { 50 unsigned val = 0; 51 size_t oldlen = len; 52 53 if (len == sizeof(val) + 1 && p[0] == 0) 54 ; 55 else if (len > sizeof(val)) 56 return ASN1_OVERRUN; 57 58 while (len--) 59 val = val * 256 + *p++; 60 *ret = val; 61 if(size) *size = oldlen; 62 return 0; 63 } 64 65 int 66 der_get_unsigned64 (const unsigned char *p, size_t len, 67 uint64_t *ret, size_t *size) 68 { 69 uint64_t val = 0; 70 size_t oldlen = len; 71 72 if (len == sizeof(val) + 1 && p[0] == 0) 73 ; 74 else if (len > sizeof(val)) 75 return ASN1_OVERRUN; 76 77 while (len--) 78 val = val * 256 + *p++; 79 *ret = val; 80 if(size) *size = oldlen; 81 return 0; 82 } 83 84 int 85 der_get_integer (const unsigned char *p, size_t len, 86 int *ret, size_t *size) 87 { 88 int val = 0; 89 size_t oldlen = len; 90 91 if (len == sizeof(val) + 1 && (p[0] == 0 || p[0] == 0xff)) 92 ; 93 else if (len > sizeof(val)) 94 return ASN1_OVERRUN; 95 96 /* We assume we're on a twos-complement platform */ 97 if (len > 0) { 98 val = (signed char)*p++; 99 while (--len) 100 val = val * 256 + *p++; 101 } 102 *ret = val; 103 if(size) *size = oldlen; 104 return 0; 105 } 106 107 int 108 der_get_integer64 (const unsigned char *p, size_t len, 109 int64_t *ret, size_t *size) 110 { 111 int64_t val = 0; 112 size_t oldlen = len; 113 114 if (len > sizeof(val)) 115 return ASN1_OVERRUN; 116 117 /* We assume we're on a twos-complement platform */ 118 if (len > 0) { 119 val = (signed char)*p++; 120 while (--len) 121 val = val * 256 + *p++; 122 } 123 *ret = val; 124 if(size) *size = oldlen; 125 return 0; 126 } 127 128 129 int 130 der_get_length (const unsigned char *p, size_t len, 131 size_t *val, size_t *size) 132 { 133 size_t v; 134 135 if (len <= 0) 136 return ASN1_OVERRUN; 137 --len; 138 v = *p++; 139 if (v < 128) { 140 *val = v; 141 if(size) *size = 1; 142 } else { 143 int e; 144 size_t l; 145 unsigned tmp; 146 147 if(v == 0x80){ 148 *val = ASN1_INDEFINITE; 149 if(size) *size = 1; 150 return 0; 151 } 152 v &= 0x7F; 153 if (len < v) 154 return ASN1_OVERRUN; 155 e = der_get_unsigned (p, v, &tmp, &l); 156 if(e) return e; 157 *val = tmp; 158 if(size) *size = l + 1; 159 } 160 return 0; 161 } 162 163 int 164 der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size) 165 { 166 if(len < 1) 167 return ASN1_OVERRUN; 168 if(*p != 0) 169 *data = 1; 170 else 171 *data = 0; 172 *size = 1; 173 return 0; 174 } 175 176 int 177 der_get_general_string (const unsigned char *p, size_t len, 178 heim_general_string *str, size_t *size) 179 { 180 const unsigned char *p1; 181 char *s; 182 183 p1 = memchr(p, 0, len); 184 if (p1 != NULL) { 185 /* 186 * Allow trailing NULs. We allow this since MIT Kerberos sends 187 * an strings in the NEED_PREAUTH case that includes a 188 * trailing NUL. 189 */ 190 while ((size_t)(p1 - p) < len && *p1 == '\0') 191 p1++; 192 if ((size_t)(p1 - p) != len) { 193 *str = NULL; 194 return ASN1_BAD_CHARACTER; 195 } 196 } 197 if (len == SIZE_MAX) { 198 *str = NULL; 199 return ASN1_BAD_LENGTH; 200 } 201 202 *str = s = malloc (len + 1); 203 if (s == NULL) 204 return ENOMEM; 205 memcpy (s, p, len); 206 s[len] = '\0'; 207 208 if(size) *size = len; 209 return 0; 210 } 211 212 int 213 der_get_utf8string (const unsigned char *p, size_t len, 214 heim_utf8_string *str, size_t *size) 215 { 216 return der_get_general_string(p, len, str, size); 217 } 218 219 #define gen_data_zero(_data) \ 220 do { (_data)->length = 0; (_data)->data = NULL; } while(0) 221 222 int 223 der_get_printable_string(const unsigned char *p, size_t len, 224 heim_printable_string *str, size_t *size) 225 { 226 if (len == SIZE_MAX) { 227 gen_data_zero(str); 228 return ASN1_BAD_LENGTH; 229 } 230 str->length = len; 231 str->data = malloc(len + 1); 232 if (str->data == NULL) { 233 gen_data_zero(str); 234 return ENOMEM; 235 } 236 memcpy(str->data, p, len); 237 ((char *)str->data)[len] = '\0'; 238 if(size) *size = len; 239 return 0; 240 } 241 242 int 243 der_get_ia5_string(const unsigned char *p, size_t len, 244 heim_ia5_string *str, size_t *size) 245 { 246 return der_get_printable_string(p, len, str, size); 247 } 248 249 int 250 der_get_bmp_string (const unsigned char *p, size_t len, 251 heim_bmp_string *data, size_t *size) 252 { 253 size_t i; 254 255 if (len & 1) { 256 gen_data_zero(data); 257 return ASN1_BAD_FORMAT; 258 } 259 data->length = len / 2; 260 if (data->length > UINT_MAX/sizeof(data->data[0])) { 261 gen_data_zero(data); 262 return ERANGE; 263 } 264 data->data = malloc(data->length * sizeof(data->data[0])); 265 if (data->data == NULL && data->length != 0) { 266 gen_data_zero(data); 267 return ENOMEM; 268 } 269 270 for (i = 0; i < data->length; i++) { 271 data->data[i] = (p[0] << 8) | p[1]; 272 p += 2; 273 /* check for NUL in the middle of the string */ 274 if (data->data[i] == 0 && i != (data->length - 1)) { 275 free(data->data); 276 gen_data_zero(data); 277 return ASN1_BAD_CHARACTER; 278 } 279 } 280 if (size) *size = len; 281 282 return 0; 283 } 284 285 int 286 der_get_universal_string (const unsigned char *p, size_t len, 287 heim_universal_string *data, size_t *size) 288 { 289 size_t i; 290 291 if (len & 3) { 292 gen_data_zero(data); 293 return ASN1_BAD_FORMAT; 294 } 295 data->length = len / 4; 296 if (data->length > UINT_MAX/sizeof(data->data[0])) { 297 gen_data_zero(data); 298 return ERANGE; 299 } 300 data->data = malloc(data->length * sizeof(data->data[0])); 301 if (data->data == NULL && data->length != 0) { 302 gen_data_zero(data); 303 return ENOMEM; 304 } 305 306 for (i = 0; i < data->length; i++) { 307 data->data[i] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 308 p += 4; 309 /* check for NUL in the middle of the string */ 310 if (data->data[i] == 0 && i != (data->length - 1)) { 311 free(data->data); 312 gen_data_zero(data); 313 return ASN1_BAD_CHARACTER; 314 } 315 } 316 if (size) *size = len; 317 return 0; 318 } 319 320 int 321 der_get_visible_string (const unsigned char *p, size_t len, 322 heim_visible_string *str, size_t *size) 323 { 324 return der_get_general_string(p, len, str, size); 325 } 326 327 int 328 der_get_octet_string (const unsigned char *p, size_t len, 329 heim_octet_string *data, size_t *size) 330 { 331 data->length = len; 332 data->data = malloc(len); 333 if (data->data == NULL && data->length != 0) 334 return ENOMEM; 335 memcpy (data->data, p, len); 336 if(size) *size = len; 337 return 0; 338 } 339 340 int 341 der_get_octet_string_ber (const unsigned char *p, size_t len, 342 heim_octet_string *data, size_t *size) 343 { 344 int e; 345 Der_type type; 346 Der_class cls; 347 unsigned int tag, depth = 0; 348 size_t l, datalen, oldlen = len; 349 350 data->length = 0; 351 data->data = NULL; 352 353 while (len) { 354 e = der_get_tag (p, len, &cls, &type, &tag, &l); 355 if (e) goto out; 356 if (cls != ASN1_C_UNIV) { 357 e = ASN1_BAD_ID; 358 goto out; 359 } 360 if (type == PRIM && tag == UT_EndOfContent) { 361 if (depth == 0) 362 break; 363 depth--; 364 } 365 if (tag != UT_OctetString) { 366 e = ASN1_BAD_ID; 367 goto out; 368 } 369 370 p += l; 371 len -= l; 372 e = der_get_length (p, len, &datalen, &l); 373 if (e) goto out; 374 p += l; 375 len -= l; 376 377 if (datalen > len) 378 return ASN1_OVERRUN; 379 380 if (type == PRIM) { 381 void *ptr; 382 383 ptr = realloc(data->data, data->length + datalen); 384 if (ptr == NULL) { 385 e = ENOMEM; 386 goto out; 387 } 388 data->data = ptr; 389 memcpy(((unsigned char *)data->data) + data->length, p, datalen); 390 data->length += datalen; 391 } else 392 depth++; 393 394 p += datalen; 395 len -= datalen; 396 } 397 if (depth != 0) 398 return ASN1_INDEF_OVERRUN; 399 if(size) *size = oldlen - len; 400 return 0; 401 out: 402 free(data->data); 403 data->data = NULL; 404 data->length = 0; 405 return e; 406 } 407 408 409 int 410 der_get_heim_integer (const unsigned char *p, size_t len, 411 heim_integer *data, size_t *size) 412 { 413 data->length = 0; 414 data->negative = 0; 415 data->data = NULL; 416 417 if (len == 0) { 418 if (size) 419 *size = 0; 420 return 0; 421 } 422 if (p[0] & 0x80) { 423 unsigned char *q; 424 int carry = 1; 425 426 427 /* 428 * A negative number. It's going to be a twos complement byte array. 429 * We're going to leave the positive value in `data->data', but set the 430 * `data->negative' flag. That means we need to negate the 431 * twos-complement integer received. 432 */ 433 data->negative = 1; 434 data->length = len; 435 436 if (p[0] == 0xff) { 437 if (data->length == 1) { 438 /* One byte of all ones == -1 */ 439 q = data->data = malloc(1); 440 *q = 1; 441 data->length = 1; 442 if (size) 443 *size = 1; 444 return 0; 445 } 446 447 p++; 448 data->length--; 449 450 /* 451 * We could check if the next byte's high bit is set, which would 452 * be an error ("illegal padding" in OpenSSL). However, this would 453 * mean failing to accept certificates made by certain CAs that 454 * would read 8 bytes of RNG into a buffer, slap on length 8, then 455 * slap on the tag [UNIVERSAL INTEGER], and make that the 456 * serialNumber field's encoding, which then fails to parse in 457 * around 1 in 256 certificates. 458 * 459 * So let's not. 460 * 461 * if (p[0] & 0x80) 462 * return ASN1_PARSE_ERROR; // or a new error code 463 */ 464 } 465 data->data = malloc(data->length); 466 if (data->data == NULL) { 467 data->length = 0; 468 if (size) 469 *size = 0; 470 return ENOMEM; 471 } 472 473 /* 474 * Note that if `data->length' were zero, this would be UB because we 475 * underflow if data->length is zero even though we wouldn't actually 476 * dereference the byte before data->data. Thus we check above for 477 * that. 478 */ 479 q = &((unsigned char*)data->data)[data->length - 1]; 480 p += data->length - 1; 481 while (q >= (unsigned char*)data->data) { 482 /* *p XOR 0xff -> ~*p; we're dealing with twos complement */ 483 *q = *p ^ 0xff; 484 if (carry) 485 carry = !++*q; 486 p--; 487 q--; 488 } 489 } else { 490 data->negative = 0; 491 data->length = len; 492 493 if (p[0] == 0) { 494 p++; 495 data->length--; 496 } 497 data->data = malloc(data->length); 498 if (data->data == NULL && data->length != 0) { 499 data->length = 0; 500 if (size) 501 *size = 0; 502 return ENOMEM; 503 } 504 memcpy(data->data, p, data->length); 505 } 506 if (size) 507 *size = len; 508 return 0; 509 } 510 511 static int 512 generalizedtime2time (const char *s, time_t *t) 513 { 514 struct tm tm; 515 516 memset(&tm, 0, sizeof(tm)); 517 if (sscanf (s, "%04d%02d%02d%02d%02d%02dZ", 518 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 519 &tm.tm_min, &tm.tm_sec) != 6) { 520 if (sscanf (s, "%02d%02d%02d%02d%02d%02dZ", 521 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 522 &tm.tm_min, &tm.tm_sec) != 6) 523 return ASN1_BAD_TIMEFORMAT; 524 if (tm.tm_year < 50) 525 tm.tm_year += 2000; 526 else 527 tm.tm_year += 1900; 528 } 529 tm.tm_year -= 1900; 530 tm.tm_mon -= 1; 531 *t = _der_timegm (&tm); 532 return 0; 533 } 534 535 static int 536 der_get_time (const unsigned char *p, size_t len, 537 time_t *data, size_t *size) 538 { 539 char *times; 540 int e; 541 542 if (len == SIZE_MAX || len == 0) 543 return ASN1_BAD_LENGTH; 544 545 times = malloc(len + 1); 546 if (times == NULL) 547 return ENOMEM; 548 memcpy(times, p, len); 549 times[len] = '\0'; 550 e = generalizedtime2time(times, data); 551 free (times); 552 if(size) *size = len; 553 return e; 554 } 555 556 int 557 der_get_generalized_time (const unsigned char *p, size_t len, 558 time_t *data, size_t *size) 559 { 560 return der_get_time(p, len, data, size); 561 } 562 563 int 564 der_get_utctime (const unsigned char *p, size_t len, 565 time_t *data, size_t *size) 566 { 567 return der_get_time(p, len, data, size); 568 } 569 570 int 571 der_get_oid (const unsigned char *p, size_t len, 572 heim_oid *data, size_t *size) 573 { 574 size_t n; 575 size_t oldlen = len; 576 577 if (len < 1) 578 return ASN1_OVERRUN; 579 580 if (len == SIZE_MAX) 581 return ASN1_BAD_LENGTH; 582 583 if (len + 1 > UINT_MAX/sizeof(data->components[0])) 584 return ERANGE; 585 586 data->components = malloc((len + 1) * sizeof(data->components[0])); 587 if (data->components == NULL) 588 return ENOMEM; 589 data->components[0] = (*p) / 40; 590 data->components[1] = (*p) % 40; 591 --len; 592 ++p; 593 for (n = 2; len > 0; ++n) { 594 unsigned u = 0, u1; 595 596 do { 597 --len; 598 u1 = u * 128 + (*p++ % 128); 599 /* check that we don't overflow the element */ 600 if (u1 < u) { 601 der_free_oid(data); 602 return ASN1_OVERRUN; 603 } 604 u = u1; 605 } while (len > 0 && p[-1] & 0x80); 606 data->components[n] = u; 607 } 608 if (n > 2 && p[-1] & 0x80) { 609 der_free_oid (data); 610 return ASN1_OVERRUN; 611 } 612 data->length = n; 613 if (size) 614 *size = oldlen; 615 return 0; 616 } 617 618 int 619 der_get_tag (const unsigned char *p, size_t len, 620 Der_class *cls, Der_type *type, 621 unsigned int *tag, size_t *size) 622 { 623 size_t ret = 0; 624 if (len < 1) 625 return ASN1_OVERRUN; 626 *cls = (Der_class)(((*p) >> 6) & 0x03); 627 *type = (Der_type)(((*p) >> 5) & 0x01); 628 *tag = (*p) & 0x1f; 629 p++; len--; ret++; 630 if(*tag == 0x1f) { 631 unsigned int continuation; 632 unsigned int tag1; 633 *tag = 0; 634 do { 635 if(len < 1) 636 return ASN1_OVERRUN; 637 continuation = *p & 128; 638 tag1 = *tag * 128 + (*p % 128); 639 /* check that we don't overflow the tag */ 640 if (tag1 < *tag) 641 return ASN1_OVERFLOW; 642 *tag = tag1; 643 p++; len--; ret++; 644 } while(continuation); 645 } 646 if(size) *size = ret; 647 return 0; 648 } 649 650 int 651 der_match_tag (const unsigned char *p, size_t len, 652 Der_class cls, Der_type type, 653 unsigned int tag, size_t *size) 654 { 655 Der_type thistype; 656 int e; 657 658 e = der_match_tag2(p, len, cls, &thistype, tag, size); 659 if (e) return e; 660 if (thistype != type) return ASN1_BAD_ID; 661 return 0; 662 } 663 664 int 665 der_match_tag2 (const unsigned char *p, size_t len, 666 Der_class cls, Der_type *type, 667 unsigned int tag, size_t *size) 668 { 669 size_t l; 670 Der_class thisclass; 671 unsigned int thistag; 672 int e; 673 674 e = der_get_tag (p, len, &thisclass, type, &thistag, &l); 675 if (e) return e; 676 if (cls != thisclass) 677 return ASN1_BAD_ID; 678 if(tag > thistag) 679 return ASN1_MISPLACED_FIELD; 680 if(tag < thistag) 681 return ASN1_MISSING_FIELD; 682 if(size) *size = l; 683 return 0; 684 } 685 686 int 687 der_match_tag_and_length (const unsigned char *p, size_t len, 688 Der_class cls, Der_type *type, unsigned int tag, 689 size_t *length_ret, size_t *size) 690 { 691 size_t l, ret = 0; 692 int e; 693 694 e = der_match_tag2 (p, len, cls, type, tag, &l); 695 if (e) return e; 696 p += l; 697 len -= l; 698 ret += l; 699 e = der_get_length (p, len, length_ret, &l); 700 if (e) return e; 701 if(size) *size = ret + l; 702 return 0; 703 } 704 705 706 707 /* 708 * Old versions of DCE was based on a very early beta of the MIT code, 709 * which used MAVROS for ASN.1 encoding. MAVROS had the interesting 710 * feature that it encoded data in the forward direction, which has 711 * it's problems, since you have no idea how long the data will be 712 * until after you're done. MAVROS solved this by reserving one byte 713 * for length, and later, if the actual length was longer, it reverted 714 * to indefinite, BER style, lengths. The version of MAVROS used by 715 * the DCE people could apparently generate correct X.509 DER encodings, and 716 * did this by making space for the length after encoding, but 717 * unfortunately this feature wasn't used with Kerberos. 718 */ 719 720 int 721 _heim_fix_dce(size_t reallen, size_t *len) 722 { 723 if(reallen == ASN1_INDEFINITE) 724 return 1; 725 if(*len < reallen) 726 return -1; 727 *len = reallen; 728 return 0; 729 } 730 731 int 732 der_get_bit_string (const unsigned char *p, size_t len, 733 heim_bit_string *data, size_t *size) 734 { 735 if (len < 1) 736 return ASN1_OVERRUN; 737 if (p[0] > 7) 738 return ASN1_BAD_FORMAT; 739 if (len - 1 == 0 && p[0] != 0) 740 return ASN1_BAD_FORMAT; 741 /* check if any of the three upper bits are set 742 * any of them will cause a interger overrun */ 743 if ((len - 1) >> (sizeof(len) * 8 - 3)) 744 return ASN1_OVERRUN; 745 /* 746 * If there is data to copy, do that now. 747 */ 748 if (len - 1 > 0) { 749 data->length = (len - 1) * 8; 750 data->data = malloc(len - 1); 751 if (data->data == NULL) 752 return ENOMEM; 753 memcpy (data->data, p + 1, len - 1); 754 data->length -= p[0]; 755 } else { 756 data->data = NULL; 757 data->length = 0; 758 } 759 if(size) *size = len; 760 return 0; 761 } 762