summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2022-05-17 12:23:52 +0000
committerjsing <>2022-05-17 12:23:52 +0000
commit440516cf733a3d776a7133a827812490af8d75e1 (patch)
treea9bc9123c236536286916e542b234437fde5b6ef /src
parent8b50bcf55793c7830584351b3cadc861113b9b41 (diff)
downloadopenbsd-440516cf733a3d776a7133a827812490af8d75e1.tar.gz
openbsd-440516cf733a3d776a7133a827812490af8d75e1.tar.bz2
openbsd-440516cf733a3d776a7133a827812490af8d75e1.zip
Refactor ASN.1 template functions before rewriting.
Change asn1_template_ex_d2i() so that we short circuit in the no explicit tagging case. Split out the SET OF/SEQUENCE OF handling from asn1_template_noexp_d2i() into a asn1_template_stack_of_d2i() function and simplify the remaining code. ok tb@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/asn1/tasn_dec.c278
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
535static int 531static int
536asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, 532asn1_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
624static int 620static int
625asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, 621asn1_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
741static int 713static int
714asn1_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
753static int
742asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, 754asn1_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{