diff options
author | jsing <> | 2022-03-13 14:58:14 +0000 |
---|---|---|
committer | jsing <> | 2022-03-13 14:58:14 +0000 |
commit | be7b42f7987f9d00704bbfd3d473b8f2256a02af (patch) | |
tree | 36f685d9bd7666801c581d5dd900e750fd99b22a /src/lib | |
parent | 924b94dac6d48df7daea80927390c63e10863ed6 (diff) | |
download | openbsd-be7b42f7987f9d00704bbfd3d473b8f2256a02af.tar.gz openbsd-be7b42f7987f9d00704bbfd3d473b8f2256a02af.tar.bz2 openbsd-be7b42f7987f9d00704bbfd3d473b8f2256a02af.zip |
Remove free_cont from asn1_d2i_ex_primitive()/asn1_ex_c2i().
The constructed ASN.1 handling in asn1_d2i_ex_primitive() and asn1_ex_c2i()
currently has code to potentially avoid a malloc/memcpy - this is a less
common code path and it introduces a bunch of complexity for minimal gain.
In particular, we're manually adding a trailing NUL when ASN1_STRING_set()
would already do that for us, plus we currently manually free() the data on
an ASN1_STRING, rather than using freezero().
ok inoguchi@ tb@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/asn1/asn1_locl.h | 4 | ||||
-rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 77 |
2 files changed, 31 insertions, 50 deletions
diff --git a/src/lib/libcrypto/asn1/asn1_locl.h b/src/lib/libcrypto/asn1/asn1_locl.h index bb6a9fc91a..9a29a2b13f 100644 --- a/src/lib/libcrypto/asn1/asn1_locl.h +++ b/src/lib/libcrypto/asn1/asn1_locl.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: asn1_locl.h,v 1.21 2022/03/02 11:28:00 jsing Exp $ */ | 1 | /* $OpenBSD: asn1_locl.h,v 1.22 2022/03/13 14:58:14 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 2006. | 3 | * project 2006. |
4 | */ | 4 | */ |
@@ -161,8 +161,6 @@ struct x509_crl_method_st { | |||
161 | int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk); | 161 | int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk); |
162 | }; | 162 | }; |
163 | 163 | ||
164 | int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); | ||
165 | |||
166 | int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); | 164 | int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); |
167 | int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it); | 165 | int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it); |
168 | 166 | ||
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 8f41deef8d..d475c99676 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.48 2022/01/07 12:24:17 tb Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.49 2022/03/13 14:58:14 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 | */ |
@@ -95,6 +95,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, | |||
95 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, | 95 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, |
96 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt, | 96 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt, |
97 | ASN1_TLC *ctx); | 97 | ASN1_TLC *ctx); |
98 | static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, | ||
99 | int utype, const ASN1_ITEM *it); | ||
98 | 100 | ||
99 | static void | 101 | static void |
100 | asn1_tlc_invalidate(ASN1_TLC *ctx) | 102 | asn1_tlc_invalidate(ASN1_TLC *ctx) |
@@ -662,9 +664,9 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
662 | { | 664 | { |
663 | int ret = 0, utype; | 665 | int ret = 0, utype; |
664 | long plen; | 666 | long plen; |
665 | char cst, inf, free_cont = 0; | 667 | char cst, inf; |
666 | const unsigned char *p; | 668 | const unsigned char *p; |
667 | const unsigned char *cont = NULL; | 669 | const unsigned char *content = NULL; |
668 | uint8_t *data = NULL; | 670 | uint8_t *data = NULL; |
669 | size_t data_len = 0; | 671 | size_t data_len = 0; |
670 | CBB cbb; | 672 | CBB cbb; |
@@ -732,14 +734,14 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
732 | return 0; | 734 | return 0; |
733 | } | 735 | } |
734 | 736 | ||
735 | cont = *in; | 737 | content = *in; |
736 | /* If indefinite length constructed find the real end */ | 738 | /* If indefinite length constructed find the real end */ |
737 | if (inf) { | 739 | if (inf) { |
738 | if (!asn1_find_end(&p, plen, inf)) | 740 | if (!asn1_find_end(&p, plen, inf)) |
739 | goto err; | 741 | goto err; |
740 | len = p - cont; | 742 | len = p - content; |
741 | } else { | 743 | } else { |
742 | len = p - cont + plen; | 744 | len = p - content + plen; |
743 | p += plen; | 745 | p += plen; |
744 | } | 746 | } |
745 | } else if (cst) { | 747 | } else if (cst) { |
@@ -754,29 +756,22 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
754 | goto err; | 756 | goto err; |
755 | if (!asn1_collect(&cbb, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) | 757 | if (!asn1_collect(&cbb, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) |
756 | goto err; | 758 | goto err; |
757 | |||
758 | /* Append a final NUL to string. */ | ||
759 | if (!CBB_add_u8(&cbb, 0)) | ||
760 | goto err; | ||
761 | |||
762 | if (!CBB_finish(&cbb, &data, &data_len)) | 759 | if (!CBB_finish(&cbb, &data, &data_len)) |
763 | goto err; | 760 | goto err; |
764 | 761 | ||
765 | free_cont = 1; | 762 | if (data_len > LONG_MAX) |
766 | |||
767 | if (data_len < 1 || data_len > LONG_MAX) | ||
768 | goto err; | 763 | goto err; |
769 | 764 | ||
770 | cont = data; | 765 | content = data; |
771 | len = data_len - 1; | 766 | len = data_len; |
772 | } else { | 767 | } else { |
773 | cont = p; | 768 | content = p; |
774 | len = plen; | 769 | len = plen; |
775 | p += plen; | 770 | p += plen; |
776 | } | 771 | } |
777 | 772 | ||
778 | /* We now have content length and type: translate into a structure */ | 773 | /* We now have content length and type: translate into a structure */ |
779 | if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) | 774 | if (!asn1_ex_c2i(pval, content, len, utype, it)) |
780 | goto err; | 775 | goto err; |
781 | 776 | ||
782 | *in = p; | 777 | *in = p; |
@@ -784,18 +779,16 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
784 | 779 | ||
785 | err: | 780 | err: |
786 | CBB_cleanup(&cbb); | 781 | CBB_cleanup(&cbb); |
787 | 782 | freezero(data, data_len); | |
788 | if (free_cont) | ||
789 | freezero(data, data_len); | ||
790 | 783 | ||
791 | return ret; | 784 | return ret; |
792 | } | 785 | } |
793 | 786 | ||
794 | /* Translate ASN1 content octets into a structure */ | 787 | /* Translate ASN1 content octets into a structure */ |
795 | 788 | ||
796 | int | 789 | static int |
797 | asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, | 790 | asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype, |
798 | char *free_cont, const ASN1_ITEM *it) | 791 | const ASN1_ITEM *it) |
799 | { | 792 | { |
800 | ASN1_VALUE **opval = NULL; | 793 | ASN1_VALUE **opval = NULL; |
801 | ASN1_STRING *stmp; | 794 | ASN1_STRING *stmp; |
@@ -805,10 +798,11 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, | |||
805 | 798 | ||
806 | if (it->funcs != NULL) { | 799 | if (it->funcs != NULL) { |
807 | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; | 800 | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; |
801 | char free_content = 0; | ||
808 | 802 | ||
809 | if (pf->prim_c2i == NULL) | 803 | if (pf->prim_c2i == NULL) |
810 | return 0; | 804 | return 0; |
811 | return pf->prim_c2i(pval, cont, len, utype, free_cont, it); | 805 | return pf->prim_c2i(pval, content, len, utype, &free_content, it); |
812 | } | 806 | } |
813 | 807 | ||
814 | /* If ANY type clear type and set pointer to internal value */ | 808 | /* If ANY type clear type and set pointer to internal value */ |
@@ -828,7 +822,7 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, | |||
828 | } | 822 | } |
829 | switch (utype) { | 823 | switch (utype) { |
830 | case V_ASN1_OBJECT: | 824 | case V_ASN1_OBJECT: |
831 | if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) | 825 | if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &content, len)) |
832 | goto err; | 826 | goto err; |
833 | break; | 827 | break; |
834 | 828 | ||
@@ -847,19 +841,19 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, | |||
847 | } else { | 841 | } else { |
848 | ASN1_BOOLEAN *tbool; | 842 | ASN1_BOOLEAN *tbool; |
849 | tbool = (ASN1_BOOLEAN *)pval; | 843 | tbool = (ASN1_BOOLEAN *)pval; |
850 | *tbool = *cont; | 844 | *tbool = *content; |
851 | } | 845 | } |
852 | break; | 846 | break; |
853 | 847 | ||
854 | case V_ASN1_BIT_STRING: | 848 | case V_ASN1_BIT_STRING: |
855 | if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) | 849 | if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &content, len)) |
856 | goto err; | 850 | goto err; |
857 | break; | 851 | break; |
858 | 852 | ||
859 | case V_ASN1_INTEGER: | 853 | case V_ASN1_INTEGER: |
860 | case V_ASN1_ENUMERATED: | 854 | case V_ASN1_ENUMERATED: |
861 | tint = (ASN1_INTEGER **)pval; | 855 | tint = (ASN1_INTEGER **)pval; |
862 | if (!c2i_ASN1_INTEGER(tint, &cont, len)) | 856 | if (!c2i_ASN1_INTEGER(tint, &content, len)) |
863 | goto err; | 857 | goto err; |
864 | /* Fixup type to match the expected form */ | 858 | /* Fixup type to match the expected form */ |
865 | (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); | 859 | (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); |
@@ -891,10 +885,9 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, | |||
891 | ASN1error(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); | 885 | ASN1error(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); |
892 | goto err; | 886 | goto err; |
893 | } | 887 | } |
894 | /* All based on ASN1_STRING and handled the same */ | 888 | /* All based on ASN1_STRING and handled the same way. */ |
895 | if (!*pval) { | 889 | if (*pval == NULL) { |
896 | stmp = ASN1_STRING_type_new(utype); | 890 | if ((stmp = ASN1_STRING_type_new(utype)) == NULL) { |
897 | if (!stmp) { | ||
898 | ASN1error(ERR_R_MALLOC_FAILURE); | 891 | ASN1error(ERR_R_MALLOC_FAILURE); |
899 | goto err; | 892 | goto err; |
900 | } | 893 | } |
@@ -903,19 +896,10 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, | |||
903 | stmp = (ASN1_STRING *)*pval; | 896 | stmp = (ASN1_STRING *)*pval; |
904 | stmp->type = utype; | 897 | stmp->type = utype; |
905 | } | 898 | } |
906 | /* If we've already allocated a buffer use it */ | 899 | if (!ASN1_STRING_set(stmp, content, len)) { |
907 | if (*free_cont) { | 900 | ASN1_STRING_free(stmp); |
908 | free(stmp->data); | 901 | *pval = NULL; |
909 | stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ | 902 | goto err; |
910 | stmp->length = len; | ||
911 | *free_cont = 0; | ||
912 | } else { | ||
913 | if (!ASN1_STRING_set(stmp, cont, len)) { | ||
914 | ASN1error(ERR_R_MALLOC_FAILURE); | ||
915 | ASN1_STRING_free(stmp); | ||
916 | *pval = NULL; | ||
917 | goto err; | ||
918 | } | ||
919 | } | 903 | } |
920 | break; | 904 | break; |
921 | } | 905 | } |
@@ -934,7 +918,6 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, | |||
934 | return ret; | 918 | return ret; |
935 | } | 919 | } |
936 | 920 | ||
937 | |||
938 | /* This function finds the end of an ASN1 structure when passed its maximum | 921 | /* This function finds the end of an ASN1 structure when passed its maximum |
939 | * length, whether it is indefinite length and a pointer to the content. | 922 | * length, whether it is indefinite length and a pointer to the content. |
940 | * This is more efficient than calling asn1_collect because it does not | 923 | * This is more efficient than calling asn1_collect because it does not |