You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
9.9 KiB
217 lines
9.9 KiB
diff -up openssl-1.0.2k/crypto/asn1/asn1_err.c.asn1-recursive openssl-1.0.2k/crypto/asn1/asn1_err.c |
|
--- openssl-1.0.2k/crypto/asn1/asn1_err.c.asn1-recursive 2017-01-26 14:22:03.000000000 +0100 |
|
+++ openssl-1.0.2k/crypto/asn1/asn1_err.c 2018-06-18 15:08:18.333412753 +0200 |
|
@@ -279,6 +279,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"}, |
|
diff -up openssl-1.0.2k/crypto/asn1/asn1.h.asn1-recursive openssl-1.0.2k/crypto/asn1/asn1.h |
|
--- openssl-1.0.2k/crypto/asn1/asn1.h.asn1-recursive 2018-06-18 13:46:23.857127431 +0200 |
|
+++ openssl-1.0.2k/crypto/asn1/asn1.h 2018-06-18 15:07:53.915826715 +0200 |
|
@@ -1365,6 +1365,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 |
|
diff -up openssl-1.0.2k/crypto/asn1/tasn_dec.c.asn1-recursive openssl-1.0.2k/crypto/asn1/tasn_dec.c |
|
--- openssl-1.0.2k/crypto/asn1/tasn_dec.c.asn1-recursive 2017-01-26 14:22:03.000000000 +0100 |
|
+++ openssl-1.0.2k/crypto/asn1/tasn_dec.c 2018-06-18 15:14:28.978308482 +0200 |
|
@@ -4,7 +4,7 @@ |
|
* 2000. |
|
*/ |
|
/* ==================================================================== |
|
- * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. |
|
+ * Copyright (c) 2000-2018 The OpenSSL Project. All rights reserved. |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
* modification, are permitted provided that the following conditions |
|
@@ -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); |
|
|
|
@@ -81,11 +89,11 @@ static int asn1_check_tlen(long *olen, i |
|
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, |
|
@@ -154,17 +162,16 @@ 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); |
|
} |
|
|
|
/* |
|
* Decode an item, taking care of IMPLICIT tagging, if any. 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; |
|
@@ -189,6 +196,11 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, |
|
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: |
|
if (it->templates) { |
|
@@ -204,7 +216,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); |
|
@@ -326,7 +338,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; |
|
@@ -444,7 +456,8 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, |
|
* attempt to read in field, allowing each to be OPTIONAL |
|
*/ |
|
|
|
- ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx); |
|
+ ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx, |
|
+ depth); |
|
if (!ret) { |
|
errtt = seqtt; |
|
goto err; |
|
@@ -514,6 +527,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. |
|
@@ -522,7 +542,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; |
|
@@ -557,7 +577,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, ERR_R_NESTED_ASN1_ERROR); |
|
return 0; |
|
@@ -581,7 +601,7 @@ static int asn1_template_ex_d2i(ASN1_VAL |
|
} |
|
} |
|
} else |
|
- return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx); |
|
+ return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth); |
|
|
|
*in = p; |
|
return 1; |
|
@@ -594,7 +614,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; |
|
@@ -665,14 +685,15 @@ static int asn1_template_noexp_d2i(ASN1_ |
|
break; |
|
} |
|
skfield = NULL; |
|
- if (!ASN1_item_ex_d2i(&skfield, &p, len, |
|
- ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) { |
|
+ if (!asn1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), |
|
+ -1, 0, 0, ctx, depth)) { |
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, |
|
ERR_R_NESTED_ASN1_ERROR); |
|
goto err; |
|
} |
|
len -= p - q; |
|
if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { |
|
+ ASN1_item_ex_free(&skfield, ASN1_ITEM_ptr(tt->item)); |
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); |
|
goto err; |
|
} |
|
@@ -683,9 +704,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, ERR_R_NESTED_ASN1_ERROR); |
|
goto err; |
|
@@ -693,8 +713,9 @@ static int asn1_template_noexp_d2i(ASN1_ |
|
return -1; |
|
} 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, ERR_R_NESTED_ASN1_ERROR); |
|
goto err;
|
|
|