diff options
Diffstat (limited to 'src/lib/libcrypto')
| -rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 278 |
1 files changed, 145 insertions, 133 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 744dde23c0..88b61a997d 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.68 2022/05/16 20:06:15 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.69 2022/05/17 12:23:52 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 | */ |
| @@ -528,10 +528,6 @@ ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
| 528 | return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, 0); | 528 | return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, 0); |
| 529 | } | 529 | } |
| 530 | 530 | ||
| 531 | /* Templates are handled with two separate functions. | ||
| 532 | * One handles any EXPLICIT tag and the other handles the rest. | ||
| 533 | */ | ||
| 534 | |||
| 535 | static int | 531 | static int |
| 536 | asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | 532 | asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, |
| 537 | const ASN1_TEMPLATE *tt, char opt, int depth) | 533 | const ASN1_TEMPLATE *tt, char opt, int depth) |
| @@ -541,6 +537,7 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | |||
| 541 | long len; | 537 | long len; |
| 542 | const unsigned char *p, *q; | 538 | const unsigned char *p, *q; |
| 543 | char exp_eoc; | 539 | char exp_eoc; |
| 540 | char cst; | ||
| 544 | 541 | ||
| 545 | if (!val) | 542 | if (!val) |
| 546 | return 0; | 543 | return 0; |
| @@ -550,48 +547,47 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | |||
| 550 | p = *in; | 547 | p = *in; |
| 551 | 548 | ||
| 552 | /* Check if EXPLICIT tag expected */ | 549 | /* Check if EXPLICIT tag expected */ |
| 553 | if (flags & ASN1_TFLG_EXPTAG) { | 550 | if ((flags & ASN1_TFLG_EXPTAG) == 0) |
| 554 | char cst; | 551 | return asn1_template_noexp_d2i(val, in, inlen, tt, opt, depth); |
| 555 | /* Need to work out amount of data available to the inner | 552 | |
| 556 | * content and where it starts: so read in EXPLICIT header to | 553 | /* Need to work out amount of data available to the inner |
| 557 | * get the info. | 554 | * content and where it starts: so read in EXPLICIT header to |
| 558 | */ | 555 | * get the info. |
| 559 | ret = asn1_check_tag(&len, NULL, NULL, &exp_eoc, &cst, &p, | 556 | */ |
| 560 | inlen, tt->tag, aclass, opt); | 557 | ret = asn1_check_tag(&len, NULL, NULL, &exp_eoc, &cst, &p, |
| 561 | q = p; | 558 | inlen, tt->tag, aclass, opt); |
| 562 | if (!ret) { | 559 | q = p; |
| 563 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 560 | if (!ret) { |
| 564 | return 0; | 561 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
| 565 | } else if (ret == -1) | 562 | return 0; |
| 566 | return -1; | 563 | } else if (ret == -1) |
| 567 | if (!cst) { | 564 | return -1; |
| 568 | ASN1error(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); | 565 | if (!cst) { |
| 569 | return 0; | 566 | ASN1error(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); |
| 570 | } | 567 | return 0; |
| 571 | /* We've found the field so it can't be OPTIONAL now */ | 568 | } |
| 572 | ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, depth); | 569 | /* We've found the field so it can't be OPTIONAL now */ |
| 573 | if (!ret) { | 570 | ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, depth); |
| 574 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 571 | if (!ret) { |
| 575 | return 0; | 572 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
| 573 | return 0; | ||
| 574 | } | ||
| 575 | /* We read the field in OK so update length */ | ||
| 576 | len -= p - q; | ||
| 577 | if (exp_eoc) { | ||
| 578 | /* If NDEF we must have an EOC here */ | ||
| 579 | if (!asn1_check_eoc(&p, len)) { | ||
| 580 | ASN1error(ASN1_R_MISSING_EOC); | ||
| 581 | goto err; | ||
| 576 | } | 582 | } |
| 577 | /* We read the field in OK so update length */ | 583 | } else { |
| 578 | len -= p - q; | 584 | /* Otherwise we must hit the EXPLICIT tag end or its |
| 579 | if (exp_eoc) { | 585 | * an error */ |
| 580 | /* If NDEF we must have an EOC here */ | 586 | if (len) { |
| 581 | if (!asn1_check_eoc(&p, len)) { | 587 | ASN1error(ASN1_R_EXPLICIT_LENGTH_MISMATCH); |
| 582 | ASN1error(ASN1_R_MISSING_EOC); | 588 | goto err; |
| 583 | goto err; | ||
| 584 | } | ||
| 585 | } else { | ||
| 586 | /* Otherwise we must hit the EXPLICIT tag end or its | ||
| 587 | * an error */ | ||
| 588 | if (len) { | ||
| 589 | ASN1error(ASN1_R_EXPLICIT_LENGTH_MISMATCH); | ||
| 590 | goto err; | ||
| 591 | } | ||
| 592 | } | 589 | } |
| 593 | } else | 590 | } |
| 594 | return asn1_template_noexp_d2i(val, in, inlen, tt, opt, depth); | ||
| 595 | 591 | ||
| 596 | *in = p; | 592 | *in = p; |
| 597 | return 1; | 593 | return 1; |
| @@ -622,112 +618,88 @@ asn1_template_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt, | |||
| 622 | } | 618 | } |
| 623 | 619 | ||
| 624 | static int | 620 | static int |
| 625 | asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | 621 | asn1_template_stack_of_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, |
| 626 | const ASN1_TEMPLATE *tt, char opt, int depth) | 622 | const ASN1_TEMPLATE *tt, char opt, int depth) |
| 627 | { | 623 | { |
| 628 | int flags, aclass; | ||
| 629 | int ret; | ||
| 630 | const unsigned char *p, *q; | 624 | const unsigned char *p, *q; |
| 625 | int sktag, skaclass; | ||
| 626 | char sk_eoc; | ||
| 627 | long len; | ||
| 628 | int ret; | ||
| 631 | 629 | ||
| 632 | if (!val) | 630 | /* SET OF, SEQUENCE OF */ |
| 633 | return 0; | ||
| 634 | flags = tt->flags; | ||
| 635 | aclass = flags & ASN1_TFLG_TAG_CLASS; | ||
| 636 | 631 | ||
| 637 | p = *in; | 632 | p = *in; |
| 638 | q = p; | 633 | q = p; |
| 639 | 634 | ||
| 640 | if (flags & ASN1_TFLG_SK_MASK) { | 635 | /* First work out expected inner tag value */ |
| 641 | /* SET OF, SEQUENCE OF */ | 636 | if (tt->flags & ASN1_TFLG_IMPTAG) { |
| 642 | int sktag, skaclass; | 637 | sktag = tt->tag; |
| 643 | char sk_eoc; | 638 | skaclass = tt->flags & ASN1_TFLG_TAG_CLASS; |
| 644 | /* First work out expected inner tag value */ | 639 | } else { |
| 645 | if (flags & ASN1_TFLG_IMPTAG) { | 640 | skaclass = V_ASN1_UNIVERSAL; |
| 646 | sktag = tt->tag; | 641 | if (tt->flags & ASN1_TFLG_SET_OF) |
| 647 | skaclass = aclass; | 642 | sktag = V_ASN1_SET; |
| 648 | } else { | 643 | else |
| 649 | skaclass = V_ASN1_UNIVERSAL; | 644 | sktag = V_ASN1_SEQUENCE; |
| 650 | if (flags & ASN1_TFLG_SET_OF) | 645 | } |
| 651 | sktag = V_ASN1_SET; | 646 | /* Get the tag */ |
| 652 | else | 647 | ret = asn1_check_tag(&len, NULL, NULL, &sk_eoc, NULL, &p, inlen, |
| 653 | sktag = V_ASN1_SEQUENCE; | 648 | sktag, skaclass, opt); |
| 654 | } | 649 | if (!ret) { |
| 655 | /* Get the tag */ | 650 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
| 656 | ret = asn1_check_tag(&len, NULL, NULL, &sk_eoc, NULL, &p, len, | 651 | return 0; |
| 657 | sktag, skaclass, opt); | 652 | } else if (ret == -1) |
| 658 | if (!ret) { | 653 | return -1; |
| 659 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 654 | if (!*val) |
| 660 | return 0; | 655 | *val = (ASN1_VALUE *)sk_new_null(); |
| 661 | } else if (ret == -1) | 656 | else { |
| 662 | return -1; | 657 | /* We've got a valid STACK: free up any items present */ |
| 663 | if (!*val) | 658 | STACK_OF(ASN1_VALUE) *sktmp = |
| 664 | *val = (ASN1_VALUE *)sk_new_null(); | 659 | (STACK_OF(ASN1_VALUE) *)*val; |
| 665 | else { | 660 | ASN1_VALUE *vtmp; |
| 666 | /* We've got a valid STACK: free up any items present */ | 661 | while (sk_ASN1_VALUE_num(sktmp) > 0) { |
| 667 | STACK_OF(ASN1_VALUE) *sktmp = | 662 | vtmp = sk_ASN1_VALUE_pop(sktmp); |
| 668 | (STACK_OF(ASN1_VALUE) *)*val; | 663 | ASN1_item_ex_free(&vtmp, |
| 669 | ASN1_VALUE *vtmp; | 664 | tt->item); |
| 670 | while (sk_ASN1_VALUE_num(sktmp) > 0) { | ||
| 671 | vtmp = sk_ASN1_VALUE_pop(sktmp); | ||
| 672 | ASN1_item_ex_free(&vtmp, | ||
| 673 | tt->item); | ||
| 674 | } | ||
| 675 | } | 665 | } |
| 666 | } | ||
| 676 | 667 | ||
| 677 | if (!*val) { | 668 | if (!*val) { |
| 678 | ASN1error(ERR_R_MALLOC_FAILURE); | 669 | ASN1error(ERR_R_MALLOC_FAILURE); |
| 679 | goto err; | 670 | goto err; |
| 680 | } | 671 | } |
| 681 | 672 | ||
| 682 | /* Read as many items as we can */ | 673 | /* Read as many items as we can */ |
| 683 | while (len > 0) { | 674 | while (len > 0) { |
| 684 | ASN1_VALUE *skfield; | 675 | ASN1_VALUE *skfield; |
| 685 | q = p; | 676 | q = p; |
| 686 | /* See if EOC found */ | 677 | /* See if EOC found */ |
| 687 | if (asn1_check_eoc(&p, len)) { | 678 | if (asn1_check_eoc(&p, len)) { |
| 688 | if (!sk_eoc) { | 679 | if (!sk_eoc) { |
| 689 | ASN1error(ASN1_R_UNEXPECTED_EOC); | 680 | ASN1error(ASN1_R_UNEXPECTED_EOC); |
| 690 | goto err; | ||
| 691 | } | ||
| 692 | len -= p - q; | ||
| 693 | sk_eoc = 0; | ||
| 694 | break; | ||
| 695 | } | ||
| 696 | skfield = NULL; | ||
| 697 | if (!asn1_item_ex_d2i(&skfield, &p, len, | ||
| 698 | tt->item, -1, 0, 0, depth)) { | ||
| 699 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
| 700 | goto err; | 681 | goto err; |
| 701 | } | 682 | } |
| 702 | len -= p - q; | 683 | len -= p - q; |
| 703 | if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, | 684 | sk_eoc = 0; |
| 704 | skfield)) { | 685 | break; |
| 705 | ASN1error(ERR_R_MALLOC_FAILURE); | ||
| 706 | goto err; | ||
| 707 | } | ||
| 708 | } | ||
| 709 | if (sk_eoc) { | ||
| 710 | ASN1error(ASN1_R_MISSING_EOC); | ||
| 711 | goto err; | ||
| 712 | } | 686 | } |
| 713 | } else if (flags & ASN1_TFLG_IMPTAG) { | 687 | skfield = NULL; |
| 714 | /* IMPLICIT tagging */ | 688 | if (!asn1_item_ex_d2i(&skfield, &p, len, |
| 715 | ret = asn1_item_ex_d2i(val, &p, len, | 689 | tt->item, -1, 0, 0, depth)) { |
| 716 | tt->item, tt->tag, aclass, opt, depth); | ||
| 717 | if (!ret) { | ||
| 718 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 690 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
| 719 | goto err; | 691 | goto err; |
| 720 | } else if (ret == -1) | 692 | } |
| 721 | return -1; | 693 | len -= p - q; |
| 722 | } else { | 694 | if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, |
| 723 | /* Nothing special */ | 695 | skfield)) { |
| 724 | ret = asn1_item_ex_d2i(val, &p, len, tt->item, -1, 0, | 696 | ASN1error(ERR_R_MALLOC_FAILURE); |
| 725 | opt, depth); | ||
| 726 | if (!ret) { | ||
| 727 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
| 728 | goto err; | 697 | goto err; |
| 729 | } else if (ret == -1) | 698 | } |
| 730 | return -1; | 699 | } |
| 700 | if (sk_eoc) { | ||
| 701 | ASN1error(ASN1_R_MISSING_EOC); | ||
| 702 | goto err; | ||
| 731 | } | 703 | } |
| 732 | 704 | ||
| 733 | *in = p; | 705 | *in = p; |
| @@ -739,6 +711,46 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | |||
| 739 | } | 711 | } |
| 740 | 712 | ||
| 741 | static int | 713 | static int |
| 714 | asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | ||
| 715 | const ASN1_TEMPLATE *tt, char opt, int depth) | ||
| 716 | { | ||
| 717 | const unsigned char *p; | ||
| 718 | int tag_number, tag_class; | ||
| 719 | int ret; | ||
| 720 | |||
| 721 | if (!val) | ||
| 722 | return 0; | ||
| 723 | |||
| 724 | p = *in; | ||
| 725 | |||
| 726 | if ((tt->flags & ASN1_TFLG_SK_MASK) != 0) | ||
| 727 | return asn1_template_stack_of_d2i(val, in, len, tt, opt, depth); | ||
| 728 | |||
| 729 | tag_number = -1; | ||
| 730 | tag_class = V_ASN1_UNIVERSAL; | ||
| 731 | |||
| 732 | /* See if we need to use IMPLICIT tagging. */ | ||
| 733 | if ((tt->flags & ASN1_TFLG_IMPTAG) != 0) { | ||
| 734 | tag_number = tt->tag; | ||
| 735 | tag_class = tt->flags & ASN1_TFLG_TAG_CLASS; | ||
| 736 | } | ||
| 737 | |||
| 738 | ret = asn1_item_ex_d2i(val, &p, len, tt->item, tag_number, tag_class, opt, depth); | ||
| 739 | if (!ret) { | ||
| 740 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
| 741 | goto err; | ||
| 742 | } else if (ret == -1) | ||
| 743 | return -1; | ||
| 744 | |||
| 745 | *in = p; | ||
| 746 | return 1; | ||
| 747 | |||
| 748 | err: | ||
| 749 | ASN1_template_free(val, tt); | ||
| 750 | return 0; | ||
| 751 | } | ||
| 752 | |||
| 753 | static int | ||
| 742 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | 754 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, |
| 743 | int tag_number, int tag_class, char optional) | 755 | int tag_number, int tag_class, char optional) |
| 744 | { | 756 | { |
