Search
j0ke.net Open Build Service
>
Projects
>
home:netmax
:
monitoring
>
openssl1
> openssl-CVE-2018-0739.patch
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File openssl-CVE-2018-0739.patch of Package openssl1
commit 9310d45087ae546e27e61ddf8f6367f29848220d Author: Matt Caswell <matt@openssl.org> Date: Thu Mar 22 10:05:40 2018 +0000 Limit ASN.1 constructed types recursive definition depth Constructed types with a recursive definition (such as can be found in PKCS7) could eventually exceed the stack given malicious input with excessive recursion. Therefore we limit the stack depth. CVE-2018-0739 Credit to OSSFuzz for finding this issue. Reviewed-by: Rich Salz <rsalz@openssl.org> Index: openssl-1.0.1i/crypto/asn1/asn1.h =================================================================== --- openssl-1.0.1i.orig/crypto/asn1/asn1.h 2018-03-28 12:53:23.510899375 +0200 +++ openssl-1.0.1i/crypto/asn1/asn1.h 2018-03-28 12:53:24.822920427 +0200 @@ -1352,6 +1352,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_MSTRING_NOT_UNIVERSAL 139 #define ASN1_R_MSTRING_WRONG_TAG 140 #define ASN1_R_NESTED_ASN1_STRING 197 +#define ASN1_R_NESTED_TOO_DEEP 219 #define ASN1_R_NON_HEX_CHARACTERS 141 #define ASN1_R_NOT_ASCII_FORMAT 190 #define ASN1_R_NOT_ENOUGH_DATA 142 Index: openssl-1.0.1i/crypto/asn1/asn1_err.c =================================================================== --- openssl-1.0.1i.orig/crypto/asn1/asn1_err.c 2018-03-28 12:53:23.510899375 +0200 +++ openssl-1.0.1i/crypto/asn1/asn1_err.c 2018-03-28 12:53:24.822920427 +0200 @@ -269,6 +269,7 @@ static ERR_STRING_DATA ASN1_str_reasons[ {ERR_REASON(ASN1_R_MSTRING_NOT_UNIVERSAL),"mstring not universal"}, {ERR_REASON(ASN1_R_MSTRING_WRONG_TAG) ,"mstring wrong tag"}, {ERR_REASON(ASN1_R_NESTED_ASN1_STRING) ,"nested asn1 string"}, +{ERR_REASON(ASN1_R_NESTED_TOO_DEEP) ,"nested too deep"}, {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS) ,"non hex characters"}, {ERR_REASON(ASN1_R_NOT_ASCII_FORMAT) ,"not ascii format"}, {ERR_REASON(ASN1_R_NOT_ENOUGH_DATA) ,"not enough data"}, Index: openssl-1.0.1i/crypto/asn1/tasn_dec.c =================================================================== --- openssl-1.0.1i.orig/crypto/asn1/tasn_dec.c 2018-03-28 12:53:24.174910030 +0200 +++ openssl-1.0.1i/crypto/asn1/tasn_dec.c 2018-03-28 14:01:20.367253628 +0200 @@ -65,6 +65,14 @@ #include <openssl/buffer.h> #include <openssl/err.h> +/* + * Constructed types with a recursive definition (such as can be found in PKCS7) + * could eventually exceed the stack given malicious input with excessive + * recursion. Therefore we limit the stack depth. This is the maximum number of + * recursive invocations of asn1_item_embed_d2i(). + */ +#define ASN1_MAX_CONSTRUCTED_NEST 30 + static int asn1_check_eoc(const unsigned char **in, long len); static int asn1_find_end(const unsigned char **in, long len, char inf); @@ -77,16 +85,16 @@ static int asn1_check_tlen(long *olen, i char *inf, char *cst, const unsigned char **in, long len, int exptag, int expclass, char opt, - ASN1_TLC *ctx); + ASN1_TLC *ctx); static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx); + ASN1_TLC *ctx, int depth); static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx); + ASN1_TLC *ctx, int depth); static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, @@ -143,7 +151,7 @@ int ASN1_template_d2i(ASN1_VALUE **pval, { ASN1_TLC c; asn1_tlc_clear_nc(&c); - return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); + return asn1_template_ex_d2i(pval, in, len, tt, 0, &c, 0); } @@ -151,9 +159,9 @@ int ASN1_template_d2i(ASN1_VALUE **pval, * If 'opt' set and tag mismatch return -1 to handle OPTIONAL */ -int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, - const ASN1_ITEM *it, - int tag, int aclass, char opt, ASN1_TLC *ctx) +static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_ITEM *it, int tag, int aclass, + char opt, ASN1_TLC *ctx, int depth) { const ASN1_TEMPLATE *tt, *errtt = NULL; const ASN1_COMPAT_FUNCS *cf; @@ -177,6 +185,11 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, asn1_cb = aux->asn1_cb; else asn1_cb = 0; + if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_NESTED_TOO_DEEP); + goto err; + } + switch(it->itype) { case ASN1_ITYPE_PRIMITIVE: @@ -195,7 +208,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, goto err; } return asn1_template_ex_d2i(pval, in, len, - it->templates, opt, ctx); + it->templates, opt, ctx, depth); } return asn1_d2i_ex_primitive(pval, in, len, it, tag, aclass, opt, ctx); @@ -335,7 +348,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, /* We mark field as OPTIONAL so its absence * can be recognised. */ - ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); + ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth); /* If field not present, try the next one */ if (ret == -1) continue; @@ -466,7 +479,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, * OPTIONAL */ ret = asn1_template_ex_d2i(pseqval, &p, len, - seqtt, isopt, ctx); + seqtt, isopt, ctx, depth); if (!ret) { errtt = seqtt; @@ -546,6 +559,13 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, return 0; } +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0); +} + /* Templates are handled with two separate functions. * One handles any EXPLICIT tag and the other handles the rest. */ @@ -553,7 +573,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx) + ASN1_TLC *ctx, int depth) { int flags, aclass; int ret; @@ -593,7 +613,7 @@ static int asn1_template_ex_d2i(ASN1_VAL return 0; } /* We've found the field so it can't be OPTIONAL now */ - ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); + ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth); if (!ret) { ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, @@ -626,7 +646,7 @@ static int asn1_template_ex_d2i(ASN1_VAL } else return asn1_template_noexp_d2i(val, in, inlen, - tt, opt, ctx); + tt, opt, ctx, depth); *in = p; return 1; @@ -639,7 +659,7 @@ static int asn1_template_ex_d2i(ASN1_VAL static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx) + ASN1_TLC *ctx, int depth) { int flags, aclass; int ret; @@ -724,9 +744,9 @@ static int asn1_template_noexp_d2i(ASN1_ break; } skfield = NULL; - if (!ASN1_item_ex_d2i(&skfield, &p, len, + if (!asn1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), - -1, 0, 0, ctx)) + -1, 0, 0, ctx, depth)) { ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); @@ -750,8 +770,8 @@ static int asn1_template_noexp_d2i(ASN1_ else if (flags & ASN1_TFLG_IMPTAG) { /* IMPLICIT tagging */ - ret = ASN1_item_ex_d2i(val, &p, len, - ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx); + ret = asn1_item_ex_d2i(val, &p, len, + ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx, depth); if (!ret) { ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, @@ -764,8 +784,8 @@ static int asn1_template_noexp_d2i(ASN1_ else { /* Nothing special */ - ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), - -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx); + ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), + -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx, depth); if (!ret) { ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,