diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 158 |
1 files changed, 86 insertions, 72 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index f04ec66bc7..3cc2146e45 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.59 2022/05/07 10:03:49 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.60 2022/05/07 10:13:56 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 | */ |
@@ -645,86 +645,89 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | |||
645 | } | 645 | } |
646 | 646 | ||
647 | static int | 647 | static int |
648 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | 648 | asn1_d2i_ex_primitive_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, |
649 | const ASN1_ITEM *it, int tag, int aclass, char opt) | 649 | int tag_number, int tag_class, char optional) |
650 | { | 650 | { |
651 | int ret = 0, utype; | 651 | CBS cbs_any, cbs_content, cbs_object, cbs_initial; |
652 | long plen; | 652 | char constructed, indefinite; |
653 | char cst, inf; | ||
654 | const unsigned char *p; | ||
655 | const unsigned char *content = NULL; | ||
656 | uint8_t *data = NULL; | 653 | uint8_t *data = NULL; |
657 | size_t data_len = 0; | 654 | size_t data_len = 0; |
658 | CBS cbs; | 655 | int utype = it->utype; |
656 | unsigned char oclass; | ||
657 | size_t length; | ||
659 | CBB cbb; | 658 | CBB cbb; |
660 | long len; | 659 | int tag_ret; |
660 | int ret = 0; | ||
661 | 661 | ||
662 | memset(&cbb, 0, sizeof(cbb)); | 662 | memset(&cbb, 0, sizeof(cbb)); |
663 | 663 | ||
664 | if (!pval) { | 664 | CBS_dup(cbs, &cbs_initial); |
665 | CBS_init(&cbs_content, NULL, 0); | ||
666 | CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs)); | ||
667 | |||
668 | if (pval == NULL) { | ||
665 | ASN1error(ASN1_R_ILLEGAL_NULL); | 669 | ASN1error(ASN1_R_ILLEGAL_NULL); |
666 | return 0; /* Should never happen */ | 670 | goto err; |
667 | } | 671 | } |
668 | 672 | ||
669 | if (it->itype == ASN1_ITYPE_MSTRING) { | 673 | if (it->itype == ASN1_ITYPE_MSTRING) { |
670 | utype = tag; | 674 | utype = tag_number; |
671 | tag = -1; | 675 | tag_number = -1; |
672 | } else | 676 | } |
673 | utype = it->utype; | ||
674 | 677 | ||
675 | if (utype == V_ASN1_ANY) { | 678 | if (utype == V_ASN1_ANY) { |
676 | /* If type is ANY need to figure out type from tag */ | 679 | /* Determine type from ASN.1 tag. */ |
677 | unsigned char oclass; | 680 | if (tag_number >= 0) { |
678 | if (tag >= 0) { | ||
679 | ASN1error(ASN1_R_ILLEGAL_TAGGED_ANY); | 681 | ASN1error(ASN1_R_ILLEGAL_TAGGED_ANY); |
680 | return 0; | 682 | goto err; |
681 | } | 683 | } |
682 | if (opt) { | 684 | if (optional) { |
683 | ASN1error(ASN1_R_ILLEGAL_OPTIONAL_ANY); | 685 | ASN1error(ASN1_R_ILLEGAL_OPTIONAL_ANY); |
684 | return 0; | 686 | goto err; |
685 | } | 687 | } |
686 | p = *in; | 688 | /* XXX - avoid reading the header twice for ANY. */ |
687 | ret = asn1_check_tag(NULL, &utype, &oclass, NULL, NULL, &p, | 689 | CBS_dup(&cbs_object, &cbs_any); |
688 | inlen, -1, 0, 0); | 690 | tag_ret = asn1_check_tag_cbs(&cbs_any, NULL, &utype, &oclass, |
689 | if (!ret) { | 691 | NULL, NULL, -1, 0, 0); |
692 | if (tag_ret != 1) { | ||
690 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 693 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
691 | return 0; | 694 | goto err; |
692 | } | 695 | } |
693 | if (oclass != V_ASN1_UNIVERSAL) | 696 | if (oclass != V_ASN1_UNIVERSAL) |
694 | utype = V_ASN1_OTHER; | 697 | utype = V_ASN1_OTHER; |
695 | } | 698 | } |
696 | if (tag == -1) { | 699 | |
697 | tag = utype; | 700 | if (tag_number == -1) { |
698 | aclass = V_ASN1_UNIVERSAL; | 701 | tag_number = utype; |
702 | tag_class = V_ASN1_UNIVERSAL; | ||
699 | } | 703 | } |
700 | p = *in; | 704 | |
701 | /* Check header */ | 705 | tag_ret = asn1_check_tag_cbs(&cbs_object, &length, NULL, NULL, &indefinite, |
702 | ret = asn1_check_tag(&plen, NULL, NULL, &inf, &cst, &p, inlen, tag, | 706 | &constructed, tag_number, tag_class, optional); |
703 | aclass, opt); | 707 | if (tag_ret == -1) { |
704 | if (!ret) { | 708 | ret = -1; |
709 | goto err; | ||
710 | } | ||
711 | if (tag_ret != 1) { | ||
705 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 712 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
706 | return 0; | 713 | goto err; |
707 | } else if (ret == -1) | 714 | } |
708 | return -1; | 715 | |
709 | ret = 0; | 716 | /* SEQUENCE and SET must be constructed. */ |
710 | /* SEQUENCE, SET and "OTHER" are left in encoded form */ | 717 | if ((utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET) && !constructed) { |
711 | if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || | 718 | ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); |
712 | (utype == V_ASN1_OTHER)) { | 719 | goto err; |
713 | if (utype != V_ASN1_OTHER && !cst) { | 720 | } |
714 | /* SEQUENCE and SET must be constructed */ | ||
715 | ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); | ||
716 | return 0; | ||
717 | } | ||
718 | 721 | ||
719 | content = *in; | 722 | /* SEQUENCE, SET and "OTHER" are left in encoded form. */ |
720 | if (plen < 0) | 723 | if (utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET || |
724 | utype == V_ASN1_OTHER) { | ||
725 | if (!asn1_find_end(&cbs_object, length, indefinite)) | ||
721 | goto err; | 726 | goto err; |
722 | CBS_init(&cbs, p, plen); | 727 | if (!CBS_get_bytes(&cbs_initial, &cbs_content, |
723 | if (!asn1_find_end(&cbs, plen, inf)) | 728 | CBS_offset(&cbs_object))) |
724 | goto err; | 729 | goto err; |
725 | p = CBS_data(&cbs); | 730 | } else if (constructed) { |
726 | len = p - content; | ||
727 | } else if (cst) { | ||
728 | /* | 731 | /* |
729 | * Should really check the internal tags are correct but | 732 | * Should really check the internal tags are correct but |
730 | * some things may get this wrong. The relevant specs | 733 | * some things may get this wrong. The relevant specs |
@@ -734,34 +737,24 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
734 | */ | 737 | */ |
735 | if (!CBB_init(&cbb, 0)) | 738 | if (!CBB_init(&cbb, 0)) |
736 | goto err; | 739 | goto err; |
737 | if (plen < 0) | 740 | if (!asn1_collect(&cbb, &cbs_object, indefinite, -1, |
741 | V_ASN1_UNIVERSAL, 0)) | ||
738 | goto err; | 742 | goto err; |
739 | CBS_init(&cbs, p, plen); | ||
740 | if (!asn1_collect(&cbb, &cbs, inf, -1, V_ASN1_UNIVERSAL, 0)) | ||
741 | goto err; | ||
742 | p = CBS_data(&cbs); | ||
743 | if (!CBB_finish(&cbb, &data, &data_len)) | 743 | if (!CBB_finish(&cbb, &data, &data_len)) |
744 | goto err; | 744 | goto err; |
745 | 745 | ||
746 | if (data_len > LONG_MAX) | 746 | CBS_init(&cbs_content, data, data_len); |
747 | goto err; | ||
748 | |||
749 | content = data; | ||
750 | len = data_len; | ||
751 | } else { | 747 | } else { |
752 | content = p; | 748 | if (!CBS_get_bytes(&cbs_object, &cbs_content, length)) |
753 | len = plen; | 749 | goto err; |
754 | p += plen; | ||
755 | } | 750 | } |
756 | 751 | ||
757 | /* We now have content length and type: translate into a structure */ | 752 | if (!asn1_ex_c2i(pval, &cbs_content, utype, it)) |
758 | if (len < 0) | ||
759 | goto err; | 753 | goto err; |
760 | CBS_init(&cbs, content, len); | 754 | |
761 | if (!asn1_ex_c2i(pval, &cbs, utype, it)) | 755 | if (!CBS_skip(cbs, CBS_offset(&cbs_object))) |
762 | goto err; | 756 | goto err; |
763 | 757 | ||
764 | *in = p; | ||
765 | ret = 1; | 758 | ret = 1; |
766 | 759 | ||
767 | err: | 760 | err: |
@@ -772,6 +765,27 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
772 | } | 765 | } |
773 | 766 | ||
774 | static int | 767 | static int |
768 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | ||
769 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional) | ||
770 | { | ||
771 | CBS cbs; | ||
772 | int ret; | ||
773 | |||
774 | if (inlen < 0) | ||
775 | return 0; | ||
776 | |||
777 | CBS_init(&cbs, *in, inlen); | ||
778 | |||
779 | ret = asn1_d2i_ex_primitive_cbs(pval, &cbs, it, tag_number, tag_class, | ||
780 | optional); | ||
781 | |||
782 | if (ret == 1) | ||
783 | *in = CBS_data(&cbs); | ||
784 | |||
785 | return ret; | ||
786 | } | ||
787 | |||
788 | static int | ||
775 | asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | 789 | asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) |
776 | { | 790 | { |
777 | ASN1_STRING *stmp; | 791 | ASN1_STRING *stmp; |