1717#include "internal/numbers.h"
1818#include "asn1_locl.h"
1919
20+ /*
21+ * Constructed types with a recursive definition (such as can be found in PKCS7)
22+ * could eventually exceed the stack given malicious input with excessive
23+ * recursion. Therefore we limit the stack depth. This is the maximum number of
24+ * recursive invocations of asn1_item_embed_d2i().
25+ */
26+ #define ASN1_MAX_CONSTRUCTED_NEST 30
27+
2028static int asn1_item_embed_d2i (ASN1_VALUE * * pval , const unsigned char * * in ,
2129 long len , const ASN1_ITEM * it ,
22- int tag , int aclass , char opt , ASN1_TLC * ctx );
30+ int tag , int aclass , char opt , ASN1_TLC * ctx ,
31+ int depth );
2332
2433static int asn1_check_eoc (const unsigned char * * in , long len );
2534static int asn1_find_end (const unsigned char * * in , long len , char inf );
@@ -37,11 +46,11 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
3746static int asn1_template_ex_d2i (ASN1_VALUE * * pval ,
3847 const unsigned char * * in , long len ,
3948 const ASN1_TEMPLATE * tt , char opt ,
40- ASN1_TLC * ctx );
49+ ASN1_TLC * ctx , int depth );
4150static int asn1_template_noexp_d2i (ASN1_VALUE * * val ,
4251 const unsigned char * * in , long len ,
4352 const ASN1_TEMPLATE * tt , char opt ,
44- ASN1_TLC * ctx );
53+ ASN1_TLC * ctx , int depth );
4554static int asn1_d2i_ex_primitive (ASN1_VALUE * * pval ,
4655 const unsigned char * * in , long len ,
4756 const ASN1_ITEM * it ,
@@ -111,7 +120,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
111120 int tag , int aclass , char opt , ASN1_TLC * ctx )
112121{
113122 int rv ;
114- rv = asn1_item_embed_d2i (pval , in , len , it , tag , aclass , opt , ctx );
123+ rv = asn1_item_embed_d2i (pval , in , len , it , tag , aclass , opt , ctx , 0 );
115124 if (rv <= 0 )
116125 ASN1_item_ex_free (pval , it );
117126 return rv ;
@@ -124,7 +133,8 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
124133
125134static int asn1_item_embed_d2i (ASN1_VALUE * * pval , const unsigned char * * in ,
126135 long len , const ASN1_ITEM * it ,
127- int tag , int aclass , char opt , ASN1_TLC * ctx )
136+ int tag , int aclass , char opt , ASN1_TLC * ctx ,
137+ int depth )
128138{
129139 const ASN1_TEMPLATE * tt , * errtt = NULL ;
130140 const ASN1_EXTERN_FUNCS * ef ;
@@ -145,6 +155,11 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
145155 else
146156 asn1_cb = 0 ;
147157
158+ if (++ depth > ASN1_MAX_CONSTRUCTED_NEST ) {
159+ ASN1err (ASN1_F_ASN1_ITEM_EMBED_D2I , ASN1_R_NESTED_TOO_DEEP );
160+ goto err ;
161+ }
162+
148163 switch (it -> itype ) {
149164 case ASN1_ITYPE_PRIMITIVE :
150165 if (it -> templates ) {
@@ -160,7 +175,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
160175 goto err ;
161176 }
162177 return asn1_template_ex_d2i (pval , in , len ,
163- it -> templates , opt , ctx );
178+ it -> templates , opt , ctx , depth );
164179 }
165180 return asn1_d2i_ex_primitive (pval , in , len , it ,
166181 tag , aclass , opt , ctx );
@@ -221,7 +236,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
221236 /*
222237 * We mark field as OPTIONAL so its absence can be recognised.
223238 */
224- ret = asn1_template_ex_d2i (pchptr , & p , len , tt , 1 , ctx );
239+ ret = asn1_template_ex_d2i (pchptr , & p , len , tt , 1 , ctx , depth );
225240 /* If field not present, try the next one */
226241 if (ret == -1 )
227242 continue ;
@@ -344,7 +359,8 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
344359 * attempt to read in field, allowing each to be OPTIONAL
345360 */
346361
347- ret = asn1_template_ex_d2i (pseqval , & p , len , seqtt , isopt , ctx );
362+ ret = asn1_template_ex_d2i (pseqval , & p , len , seqtt , isopt , ctx ,
363+ depth );
348364 if (!ret ) {
349365 errtt = seqtt ;
350366 goto err ;
@@ -420,7 +436,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
420436static int asn1_template_ex_d2i (ASN1_VALUE * * val ,
421437 const unsigned char * * in , long inlen ,
422438 const ASN1_TEMPLATE * tt , char opt ,
423- ASN1_TLC * ctx )
439+ ASN1_TLC * ctx , int depth )
424440{
425441 int flags , aclass ;
426442 int ret ;
@@ -455,7 +471,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
455471 return 0 ;
456472 }
457473 /* We've found the field so it can't be OPTIONAL now */
458- ret = asn1_template_noexp_d2i (val , & p , len , tt , 0 , ctx );
474+ ret = asn1_template_noexp_d2i (val , & p , len , tt , 0 , ctx , depth );
459475 if (!ret ) {
460476 ASN1err (ASN1_F_ASN1_TEMPLATE_EX_D2I , ERR_R_NESTED_ASN1_ERROR );
461477 return 0 ;
@@ -479,7 +495,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
479495 }
480496 }
481497 } else
482- return asn1_template_noexp_d2i (val , in , inlen , tt , opt , ctx );
498+ return asn1_template_noexp_d2i (val , in , inlen , tt , opt , ctx , depth );
483499
484500 * in = p ;
485501 return 1 ;
@@ -491,7 +507,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
491507static int asn1_template_noexp_d2i (ASN1_VALUE * * val ,
492508 const unsigned char * * in , long len ,
493509 const ASN1_TEMPLATE * tt , char opt ,
494- ASN1_TLC * ctx )
510+ ASN1_TLC * ctx , int depth )
495511{
496512 int flags , aclass ;
497513 int ret ;
@@ -573,7 +589,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
573589 }
574590 skfield = NULL ;
575591 if (!asn1_item_embed_d2i (& skfield , & p , len ,
576- ASN1_ITEM_ptr (tt -> item ), -1 , 0 , 0 , ctx )) {
592+ ASN1_ITEM_ptr (tt -> item ), -1 , 0 , 0 , ctx ,
593+ depth )) {
577594 ASN1err (ASN1_F_ASN1_TEMPLATE_NOEXP_D2I ,
578595 ERR_R_NESTED_ASN1_ERROR );
579596 /* |skfield| may be partially allocated despite failure. */
@@ -595,7 +612,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
595612 /* IMPLICIT tagging */
596613 ret = asn1_item_embed_d2i (val , & p , len ,
597614 ASN1_ITEM_ptr (tt -> item ), tt -> tag , aclass , opt ,
598- ctx );
615+ ctx , depth );
599616 if (!ret ) {
600617 ASN1err (ASN1_F_ASN1_TEMPLATE_NOEXP_D2I , ERR_R_NESTED_ASN1_ERROR );
601618 goto err ;
@@ -604,7 +621,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
604621 } else {
605622 /* Nothing special */
606623 ret = asn1_item_embed_d2i (val , & p , len , ASN1_ITEM_ptr (tt -> item ),
607- -1 , 0 , opt , ctx );
624+ -1 , 0 , opt , ctx , depth );
608625 if (!ret ) {
609626 ASN1err (ASN1_F_ASN1_TEMPLATE_NOEXP_D2I , ERR_R_NESTED_ASN1_ERROR );
610627 goto err ;
0 commit comments