diff options
author | jsing <> | 2022-05-07 10:03:49 +0000 |
---|---|---|
committer | jsing <> | 2022-05-07 10:03:49 +0000 |
commit | ca42b63078f68d76fac152f5bd2146e6b6d1eb17 (patch) | |
tree | 5a3cc6a41afff35410e053b557ab38020bc57d33 /src/lib | |
parent | 06373cf29b7f2f1c4fdd09ce26d5671ac29e3675 (diff) | |
download | openbsd-ca42b63078f68d76fac152f5bd2146e6b6d1eb17.tar.gz openbsd-ca42b63078f68d76fac152f5bd2146e6b6d1eb17.tar.bz2 openbsd-ca42b63078f68d76fac152f5bd2146e6b6d1eb17.zip |
Refactor asn1_ex_c2i()
The asn1_ex_c2i() function currently handles the V_ASN1_ANY case inline,
which means there multiple special cases, with pointer fudging and
restoring. Instead, split asn1_ex_c2i() into three functions - one that
only handles storage into a primitive type (asn1_ex_c2i_primitive()), one
that handles the V_ASN1_ANY case (asn1_ex_c2i_any()) and calls
asn1_ex_c2i_primitive() with the correct pointer and an asn1_ex_c2i()
that handles the custom functions case, before dispatching to
asn1_ex_c2i_any() or asn1_ex_c2i_primitive(), as appropriate.
This results in cleaner and simpler code.
With input from and ok tb@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 98 |
1 files changed, 59 insertions, 39 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 103774fc19..f04ec66bc7 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.58 2022/05/05 19:18:56 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.59 2022/05/07 10:03:49 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 | */ |
@@ -771,47 +771,21 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
771 | return ret; | 771 | return ret; |
772 | } | 772 | } |
773 | 773 | ||
774 | /* Translate ASN.1 content octets into a structure. */ | ||
775 | static int | 774 | static int |
776 | asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | 775 | asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) |
777 | { | 776 | { |
778 | ASN1_VALUE **opval = NULL; | ||
779 | ASN1_STRING *stmp; | 777 | ASN1_STRING *stmp; |
780 | ASN1_TYPE *typ = NULL; | ||
781 | ASN1_INTEGER **tint; | 778 | ASN1_INTEGER **tint; |
782 | ASN1_BOOLEAN *tbool; | 779 | ASN1_BOOLEAN *tbool; |
783 | uint8_t u8val; | 780 | uint8_t u8val; |
784 | int ret = 0; | 781 | int ret = 0; |
785 | 782 | ||
786 | if (CBS_len(content) > INT_MAX) | 783 | if (it->funcs != NULL) |
787 | return 0; | 784 | return 0; |
788 | 785 | ||
789 | if (it->funcs != NULL) { | 786 | if (CBS_len(content) > INT_MAX) |
790 | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; | 787 | return 0; |
791 | char free_content = 0; | ||
792 | |||
793 | if (pf->prim_c2i == NULL) | ||
794 | return 0; | ||
795 | |||
796 | return pf->prim_c2i(pval, CBS_data(content), CBS_len(content), | ||
797 | utype, &free_content, it); | ||
798 | } | ||
799 | 788 | ||
800 | /* If ANY type clear type and set pointer to internal value */ | ||
801 | if (it->utype == V_ASN1_ANY) { | ||
802 | if (!*pval) { | ||
803 | typ = ASN1_TYPE_new(); | ||
804 | if (typ == NULL) | ||
805 | goto err; | ||
806 | *pval = (ASN1_VALUE *)typ; | ||
807 | } else | ||
808 | typ = (ASN1_TYPE *)*pval; | ||
809 | |||
810 | if (utype != typ->type) | ||
811 | ASN1_TYPE_set(typ, utype, NULL); | ||
812 | opval = pval; | ||
813 | pval = &typ->value.asn1_value; | ||
814 | } | ||
815 | switch (utype) { | 789 | switch (utype) { |
816 | case V_ASN1_OBJECT: | 790 | case V_ASN1_OBJECT: |
817 | if (!c2i_ASN1_OBJECT_cbs((ASN1_OBJECT **)pval, content)) | 791 | if (!c2i_ASN1_OBJECT_cbs((ASN1_OBJECT **)pval, content)) |
@@ -895,21 +869,67 @@ asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | |||
895 | } | 869 | } |
896 | break; | 870 | break; |
897 | } | 871 | } |
898 | /* If ASN1_ANY and NULL type fix up value */ | ||
899 | if (typ && (utype == V_ASN1_NULL)) | ||
900 | typ->value.ptr = NULL; | ||
901 | 872 | ||
902 | ret = 1; | 873 | ret = 1; |
903 | 874 | ||
904 | err: | 875 | err: |
905 | if (!ret) { | ||
906 | ASN1_TYPE_free(typ); | ||
907 | if (opval) | ||
908 | *opval = NULL; | ||
909 | } | ||
910 | return ret; | 876 | return ret; |
911 | } | 877 | } |
912 | 878 | ||
879 | static int | ||
880 | asn1_ex_c2i_any(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | ||
881 | { | ||
882 | ASN1_TYPE *atype; | ||
883 | |||
884 | if (it->utype != V_ASN1_ANY || it->funcs != NULL) | ||
885 | return 0; | ||
886 | |||
887 | if (*pval != NULL) { | ||
888 | ASN1_TYPE_free((ASN1_TYPE *)*pval); | ||
889 | *pval = NULL; | ||
890 | } | ||
891 | |||
892 | if ((atype = ASN1_TYPE_new()) == NULL) | ||
893 | return 0; | ||
894 | |||
895 | if (!asn1_ex_c2i_primitive(&atype->value.asn1_value, content, utype, it)) { | ||
896 | ASN1_TYPE_free(atype); | ||
897 | return 0; | ||
898 | } | ||
899 | atype->type = utype; | ||
900 | |||
901 | /* Fix up value for ASN.1 NULL. */ | ||
902 | if (atype->type == V_ASN1_NULL) | ||
903 | atype->value.ptr = NULL; | ||
904 | |||
905 | *pval = (ASN1_VALUE *)atype; | ||
906 | |||
907 | return 1; | ||
908 | } | ||
909 | |||
910 | static int | ||
911 | asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | ||
912 | { | ||
913 | if (CBS_len(content) > INT_MAX) | ||
914 | return 0; | ||
915 | |||
916 | if (it->funcs != NULL) { | ||
917 | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; | ||
918 | char free_content = 0; | ||
919 | |||
920 | if (pf->prim_c2i == NULL) | ||
921 | return 0; | ||
922 | |||
923 | return pf->prim_c2i(pval, CBS_data(content), CBS_len(content), | ||
924 | utype, &free_content, it); | ||
925 | } | ||
926 | |||
927 | if (it->utype == V_ASN1_ANY) | ||
928 | return asn1_ex_c2i_any(pval, content, utype, it); | ||
929 | |||
930 | return asn1_ex_c2i_primitive(pval, content, utype, it); | ||
931 | } | ||
932 | |||
913 | /* Find the end of an ASN.1 object. */ | 933 | /* Find the end of an ASN.1 object. */ |
914 | static int | 934 | static int |
915 | asn1_find_end(CBS *cbs, size_t length, char indefinite) | 935 | asn1_find_end(CBS *cbs, size_t length, char indefinite) |