File openssl-CVE-2018-0739.patch of Package compat-openssl098.14113

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-0.9.8j/crypto/asn1/asn1.h
===================================================================
--- openssl-0.9.8j.orig/crypto/asn1/asn1.h	2018-03-28 15:13:24.531593270 +0200
+++ openssl-0.9.8j/crypto/asn1/asn1.h	2018-03-28 15:13:25.967615686 +0200
@@ -1281,6 +1281,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-0.9.8j/crypto/asn1/asn1_err.c
===================================================================
--- openssl-0.9.8j.orig/crypto/asn1/asn1_err.c	2018-03-28 15:13:24.531593270 +0200
+++ openssl-0.9.8j/crypto/asn1/asn1_err.c	2018-03-28 15:13:25.967615686 +0200
@@ -258,6 +258,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-0.9.8j/crypto/asn1/tasn_dec.c
===================================================================
--- openssl-0.9.8j.orig/crypto/asn1/tasn_dec.c	2018-03-28 15:13:24.535593332 +0200
+++ openssl-0.9.8j/crypto/asn1/tasn_dec.c	2018-03-28 15:14:55.025027989 +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,
@@ -141,7 +149,7 @@ int ASN1_template_d2i(ASN1_VALUE **pval,
 	{
 	ASN1_TLC c;
 	c.valid = 0;
-	return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
+	return asn1_template_ex_d2i(pval, in, len, tt, 0, &c, 0);
 	}
 
 
@@ -149,9 +157,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;
@@ -175,6 +183,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:
@@ -193,7 +206,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);
@@ -334,7 +347,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;
@@ -465,7 +478,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;
@@ -545,6 +558,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.
  */
@@ -552,7 +572,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;
@@ -592,7 +612,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,
@@ -625,7 +645,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;
@@ -638,7 +658,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;
@@ -722,9 +742,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);
@@ -747,8 +767,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,
@@ -761,8 +781,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,
openSUSE Build Service is sponsored by