diff options
| author | jsing <> | 2022-05-10 18:40:06 +0000 |
|---|---|---|
| committer | jsing <> | 2022-05-10 18:40:06 +0000 |
| commit | cd3bc37de37e78ce7bf99ab17cc73927e7bc8257 (patch) | |
| tree | 7ee08760131b7db74fd74e40cdaf894fc9072f12 /src/lib/libcrypto | |
| parent | 92cff24279888a655e71809016c6b1d366158c34 (diff) | |
| download | openbsd-cd3bc37de37e78ce7bf99ab17cc73927e7bc8257.tar.gz openbsd-cd3bc37de37e78ce7bf99ab17cc73927e7bc8257.tar.bz2 openbsd-cd3bc37de37e78ce7bf99ab17cc73927e7bc8257.zip | |
Rewrite asn1_item_ex_d2i() using CBS.
This requires a few wrappers to call into some non-CBS functions, however
we can now remove the asn1_d2i_ex_primitive() wrapper as there are no
longer any non-CBS callers.
ok tb@
Diffstat (limited to 'src/lib/libcrypto')
| -rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 183 |
1 files changed, 125 insertions, 58 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index de0b819064..f3e032c1c1 100644 --- a/src/lib/libcrypto/asn1/tasn_dec.c +++ b/src/lib/libcrypto/asn1/tasn_dec.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tasn_dec.c,v 1.62 2022/05/10 05:19:22 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.63 2022/05/10 18:40:06 jsing Exp $ */ |
| 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
| 3 | * project 2000. | 3 | * project 2000. |
| 4 | */ | 4 | */ |
| @@ -83,13 +83,16 @@ static int asn1_collect(CBB *cbb, CBS *cbs, char indefinite, int expected_tag, | |||
| 83 | int expected_class, int depth); | 83 | int expected_class, int depth); |
| 84 | 84 | ||
| 85 | static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, | 85 | static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, |
| 86 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt, int depth); | 86 | long len, const ASN1_ITEM *it, int tag_number, int tag_class, char optional, |
| 87 | int depth); | ||
| 88 | static int asn1_template_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, | ||
| 89 | const ASN1_TEMPLATE *tt, char optional, int depth); | ||
| 87 | static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, | 90 | static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, |
| 88 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); | 91 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); |
| 89 | static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, | 92 | static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, |
| 90 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); | 93 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); |
| 91 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, | 94 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, |
| 92 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt); | 95 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional); |
| 93 | static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, | 96 | static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, |
| 94 | const ASN1_ITEM *it); | 97 | const ASN1_ITEM *it); |
| 95 | 98 | ||
| @@ -218,6 +221,26 @@ asn1_item_ex_d2i_choice(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
| 218 | } | 221 | } |
| 219 | 222 | ||
| 220 | static int | 223 | static int |
| 224 | asn1_item_ex_d2i_choice_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | ||
| 225 | int tag_number, int tag_class, char optional, int depth) | ||
| 226 | { | ||
| 227 | const unsigned char *p; | ||
| 228 | int ret; | ||
| 229 | |||
| 230 | if (CBS_len(cbs) > LONG_MAX) | ||
| 231 | return 0; | ||
| 232 | |||
| 233 | p = CBS_data(cbs); | ||
| 234 | ret = asn1_item_ex_d2i_choice(pval, &p, (long)CBS_len(cbs), it, | ||
| 235 | tag_number, tag_class, optional, depth); | ||
| 236 | if (ret == 1) { | ||
| 237 | if (!CBS_skip(cbs, p - CBS_data(cbs))) | ||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | return ret; | ||
| 241 | } | ||
| 242 | |||
| 243 | static int | ||
| 221 | asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, const unsigned char **in, long len, | 244 | asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, const unsigned char **in, long len, |
| 222 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) | 245 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) |
| 223 | { | 246 | { |
| @@ -390,22 +413,43 @@ asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
| 390 | return 0; | 413 | return 0; |
| 391 | } | 414 | } |
| 392 | 415 | ||
| 416 | static int | ||
| 417 | asn1_item_ex_d2i_sequence_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | ||
| 418 | int tag_number, int tag_class, char optional, int depth) | ||
| 419 | { | ||
| 420 | const unsigned char *p; | ||
| 421 | int ret; | ||
| 422 | |||
| 423 | if (CBS_len(cbs) > LONG_MAX) | ||
| 424 | return 0; | ||
| 425 | |||
| 426 | p = CBS_data(cbs); | ||
| 427 | ret = asn1_item_ex_d2i_sequence(pval, &p, (long)CBS_len(cbs), it, | ||
| 428 | tag_number, tag_class, optional, depth); | ||
| 429 | if (ret == 1) { | ||
| 430 | if (!CBS_skip(cbs, p - CBS_data(cbs))) | ||
| 431 | return 0; | ||
| 432 | } | ||
| 433 | return ret; | ||
| 434 | } | ||
| 435 | |||
| 393 | /* | 436 | /* |
| 394 | * Decode an item, taking care of IMPLICIT tagging, if any. | 437 | * Decode an item, taking care of IMPLICIT tagging, if any. |
| 395 | * If 'opt' set and tag mismatch return -1 to handle OPTIONAL | 438 | * If 'opt' set and tag mismatch return -1 to handle OPTIONAL |
| 396 | */ | 439 | */ |
| 397 | static int | 440 | static int |
| 398 | asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 441 | asn1_item_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, |
| 399 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) | 442 | int tag_number, int tag_class, char optional, int depth) |
| 400 | { | 443 | { |
| 401 | const ASN1_EXTERN_FUNCS *ef; | 444 | const ASN1_EXTERN_FUNCS *ef = it->funcs; |
| 402 | ASN1_TLC ctx = { 0 }; | ||
| 403 | const unsigned char *p = NULL; | 445 | const unsigned char *p = NULL; |
| 446 | ASN1_TLC ctx = { 0 }; | ||
| 447 | CBS cbs_mstring; | ||
| 404 | unsigned char oclass; | 448 | unsigned char oclass; |
| 405 | int otag; | 449 | int otag; |
| 406 | int ret = 0; | 450 | int ret = 0; |
| 407 | 451 | ||
| 408 | if (!pval) | 452 | if (pval == NULL) |
| 409 | return 0; | 453 | return 0; |
| 410 | 454 | ||
| 411 | if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { | 455 | if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { |
| @@ -415,23 +459,23 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
| 415 | 459 | ||
| 416 | switch (it->itype) { | 460 | switch (it->itype) { |
| 417 | case ASN1_ITYPE_PRIMITIVE: | 461 | case ASN1_ITYPE_PRIMITIVE: |
| 418 | if (it->templates) { | 462 | if (it->templates != NULL) { |
| 419 | /* tagging or OPTIONAL is currently illegal on an item | 463 | /* |
| 464 | * Tagging or OPTIONAL is currently illegal on an item | ||
| 420 | * template because the flags can't get passed down. | 465 | * template because the flags can't get passed down. |
| 421 | * In practice this isn't a problem: we include the | 466 | * In practice this isn't a problem: we include the |
| 422 | * relevant flags from the item template in the | 467 | * relevant flags from the item template in the |
| 423 | * template itself. | 468 | * template itself. |
| 424 | */ | 469 | */ |
| 425 | if ((tag != -1) || opt) { | 470 | if (tag_number != -1 || optional) { |
| 426 | ASN1error(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); | 471 | ASN1error(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); |
| 427 | goto err; | 472 | goto err; |
| 428 | } | 473 | } |
| 429 | return asn1_template_ex_d2i(pval, in, len, | 474 | return asn1_template_ex_d2i_cbs(pval, cbs, |
| 430 | it->templates, opt, depth); | 475 | it->templates, optional, depth); |
| 431 | } | 476 | } |
| 432 | return asn1_d2i_ex_primitive(pval, in, len, it, | 477 | return asn1_d2i_ex_primitive(pval, cbs, it, tag_number, |
| 433 | tag, aclass, opt); | 478 | tag_class, optional); |
| 434 | break; | ||
| 435 | 479 | ||
| 436 | case ASN1_ITYPE_MSTRING: | 480 | case ASN1_ITYPE_MSTRING: |
| 437 | /* | 481 | /* |
| @@ -439,52 +483,54 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
| 439 | * tagging, so if tag != -1, then this looks like an error in | 483 | * tagging, so if tag != -1, then this looks like an error in |
| 440 | * the template. | 484 | * the template. |
| 441 | */ | 485 | */ |
| 442 | if (tag != -1) { | 486 | if (tag_number != -1) { |
| 443 | ASN1error(ASN1_R_BAD_TEMPLATE); | 487 | ASN1error(ASN1_R_BAD_TEMPLATE); |
| 444 | goto err; | 488 | goto err; |
| 445 | } | 489 | } |
| 446 | 490 | ||
| 447 | p = *in; | 491 | /* XXX - avoid reading the header twice for MSTRING. */ |
| 448 | /* Just read in tag and class */ | 492 | CBS_dup(cbs, &cbs_mstring); |
| 449 | ret = asn1_check_tag(NULL, &otag, &oclass, NULL, NULL, &p, len, | 493 | if (asn1_check_tag_cbs(&cbs_mstring, NULL, &otag, &oclass, |
| 450 | -1, 0, 1); | 494 | NULL, NULL, -1, 0, 1) != 1) { |
| 451 | if (!ret) { | ||
| 452 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 495 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
| 453 | goto err; | 496 | goto err; |
| 454 | } | 497 | } |
| 455 | 498 | ||
| 456 | /* Must be UNIVERSAL class */ | 499 | /* Must be UNIVERSAL class */ |
| 457 | if (oclass != V_ASN1_UNIVERSAL) { | 500 | if (oclass != V_ASN1_UNIVERSAL) { |
| 458 | /* If OPTIONAL, assume this is OK */ | 501 | if (optional) |
| 459 | if (opt) | ||
| 460 | return -1; | 502 | return -1; |
| 461 | ASN1error(ASN1_R_MSTRING_NOT_UNIVERSAL); | 503 | ASN1error(ASN1_R_MSTRING_NOT_UNIVERSAL); |
| 462 | goto err; | 504 | goto err; |
| 463 | } | 505 | } |
| 464 | /* Check tag matches bit map */ | 506 | /* Check tag matches bit map */ |
| 465 | if (!(ASN1_tag2bit(otag) & it->utype)) { | 507 | if (!(ASN1_tag2bit(otag) & it->utype)) { |
| 466 | /* If OPTIONAL, assume this is OK */ | 508 | if (optional) |
| 467 | if (opt) | ||
| 468 | return -1; | 509 | return -1; |
| 469 | ASN1error(ASN1_R_MSTRING_WRONG_TAG); | 510 | ASN1error(ASN1_R_MSTRING_WRONG_TAG); |
| 470 | goto err; | 511 | goto err; |
| 471 | } | 512 | } |
| 472 | return asn1_d2i_ex_primitive(pval, in, len, | 513 | return asn1_d2i_ex_primitive(pval, cbs, it, otag, 0, 0); |
| 473 | it, otag, 0, 0); | ||
| 474 | 514 | ||
| 475 | case ASN1_ITYPE_EXTERN: | 515 | case ASN1_ITYPE_EXTERN: |
| 476 | /* Use new style d2i */ | 516 | if (CBS_len(cbs) > LONG_MAX) |
| 477 | ef = it->funcs; | 517 | return 0; |
| 478 | return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, &ctx); | 518 | p = CBS_data(cbs); |
| 519 | if ((ret = ef->asn1_ex_d2i(pval, &p, (long)CBS_len(cbs), it, | ||
| 520 | tag_number, tag_class, optional, &ctx)) == 1) { | ||
| 521 | if (!CBS_skip(cbs, p - CBS_data(cbs))) | ||
| 522 | goto err; | ||
| 523 | } | ||
| 524 | return ret; | ||
| 479 | 525 | ||
| 480 | case ASN1_ITYPE_CHOICE: | 526 | case ASN1_ITYPE_CHOICE: |
| 481 | return asn1_item_ex_d2i_choice(pval, in, len, it, tag, | 527 | return asn1_item_ex_d2i_choice_cbs(pval, cbs, it, tag_number, |
| 482 | aclass, opt, depth); | 528 | tag_class, optional, depth); |
| 483 | 529 | ||
| 484 | case ASN1_ITYPE_NDEF_SEQUENCE: | 530 | case ASN1_ITYPE_NDEF_SEQUENCE: |
| 485 | case ASN1_ITYPE_SEQUENCE: | 531 | case ASN1_ITYPE_SEQUENCE: |
| 486 | return asn1_item_ex_d2i_sequence(pval, in, len, it, tag, | 532 | return asn1_item_ex_d2i_sequence_cbs(pval, cbs, it, tag_number, |
| 487 | aclass, opt, depth); | 533 | tag_class, optional, depth); |
| 488 | 534 | ||
| 489 | default: | 535 | default: |
| 490 | return 0; | 536 | return 0; |
| @@ -498,6 +544,28 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
| 498 | return 0; | 544 | return 0; |
| 499 | } | 545 | } |
| 500 | 546 | ||
| 547 | static int | ||
| 548 | asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen, | ||
| 549 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional, | ||
| 550 | int depth) | ||
| 551 | { | ||
| 552 | CBS cbs; | ||
| 553 | int ret; | ||
| 554 | |||
| 555 | if (inlen < 0) | ||
| 556 | return 0; | ||
| 557 | |||
| 558 | CBS_init(&cbs, *in, inlen); | ||
| 559 | |||
| 560 | ret = asn1_item_ex_d2i_cbs(pval, &cbs, it, tag_number, tag_class, | ||
| 561 | optional, depth); | ||
| 562 | |||
| 563 | if (ret == 1) | ||
| 564 | *in = CBS_data(&cbs); | ||
| 565 | |||
| 566 | return ret; | ||
| 567 | } | ||
| 568 | |||
| 501 | int | 569 | int |
| 502 | ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 570 | ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
| 503 | const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) | 571 | const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) |
| @@ -579,6 +647,26 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | |||
| 579 | } | 647 | } |
| 580 | 648 | ||
| 581 | static int | 649 | static int |
| 650 | asn1_template_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt, | ||
| 651 | char optional, int depth) | ||
| 652 | { | ||
| 653 | const unsigned char *p; | ||
| 654 | int ret; | ||
| 655 | |||
| 656 | if (CBS_len(cbs) > LONG_MAX) | ||
| 657 | return 0; | ||
| 658 | |||
| 659 | p = CBS_data(cbs); | ||
| 660 | ret = asn1_template_ex_d2i(pval, &p, (long)CBS_len(cbs), tt, | ||
| 661 | optional, depth); | ||
| 662 | if (ret == 1) { | ||
| 663 | if (!CBS_skip(cbs, p - CBS_data(cbs))) | ||
| 664 | return 0; | ||
| 665 | } | ||
| 666 | return ret; | ||
| 667 | } | ||
| 668 | |||
| 669 | static int | ||
| 582 | asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | 670 | asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, |
| 583 | const ASN1_TEMPLATE *tt, char opt, int depth) | 671 | const ASN1_TEMPLATE *tt, char opt, int depth) |
| 584 | { | 672 | { |
| @@ -696,7 +784,7 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | |||
| 696 | } | 784 | } |
| 697 | 785 | ||
| 698 | static int | 786 | static int |
| 699 | asn1_d2i_ex_primitive_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | 787 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, |
| 700 | int tag_number, int tag_class, char optional) | 788 | int tag_number, int tag_class, char optional) |
| 701 | { | 789 | { |
| 702 | CBS cbs_any, cbs_content, cbs_object, cbs_initial; | 790 | CBS cbs_any, cbs_content, cbs_object, cbs_initial; |
| @@ -816,27 +904,6 @@ asn1_d2i_ex_primitive_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | |||
| 816 | } | 904 | } |
| 817 | 905 | ||
| 818 | static int | 906 | static int |
| 819 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | ||
| 820 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional) | ||
| 821 | { | ||
| 822 | CBS cbs; | ||
| 823 | int ret; | ||
| 824 | |||
| 825 | if (inlen < 0) | ||
| 826 | return 0; | ||
| 827 | |||
| 828 | CBS_init(&cbs, *in, inlen); | ||
| 829 | |||
| 830 | ret = asn1_d2i_ex_primitive_cbs(pval, &cbs, it, tag_number, tag_class, | ||
| 831 | optional); | ||
| 832 | |||
| 833 | if (ret == 1) | ||
| 834 | *in = CBS_data(&cbs); | ||
| 835 | |||
| 836 | return ret; | ||
| 837 | } | ||
| 838 | |||
| 839 | static int | ||
| 840 | asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | 907 | asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) |
| 841 | { | 908 | { |
| 842 | ASN1_STRING *stmp; | 909 | ASN1_STRING *stmp; |
