65
65
#include <openssl/buffer.h>
66
66
#include <openssl/err.h>
67
67
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
+
68
76
static int asn1_check_eoc (const unsigned char * * in , long len );
69
77
static int asn1_find_end (const unsigned char * * in , long len , char inf );
70
78
@@ -81,11 +89,11 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
81
89
static int asn1_template_ex_d2i (ASN1_VALUE * * pval ,
82
90
const unsigned char * * in , long len ,
83
91
const ASN1_TEMPLATE * tt , char opt ,
84
- ASN1_TLC * ctx );
92
+ ASN1_TLC * ctx , int depth );
85
93
static int asn1_template_noexp_d2i (ASN1_VALUE * * val ,
86
94
const unsigned char * * in , long len ,
87
95
const ASN1_TEMPLATE * tt , char opt ,
88
- ASN1_TLC * ctx );
96
+ ASN1_TLC * ctx , int depth );
89
97
static int asn1_d2i_ex_primitive (ASN1_VALUE * * pval ,
90
98
const unsigned char * * in , long len ,
91
99
const ASN1_ITEM * it ,
@@ -154,17 +162,16 @@ int ASN1_template_d2i(ASN1_VALUE **pval,
154
162
{
155
163
ASN1_TLC c ;
156
164
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 );
158
166
}
159
167
160
168
/*
161
169
* Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and
162
170
* tag mismatch return -1 to handle OPTIONAL
163
171
*/
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 )
168
175
{
169
176
const ASN1_TEMPLATE * tt , * errtt = NULL ;
170
177
const ASN1_COMPAT_FUNCS * cf ;
@@ -189,6 +196,11 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
189
196
else
190
197
asn1_cb = 0 ;
191
198
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
+
192
204
switch (it -> itype ) {
193
205
case ASN1_ITYPE_PRIMITIVE :
194
206
if (it -> templates ) {
@@ -204,7 +216,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
204
216
goto err ;
205
217
}
206
218
return asn1_template_ex_d2i (pval , in , len ,
207
- it -> templates , opt , ctx );
219
+ it -> templates , opt , ctx , depth );
208
220
}
209
221
return asn1_d2i_ex_primitive (pval , in , len , it ,
210
222
tag , aclass , opt , ctx );
@@ -326,7 +338,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
326
338
/*
327
339
* We mark field as OPTIONAL so its absence can be recognised.
328
340
*/
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 );
330
342
/* If field not present, try the next one */
331
343
if (ret == -1 )
332
344
continue ;
@@ -444,7 +456,8 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
444
456
* attempt to read in field, allowing each to be OPTIONAL
445
457
*/
446
458
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 );
448
461
if (!ret ) {
449
462
errtt = seqtt ;
450
463
goto err ;
@@ -514,6 +527,13 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
514
527
return 0 ;
515
528
}
516
529
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
+
517
537
/*
518
538
* Templates are handled with two separate functions. One handles any
519
539
* 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,
522
542
static int asn1_template_ex_d2i (ASN1_VALUE * * val ,
523
543
const unsigned char * * in , long inlen ,
524
544
const ASN1_TEMPLATE * tt , char opt ,
525
- ASN1_TLC * ctx )
545
+ ASN1_TLC * ctx , int depth )
526
546
{
527
547
int flags , aclass ;
528
548
int ret ;
@@ -557,7 +577,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
557
577
return 0 ;
558
578
}
559
579
/* 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 );
561
581
if (!ret ) {
562
582
ASN1err (ASN1_F_ASN1_TEMPLATE_EX_D2I , ERR_R_NESTED_ASN1_ERROR );
563
583
return 0 ;
@@ -581,7 +601,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
581
601
}
582
602
}
583
603
} 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 );
585
605
586
606
* in = p ;
587
607
return 1 ;
@@ -594,7 +614,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
594
614
static int asn1_template_noexp_d2i (ASN1_VALUE * * val ,
595
615
const unsigned char * * in , long len ,
596
616
const ASN1_TEMPLATE * tt , char opt ,
597
- ASN1_TLC * ctx )
617
+ ASN1_TLC * ctx , int depth )
598
618
{
599
619
int flags , aclass ;
600
620
int ret ;
@@ -665,8 +685,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
665
685
break ;
666
686
}
667
687
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 )) {
670
690
ASN1err (ASN1_F_ASN1_TEMPLATE_NOEXP_D2I ,
671
691
ERR_R_NESTED_ASN1_ERROR );
672
692
goto err ;
@@ -684,18 +704,18 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
684
704
}
685
705
} else if (flags & ASN1_TFLG_IMPTAG ) {
686
706
/* 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 );
690
709
if (!ret ) {
691
710
ASN1err (ASN1_F_ASN1_TEMPLATE_NOEXP_D2I , ERR_R_NESTED_ASN1_ERROR );
692
711
goto err ;
693
712
} else if (ret == -1 )
694
713
return -1 ;
695
714
} else {
696
715
/* 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 );
699
719
if (!ret ) {
700
720
ASN1err (ASN1_F_ASN1_TEMPLATE_NOEXP_D2I , ERR_R_NESTED_ASN1_ERROR );
701
721
goto err ;
0 commit comments