diff options
author | jsing <> | 2021-12-13 17:50:24 +0000 |
---|---|---|
committer | jsing <> | 2021-12-13 17:50:24 +0000 |
commit | 82dc0f2cd4b771d4c9919257ba0bbf552353ba8c (patch) | |
tree | e252c1cc65d0d8d05a5d8c1375cfde2a278f11ea /src | |
parent | a8de9c3426a243a7fe6c43129d0580880e306298 (diff) | |
download | openbsd-82dc0f2cd4b771d4c9919257ba0bbf552353ba8c.tar.gz openbsd-82dc0f2cd4b771d4c9919257ba0bbf552353ba8c.tar.bz2 openbsd-82dc0f2cd4b771d4c9919257ba0bbf552353ba8c.zip |
Convert asn1_d2i_ex_primitive()/asn1_collect() from BUF_MEM to CBB.
With this we get simpler code, overflow checking and more sensible
memory ownership. Also switch the free_cont case to freezero() since this
could contain secrets.
ok inoguchi@ tb@
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 68 |
1 files changed, 37 insertions, 31 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 7338f6800a..a04a84cce8 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.44 2021/12/09 17:01:41 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.45 2021/12/13 17:50:24 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 | */ |
@@ -56,6 +56,7 @@ | |||
56 | * | 56 | * |
57 | */ | 57 | */ |
58 | 58 | ||
59 | #include <limits.h> | ||
59 | #include <stddef.h> | 60 | #include <stddef.h> |
60 | #include <string.h> | 61 | #include <string.h> |
61 | 62 | ||
@@ -65,6 +66,8 @@ | |||
65 | #include <openssl/err.h> | 66 | #include <openssl/err.h> |
66 | #include <openssl/objects.h> | 67 | #include <openssl/objects.h> |
67 | 68 | ||
69 | #include "bytestring.h" | ||
70 | |||
68 | /* Constructed types with a recursive definition (such as can be found in PKCS7) | 71 | /* Constructed types with a recursive definition (such as can be found in PKCS7) |
69 | * could eventually exceed the stack given malicious input with excessive | 72 | * could eventually exceed the stack given malicious input with excessive |
70 | * recursion. Therefore we limit the stack depth. | 73 | * recursion. Therefore we limit the stack depth. |
@@ -74,7 +77,7 @@ | |||
74 | static int asn1_check_eoc(const unsigned char **in, long len); | 77 | static int asn1_check_eoc(const unsigned char **in, long len); |
75 | static int asn1_find_end(const unsigned char **in, long len, char inf); | 78 | static int asn1_find_end(const unsigned char **in, long len, char inf); |
76 | 79 | ||
77 | static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, | 80 | static int asn1_collect(CBB *cbb, const unsigned char **in, long len, |
78 | char inf, int tag, int aclass, int depth); | 81 | char inf, int tag, int aclass, int depth); |
79 | 82 | ||
80 | static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, | 83 | static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, |
@@ -681,13 +684,13 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
681 | long plen; | 684 | long plen; |
682 | char cst, inf, free_cont = 0; | 685 | char cst, inf, free_cont = 0; |
683 | const unsigned char *p; | 686 | const unsigned char *p; |
684 | BUF_MEM buf; | ||
685 | const unsigned char *cont = NULL; | 687 | const unsigned char *cont = NULL; |
688 | uint8_t *data = NULL; | ||
689 | size_t data_len = 0; | ||
690 | CBB cbb; | ||
686 | long len; | 691 | long len; |
687 | 692 | ||
688 | buf.length = 0; | 693 | memset(&cbb, 0, sizeof(cbb)); |
689 | buf.max = 0; | ||
690 | buf.data = NULL; | ||
691 | 694 | ||
692 | if (!pval) { | 695 | if (!pval) { |
693 | ASN1error(ASN1_R_ILLEGAL_NULL); | 696 | ASN1error(ASN1_R_ILLEGAL_NULL); |
@@ -758,28 +761,34 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
758 | } else { | 761 | } else { |
759 | len = p - cont + plen; | 762 | len = p - cont + plen; |
760 | p += plen; | 763 | p += plen; |
761 | buf.data = NULL; | ||
762 | } | 764 | } |
763 | } else if (cst) { | 765 | } else if (cst) { |
764 | /* Should really check the internal tags are correct but | 766 | /* |
767 | * Should really check the internal tags are correct but | ||
765 | * some things may get this wrong. The relevant specs | 768 | * some things may get this wrong. The relevant specs |
766 | * say that constructed string types should be OCTET STRINGs | 769 | * say that constructed string types should be OCTET STRINGs |
767 | * internally irrespective of the type. So instead just check | 770 | * internally irrespective of the type. So instead just check |
768 | * for UNIVERSAL class and ignore the tag. | 771 | * for UNIVERSAL class and ignore the tag. |
769 | */ | 772 | */ |
770 | if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) { | 773 | if (!CBB_init(&cbb, 0)) |
771 | free_cont = 1; | ||
772 | goto err; | 774 | goto err; |
773 | } | 775 | if (!asn1_collect(&cbb, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) |
774 | len = buf.length; | 776 | goto err; |
775 | /* Append a final null to string */ | 777 | |
776 | if (!BUF_MEM_grow_clean(&buf, len + 1)) { | 778 | /* Append a final NUL to string. */ |
777 | ASN1error(ERR_R_MALLOC_FAILURE); | 779 | if (!CBB_add_u8(&cbb, 0)) |
778 | return 0; | 780 | goto err; |
779 | } | 781 | |
780 | buf.data[len] = 0; | 782 | if (!CBB_finish(&cbb, &data, &data_len)) |
781 | cont = (const unsigned char *)buf.data; | 783 | goto err; |
784 | |||
782 | free_cont = 1; | 785 | free_cont = 1; |
786 | |||
787 | if (data_len < 1 || data_len > LONG_MAX) | ||
788 | goto err; | ||
789 | |||
790 | cont = data; | ||
791 | len = data_len - 1; | ||
783 | } else { | 792 | } else { |
784 | cont = p; | 793 | cont = p; |
785 | len = plen; | 794 | len = plen; |
@@ -793,9 +802,12 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
793 | *in = p; | 802 | *in = p; |
794 | ret = 1; | 803 | ret = 1; |
795 | 804 | ||
796 | err: | 805 | err: |
797 | if (free_cont && buf.data) | 806 | CBB_cleanup(&cbb); |
798 | free(buf.data); | 807 | |
808 | if (free_cont) | ||
809 | freezero(data, data_len); | ||
810 | |||
799 | return ret; | 811 | return ret; |
800 | } | 812 | } |
801 | 813 | ||
@@ -1011,7 +1023,7 @@ asn1_find_end(const unsigned char **in, long len, char inf) | |||
1011 | #endif | 1023 | #endif |
1012 | 1024 | ||
1013 | static int | 1025 | static int |
1014 | asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, char inf, | 1026 | asn1_collect(CBB *cbb, const unsigned char **in, long len, char inf, |
1015 | int tag, int aclass, int depth) | 1027 | int tag, int aclass, int depth) |
1016 | { | 1028 | { |
1017 | const unsigned char *p, *q; | 1029 | const unsigned char *p, *q; |
@@ -1048,18 +1060,12 @@ asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, char inf, | |||
1048 | 1060 | ||
1049 | /* If indefinite length constructed update max length */ | 1061 | /* If indefinite length constructed update max length */ |
1050 | if (cst) { | 1062 | if (cst) { |
1051 | if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, | 1063 | if (!asn1_collect(cbb, &p, plen, ininf, tag, aclass, |
1052 | depth + 1)) | 1064 | depth + 1)) |
1053 | return 0; | 1065 | return 0; |
1054 | } else if (plen > 0) { | 1066 | } else if (plen > 0) { |
1055 | size_t len = buf->length; | 1067 | if (!CBB_add_bytes(cbb, p, plen)) |
1056 | |||
1057 | if (!BUF_MEM_grow_clean(buf, len + plen)) { | ||
1058 | ASN1error(ERR_R_MALLOC_FAILURE); | ||
1059 | return 0; | 1068 | return 0; |
1060 | } | ||
1061 | memcpy(buf->data + len, p, plen); | ||
1062 | |||
1063 | p += plen; | 1069 | p += plen; |
1064 | } | 1070 | } |
1065 | len -= p - q; | 1071 | len -= p - q; |