diff options
Diffstat (limited to 'crypto/asn1/tasn_dec.c')
-rw-r--r-- | crypto/asn1/tasn_dec.c | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 0ee406231e7c..48bc1c0d4d09 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -1,5 +1,5 @@ /* tasn_dec.c */ -/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ /* ==================================================================== @@ -69,7 +69,7 @@ static int asn1_check_eoc(const unsigned char **in, long len); static int asn1_find_end(const unsigned char **in, long len, char inf); static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, - char inf, int tag, int aclass); + char inf, int tag, int aclass, int depth); static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen); @@ -611,7 +611,6 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, err: ASN1_template_free(val, tt); - *val = NULL; return 0; } @@ -758,7 +757,6 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, err: ASN1_template_free(val, tt); - *val = NULL; return 0; } @@ -878,7 +876,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, * internally irrespective of the type. So instead just check * for UNIVERSAL class and ignore the tag. */ - if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL)) + if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) { free_cont = 1; goto err; @@ -1012,6 +1010,18 @@ int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, case V_ASN1_SET: case V_ASN1_SEQUENCE: default: + if (utype == V_ASN1_BMPSTRING && (len & 1)) + { + ASN1err(ASN1_F_ASN1_EX_C2I, + ASN1_R_BMPSTRING_IS_WRONG_LENGTH); + goto err; + } + if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) + { + ASN1err(ASN1_F_ASN1_EX_C2I, + ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); + goto err; + } /* All based on ASN1_STRING and handled the same */ if (!*pval) { @@ -1128,8 +1138,18 @@ static int asn1_find_end(const unsigned char **in, long len, char inf) * if it is indefinite length. */ +#ifndef ASN1_MAX_STRING_NEST +/* This determines how many levels of recursion are permitted in ASN1 + * string types. If it is not limited stack overflows can occur. If set + * to zero no recursion is allowed at all. Although zero should be adequate + * examples exist that require a value of 1. So 5 should be more than enough. + */ +#define ASN1_MAX_STRING_NEST 5 +#endif + + static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, - char inf, int tag, int aclass) + char inf, int tag, int aclass, int depth) { const unsigned char *p, *q; long plen; @@ -1171,13 +1191,15 @@ static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, /* If indefinite length constructed update max length */ if (cst) { -#ifdef OPENSSL_ALLOW_NESTED_ASN1_STRINGS - if (!asn1_collect(buf, &p, plen, ininf, tag, aclass)) + if (depth >= ASN1_MAX_STRING_NEST) + { + ASN1err(ASN1_F_ASN1_COLLECT, + ASN1_R_NESTED_ASN1_STRING); + return 0; + } + if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, + depth + 1)) return 0; -#else - ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING); - return 0; -#endif } else if (plen && !collect_data(buf, &p, plen)) return 0; |