X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fasn1%2Ftasn_dec.c;h=359e9c304bfd311166104c49942466212ac612f0;hp=302004bcab79ef09523b107e1db7e0f5baee5ae6;hb=80b2ff978d4f309cea71754ae6bcc01d6b36ea20;hpb=2e5975285e2b65261ce780fa3f5744277b66db34 diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 302004bcab..359e9c304b 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -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); @@ -126,8 +126,7 @@ unsigned long ASN1_tag2bit(int tag) */ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, - const unsigned char **in, size_t len, - const ASN1_ITEM *it) + const unsigned char **in, long len, const ASN1_ITEM *it) { ASN1_TLC c; ASN1_VALUE *ptmpval = NULL; @@ -883,7 +882,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; @@ -1017,6 +1016,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) { @@ -1133,8 +1144,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; @@ -1176,13 +1197,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; @@ -1244,7 +1267,7 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, { int i; int ptag, pclass; - size_t plen; + long plen; const unsigned char *p, *q; p = *in; q = p;