6565#include <openssl/buffer.h>
6666#include <openssl/err.h>
6767
68+ /*
69+ * Constructed types with a recursive definition (such as can be found in PKCS7)
70+ * could eventually exceed the stack given malicious input with excessive
71+ * recursion. Therefore we limit the stack depth. This is the maximum number of
72+ * recursive invocations of asn1_item_embed_d2i().
73+ */
74+ #define ASN1_MAX_CONSTRUCTED_NEST 30
75+
6876static int asn1_check_eoc (const unsigned char * * in , long len );
6977static int asn1_find_end (const unsigned char * * in , long len , char inf );
7078
@@ -81,11 +89,11 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
8189static int asn1_template_ex_d2i (ASN1_VALUE * * pval ,
8290 const unsigned char * * in , long len ,
8391 const ASN1_TEMPLATE * tt , char opt ,
84- ASN1_TLC * ctx );
92+ ASN1_TLC * ctx , int depth );
8593static int asn1_template_noexp_d2i (ASN1_VALUE * * val ,
8694 const unsigned char * * in , long len ,
8795 const ASN1_TEMPLATE * tt , char opt ,
88- ASN1_TLC * ctx );
96+ ASN1_TLC * ctx , int depth );
8997static int asn1_d2i_ex_primitive (ASN1_VALUE * * pval ,
9098 const unsigned char * * in , long len ,
9199 const ASN1_ITEM * it ,
@@ -154,17 +162,16 @@ int ASN1_template_d2i(ASN1_VALUE **pval,
154162{
155163 ASN1_TLC c ;
156164 asn1_tlc_clear_nc (& c );
157- return asn1_template_ex_d2i (pval , in , len , tt , 0 , & c );
165+ return asn1_template_ex_d2i (pval , in , len , tt , 0 , & c , 0 );
158166}
159167
160168/*
161169 * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and
162170 * tag mismatch return -1 to handle OPTIONAL
163171 */
164-
165- int ASN1_item_ex_d2i (ASN1_VALUE * * pval , const unsigned char * * in , long len ,
166- const ASN1_ITEM * it ,
167- int tag , int aclass , char opt , ASN1_TLC * ctx )
172+ static int asn1_item_ex_d2i (ASN1_VALUE * * pval , const unsigned char * * in ,
173+ long len , const ASN1_ITEM * it , int tag , int aclass ,
174+ char opt , ASN1_TLC * ctx , int depth )
168175{
169176 const ASN1_TEMPLATE * tt , * errtt = NULL ;
170177 const ASN1_COMPAT_FUNCS * cf ;
@@ -189,6 +196,11 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
189196 else
190197 asn1_cb = 0 ;
191198
199+ if (++ depth > ASN1_MAX_CONSTRUCTED_NEST ) {
200+ ASN1err (ASN1_F_ASN1_ITEM_EX_D2I , ASN1_R_NESTED_TOO_DEEP );
201+ goto err ;
202+ }
203+
192204 switch (it -> itype ) {
193205 case ASN1_ITYPE_PRIMITIVE :
194206 if (it -> templates ) {
@@ -204,7 +216,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
204216 goto err ;
205217 }
206218 return asn1_template_ex_d2i (pval , in , len ,
207- it -> templates , opt , ctx );
219+ it -> templates , opt , ctx , depth );
208220 }
209221 return asn1_d2i_ex_primitive (pval , in , len , it ,
210222 tag , aclass , opt , ctx );
@@ -326,7 +338,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
326338 /*
327339 * We mark field as OPTIONAL so its absence can be recognised.
328340 */
329- ret = asn1_template_ex_d2i (pchptr , & p , len , tt , 1 , ctx );
341+ ret = asn1_template_ex_d2i (pchptr , & p , len , tt , 1 , ctx , depth );
330342 /* If field not present, try the next one */
331343 if (ret == -1 )
332344 continue ;
@@ -444,7 +456,8 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
444456 * attempt to read in field, allowing each to be OPTIONAL
445457 */
446458
447- ret = asn1_template_ex_d2i (pseqval , & p , len , seqtt , isopt , ctx );
459+ ret = asn1_template_ex_d2i (pseqval , & p , len , seqtt , isopt , ctx ,
460+ depth );
448461 if (!ret ) {
449462 errtt = seqtt ;
450463 goto err ;
@@ -514,6 +527,13 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
514527 return 0 ;
515528}
516529
530+ int ASN1_item_ex_d2i (ASN1_VALUE * * pval , const unsigned char * * in , long len ,
531+ const ASN1_ITEM * it ,
532+ int tag , int aclass , char opt , ASN1_TLC * ctx )
533+ {
534+ return asn1_item_ex_d2i (pval , in , len , it , tag , aclass , opt , ctx , 0 );
535+ }
536+
517537/*
518538 * Templates are handled with two separate functions. One handles any
519539 * EXPLICIT tag and the other handles the rest.
@@ -522,7 +542,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
522542static int asn1_template_ex_d2i (ASN1_VALUE * * val ,
523543 const unsigned char * * in , long inlen ,
524544 const ASN1_TEMPLATE * tt , char opt ,
525- ASN1_TLC * ctx )
545+ ASN1_TLC * ctx , int depth )
526546{
527547 int flags , aclass ;
528548 int ret ;
@@ -557,7 +577,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
557577 return 0 ;
558578 }
559579 /* We've found the field so it can't be OPTIONAL now */
560- ret = asn1_template_noexp_d2i (val , & p , len , tt , 0 , ctx );
580+ ret = asn1_template_noexp_d2i (val , & p , len , tt , 0 , ctx , depth );
561581 if (!ret ) {
562582 ASN1err (ASN1_F_ASN1_TEMPLATE_EX_D2I , ERR_R_NESTED_ASN1_ERROR );
563583 return 0 ;
@@ -581,7 +601,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
581601 }
582602 }
583603 } else
584- return asn1_template_noexp_d2i (val , in , inlen , tt , opt , ctx );
604+ return asn1_template_noexp_d2i (val , in , inlen , tt , opt , ctx , depth );
585605
586606 * in = p ;
587607 return 1 ;
@@ -594,7 +614,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
594614static int asn1_template_noexp_d2i (ASN1_VALUE * * val ,
595615 const unsigned char * * in , long len ,
596616 const ASN1_TEMPLATE * tt , char opt ,
597- ASN1_TLC * ctx )
617+ ASN1_TLC * ctx , int depth )
598618{
599619 int flags , aclass ;
600620 int ret ;
@@ -665,8 +685,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
665685 break ;
666686 }
667687 skfield = NULL ;
668- if (!ASN1_item_ex_d2i (& skfield , & p , len ,
669- ASN1_ITEM_ptr ( tt -> item ), - 1 , 0 , 0 , ctx )) {
688+ if (!asn1_item_ex_d2i (& skfield , & p , len , ASN1_ITEM_ptr ( tt -> item ) ,
689+ - 1 , 0 , 0 , ctx , depth )) {
670690 ASN1err (ASN1_F_ASN1_TEMPLATE_NOEXP_D2I ,
671691 ERR_R_NESTED_ASN1_ERROR );
672692 goto err ;
@@ -684,18 +704,18 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
684704 }
685705 } else if (flags & ASN1_TFLG_IMPTAG ) {
686706 /* IMPLICIT tagging */
687- ret = ASN1_item_ex_d2i (val , & p , len ,
688- ASN1_ITEM_ptr (tt -> item ), tt -> tag , aclass , opt ,
689- ctx );
707+ ret = asn1_item_ex_d2i (val , & p , len , ASN1_ITEM_ptr (tt -> item ), tt -> tag ,
708+ aclass , opt , ctx , depth );
690709 if (!ret ) {
691710 ASN1err (ASN1_F_ASN1_TEMPLATE_NOEXP_D2I , ERR_R_NESTED_ASN1_ERROR );
692711 goto err ;
693712 } else if (ret == -1 )
694713 return -1 ;
695714 } else {
696715 /* Nothing special */
697- ret = ASN1_item_ex_d2i (val , & p , len , ASN1_ITEM_ptr (tt -> item ),
698- -1 , tt -> flags & ASN1_TFLG_COMBINE , opt , ctx );
716+ ret = asn1_item_ex_d2i (val , & p , len , ASN1_ITEM_ptr (tt -> item ),
717+ -1 , tt -> flags & ASN1_TFLG_COMBINE , opt , ctx ,
718+ depth );
699719 if (!ret ) {
700720 ASN1err (ASN1_F_ASN1_TEMPLATE_NOEXP_D2I , ERR_R_NESTED_ASN1_ERROR );
701721 goto err ;
0 commit comments