summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/asn1/tasn_dec.c158
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
647static int 647static int
648asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, 648asn1_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
774static int 767static int
768asn1_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
788static int
775asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) 789asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it)
776{ 790{
777 ASN1_STRING *stmp; 791 ASN1_STRING *stmp;