diff options
author | jsing <> | 2022-04-27 17:28:34 +0000 |
---|---|---|
committer | jsing <> | 2022-04-27 17:28:34 +0000 |
commit | 066ee7e25f2f9510191df30325a50ed15a2b910a (patch) | |
tree | ce2fe813fb0707c8eef7760eb692261e035d1948 /src/lib | |
parent | 4690f6229c18faef6d9158d023c5da46d0877da1 (diff) | |
download | openbsd-066ee7e25f2f9510191df30325a50ed15a2b910a.tar.gz openbsd-066ee7e25f2f9510191df30325a50ed15a2b910a.tar.bz2 openbsd-066ee7e25f2f9510191df30325a50ed15a2b910a.zip |
Remove the ASN.1 decoder tag/length cache (TLC).
Currently, every time an ASN.1 identifier and length is decoded it is
stored in a tag/length cache for potential reuse. However, the only time
this is actually of benefit is when decoding CHOICE or SEQUENCE with
OPTIONAL fields (or MSTRING and ANY due to less than ideal
implementation). For CHOICE and SEQUENCE with OPTIONAL fields the
current code attempts to decode the first option and if that fails, it
moves onto the next option and attempts to decode it, repeating until
it succeeds (or runs out of options).
There are a number of problems with the cache. Firstly, it adds complexity
to the ASN.1 decoder since it has to be passed up and down through the
various layers. Secondly, there is nothing that keeps the cached data in
synchronisation with the input stream. This makes it fragile and a
potential security risk. Thirdly, the type is in the public headers and
API, meaning that we cannot readily change the types or fields to improve
the code.
Testing also suggests that in typical decoding cases we actually get a
small performance increase by removing the cache. There are also several
other options that would improve decoding performance, which we can visit
once we have simpler and more robust code.
ok beck@ inoguchi@ tb@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 127 |
1 files changed, 37 insertions, 90 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 5c68834461..3936ecba63 100644 --- a/src/lib/libcrypto/asn1/tasn_dec.c +++ b/src/lib/libcrypto/asn1/tasn_dec.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tasn_dec.c,v 1.51 2022/04/26 20:00:18 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.52 2022/04/27 17:28:34 jsing Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 2000. | 3 | * project 2000. |
4 | */ | 4 | */ |
@@ -83,40 +83,28 @@ static int asn1_collect(CBB *cbb, const unsigned char **in, long len, | |||
83 | 83 | ||
84 | static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, | 84 | static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, |
85 | char *inf, char *cst, const unsigned char **in, long len, int exptag, | 85 | char *inf, char *cst, const unsigned char **in, long len, int exptag, |
86 | int expclass, char opt, ASN1_TLC *ctx); | 86 | int expclass, char opt); |
87 | 87 | ||
88 | static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, | 88 | static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, |
89 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx, | 89 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt, int depth); |
90 | int depth); | ||
91 | static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, | 90 | static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, |
92 | long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx, int depth); | 91 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); |
93 | static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, | 92 | static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, |
94 | long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx, int depth); | 93 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); |
95 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, | 94 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, |
96 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt, | 95 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt); |
97 | ASN1_TLC *ctx); | ||
98 | static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, | 96 | static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, |
99 | const ASN1_ITEM *it); | 97 | const ASN1_ITEM *it); |
100 | 98 | ||
101 | static void | ||
102 | asn1_tlc_invalidate(ASN1_TLC *ctx) | ||
103 | { | ||
104 | if (ctx != NULL) | ||
105 | ctx->valid = 0; | ||
106 | } | ||
107 | |||
108 | ASN1_VALUE * | 99 | ASN1_VALUE * |
109 | ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 100 | ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
110 | const ASN1_ITEM *it) | 101 | const ASN1_ITEM *it) |
111 | { | 102 | { |
112 | ASN1_VALUE *ptmpval = NULL; | 103 | ASN1_VALUE *ptmpval = NULL; |
113 | ASN1_TLC ctx; | ||
114 | |||
115 | asn1_tlc_invalidate(&ctx); | ||
116 | 104 | ||
117 | if (pval == NULL) | 105 | if (pval == NULL) |
118 | pval = &ptmpval; | 106 | pval = &ptmpval; |
119 | if (asn1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &ctx, 0) <= 0) | 107 | if (asn1_item_ex_d2i(pval, in, len, it, -1, 0, 0, 0) <= 0) |
120 | return NULL; | 108 | return NULL; |
121 | 109 | ||
122 | return *pval; | 110 | return *pval; |
@@ -126,11 +114,7 @@ int | |||
126 | ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 114 | ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
127 | const ASN1_TEMPLATE *tt) | 115 | const ASN1_TEMPLATE *tt) |
128 | { | 116 | { |
129 | ASN1_TLC ctx; | 117 | return asn1_template_ex_d2i(pval, in, len, tt, 0, 0); |
130 | |||
131 | asn1_tlc_invalidate(&ctx); | ||
132 | |||
133 | return asn1_template_ex_d2i(pval, in, len, tt, 0, &ctx, 0); | ||
134 | } | 118 | } |
135 | 119 | ||
136 | /* Decode an item, taking care of IMPLICIT tagging, if any. | 120 | /* Decode an item, taking care of IMPLICIT tagging, if any. |
@@ -139,13 +123,13 @@ ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
139 | 123 | ||
140 | static int | 124 | static int |
141 | asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 125 | asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
142 | const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx, | 126 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) |
143 | int depth) | ||
144 | { | 127 | { |
145 | const ASN1_TEMPLATE *tt, *errtt = NULL; | 128 | const ASN1_TEMPLATE *tt, *errtt = NULL; |
146 | const ASN1_EXTERN_FUNCS *ef; | 129 | const ASN1_EXTERN_FUNCS *ef; |
147 | const ASN1_AUX *aux = it->funcs; | 130 | const ASN1_AUX *aux = it->funcs; |
148 | ASN1_aux_cb *asn1_cb = NULL; | 131 | ASN1_aux_cb *asn1_cb = NULL; |
132 | ASN1_TLC ctx = { 0 }; | ||
149 | const unsigned char *p = NULL, *q; | 133 | const unsigned char *p = NULL, *q; |
150 | unsigned char oclass; | 134 | unsigned char oclass; |
151 | char seq_eoc, seq_nolen, cst, isopt; | 135 | char seq_eoc, seq_nolen, cst, isopt; |
@@ -184,10 +168,10 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
184 | goto err; | 168 | goto err; |
185 | } | 169 | } |
186 | return asn1_template_ex_d2i(pval, in, len, | 170 | return asn1_template_ex_d2i(pval, in, len, |
187 | it->templates, opt, ctx, depth); | 171 | it->templates, opt, depth); |
188 | } | 172 | } |
189 | return asn1_d2i_ex_primitive(pval, in, len, it, | 173 | return asn1_d2i_ex_primitive(pval, in, len, it, |
190 | tag, aclass, opt, ctx); | 174 | tag, aclass, opt); |
191 | break; | 175 | break; |
192 | 176 | ||
193 | case ASN1_ITYPE_MSTRING: | 177 | case ASN1_ITYPE_MSTRING: |
@@ -204,7 +188,7 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
204 | p = *in; | 188 | p = *in; |
205 | /* Just read in tag and class */ | 189 | /* Just read in tag and class */ |
206 | ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, | 190 | ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, |
207 | &p, len, -1, 0, 1, ctx); | 191 | &p, len, -1, 0, 1); |
208 | if (!ret) { | 192 | if (!ret) { |
209 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 193 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
210 | goto err; | 194 | goto err; |
@@ -227,13 +211,12 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
227 | goto err; | 211 | goto err; |
228 | } | 212 | } |
229 | return asn1_d2i_ex_primitive(pval, in, len, | 213 | return asn1_d2i_ex_primitive(pval, in, len, |
230 | it, otag, 0, 0, ctx); | 214 | it, otag, 0, 0); |
231 | 215 | ||
232 | case ASN1_ITYPE_EXTERN: | 216 | case ASN1_ITYPE_EXTERN: |
233 | /* Use new style d2i */ | 217 | /* Use new style d2i */ |
234 | ef = it->funcs; | 218 | ef = it->funcs; |
235 | return ef->asn1_ex_d2i(pval, in, len, | 219 | return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, &ctx); |
236 | it, tag, aclass, opt, ctx); | ||
237 | 220 | ||
238 | case ASN1_ITYPE_CHOICE: | 221 | case ASN1_ITYPE_CHOICE: |
239 | /* | 222 | /* |
@@ -269,8 +252,8 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
269 | /* We mark field as OPTIONAL so its absence | 252 | /* We mark field as OPTIONAL so its absence |
270 | * can be recognised. | 253 | * can be recognised. |
271 | */ | 254 | */ |
272 | ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, | 255 | ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, |
273 | depth); | 256 | depth); |
274 | /* If field not present, try the next one */ | 257 | /* If field not present, try the next one */ |
275 | if (ret == -1) | 258 | if (ret == -1) |
276 | continue; | 259 | continue; |
@@ -313,7 +296,7 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
313 | } | 296 | } |
314 | /* Get SEQUENCE length and update len, p */ | 297 | /* Get SEQUENCE length and update len, p */ |
315 | ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, | 298 | ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, |
316 | &p, len, tag, aclass, opt, ctx); | 299 | &p, len, tag, aclass, opt); |
317 | if (!ret) { | 300 | if (!ret) { |
318 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 301 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
319 | goto err; | 302 | goto err; |
@@ -388,7 +371,7 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
388 | * OPTIONAL */ | 371 | * OPTIONAL */ |
389 | 372 | ||
390 | ret = asn1_template_ex_d2i(pseqval, &p, len, | 373 | ret = asn1_template_ex_d2i(pseqval, &p, len, |
391 | seqtt, isopt, ctx, depth); | 374 | seqtt, isopt, depth); |
392 | if (!ret) { | 375 | if (!ret) { |
393 | errtt = seqtt; | 376 | errtt = seqtt; |
394 | goto err; | 377 | goto err; |
@@ -464,7 +447,7 @@ int | |||
464 | ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 447 | ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
465 | const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) | 448 | const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) |
466 | { | 449 | { |
467 | return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0); | 450 | return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, 0); |
468 | } | 451 | } |
469 | 452 | ||
470 | /* Templates are handled with two separate functions. | 453 | /* Templates are handled with two separate functions. |
@@ -473,7 +456,7 @@ ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
473 | 456 | ||
474 | static int | 457 | static int |
475 | asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | 458 | asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, |
476 | const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx, int depth) | 459 | const ASN1_TEMPLATE *tt, char opt, int depth) |
477 | { | 460 | { |
478 | int flags, aclass; | 461 | int flags, aclass; |
479 | int ret; | 462 | int ret; |
@@ -496,7 +479,7 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | |||
496 | * get the info. | 479 | * get the info. |
497 | */ | 480 | */ |
498 | ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, | 481 | ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, |
499 | &p, inlen, tt->tag, aclass, opt, ctx); | 482 | &p, inlen, tt->tag, aclass, opt); |
500 | q = p; | 483 | q = p; |
501 | if (!ret) { | 484 | if (!ret) { |
502 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 485 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
@@ -508,7 +491,7 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | |||
508 | return 0; | 491 | return 0; |
509 | } | 492 | } |
510 | /* We've found the field so it can't be OPTIONAL now */ | 493 | /* We've found the field so it can't be OPTIONAL now */ |
511 | ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth); | 494 | ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, depth); |
512 | if (!ret) { | 495 | if (!ret) { |
513 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 496 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
514 | return 0; | 497 | return 0; |
@@ -530,8 +513,7 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | |||
530 | } | 513 | } |
531 | } | 514 | } |
532 | } else | 515 | } else |
533 | return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, | 516 | return asn1_template_noexp_d2i(val, in, inlen, tt, opt, depth); |
534 | depth); | ||
535 | 517 | ||
536 | *in = p; | 518 | *in = p; |
537 | return 1; | 519 | return 1; |
@@ -543,7 +525,7 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | |||
543 | 525 | ||
544 | static int | 526 | static int |
545 | asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | 527 | asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, |
546 | const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx, int depth) | 528 | const ASN1_TEMPLATE *tt, char opt, int depth) |
547 | { | 529 | { |
548 | int flags, aclass; | 530 | int flags, aclass; |
549 | int ret; | 531 | int ret; |
@@ -574,7 +556,7 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | |||
574 | } | 556 | } |
575 | /* Get the tag */ | 557 | /* Get the tag */ |
576 | ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, | 558 | ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, |
577 | &p, len, sktag, skaclass, opt, ctx); | 559 | &p, len, sktag, skaclass, opt); |
578 | if (!ret) { | 560 | if (!ret) { |
579 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 561 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
580 | return 0; | 562 | return 0; |
@@ -615,7 +597,7 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | |||
615 | } | 597 | } |
616 | skfield = NULL; | 598 | skfield = NULL; |
617 | if (!asn1_item_ex_d2i(&skfield, &p, len, | 599 | if (!asn1_item_ex_d2i(&skfield, &p, len, |
618 | tt->item, -1, 0, 0, ctx, depth)) { | 600 | tt->item, -1, 0, 0, depth)) { |
619 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 601 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
620 | goto err; | 602 | goto err; |
621 | } | 603 | } |
@@ -633,7 +615,7 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | |||
633 | } else if (flags & ASN1_TFLG_IMPTAG) { | 615 | } else if (flags & ASN1_TFLG_IMPTAG) { |
634 | /* IMPLICIT tagging */ | 616 | /* IMPLICIT tagging */ |
635 | ret = asn1_item_ex_d2i(val, &p, len, | 617 | ret = asn1_item_ex_d2i(val, &p, len, |
636 | tt->item, tt->tag, aclass, opt, ctx, depth); | 618 | tt->item, tt->tag, aclass, opt, depth); |
637 | if (!ret) { | 619 | if (!ret) { |
638 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 620 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
639 | goto err; | 621 | goto err; |
@@ -642,7 +624,7 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | |||
642 | } else { | 624 | } else { |
643 | /* Nothing special */ | 625 | /* Nothing special */ |
644 | ret = asn1_item_ex_d2i(val, &p, len, tt->item, | 626 | ret = asn1_item_ex_d2i(val, &p, len, tt->item, |
645 | -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx, depth); | 627 | -1, tt->flags & ASN1_TFLG_COMBINE, opt, depth); |
646 | if (!ret) { | 628 | if (!ret) { |
647 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 629 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
648 | goto err; | 630 | goto err; |
@@ -660,7 +642,7 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | |||
660 | 642 | ||
661 | static int | 643 | static int |
662 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | 644 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, |
663 | const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) | 645 | const ASN1_ITEM *it, int tag, int aclass, char opt) |
664 | { | 646 | { |
665 | int ret = 0, utype; | 647 | int ret = 0, utype; |
666 | long plen; | 648 | long plen; |
@@ -699,7 +681,7 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
699 | } | 681 | } |
700 | p = *in; | 682 | p = *in; |
701 | ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, | 683 | ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, |
702 | &p, inlen, -1, 0, 0, ctx); | 684 | &p, inlen, -1, 0, 0); |
703 | if (!ret) { | 685 | if (!ret) { |
704 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 686 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
705 | return 0; | 687 | return 0; |
@@ -714,7 +696,7 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
714 | p = *in; | 696 | p = *in; |
715 | /* Check header */ | 697 | /* Check header */ |
716 | ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, | 698 | ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, |
717 | &p, inlen, tag, aclass, opt, ctx); | 699 | &p, inlen, tag, aclass, opt); |
718 | if (!ret) { | 700 | if (!ret) { |
719 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 701 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
720 | return 0; | 702 | return 0; |
@@ -724,12 +706,7 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | |||
724 | /* SEQUENCE, SET and "OTHER" are left in encoded form */ | 706 | /* SEQUENCE, SET and "OTHER" are left in encoded form */ |
725 | if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || | 707 | if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || |
726 | (utype == V_ASN1_OTHER)) { | 708 | (utype == V_ASN1_OTHER)) { |
727 | /* Clear context cache for type OTHER because the auto clear | 709 | if (utype != V_ASN1_OTHER && !cst) { |
728 | * when we have a exact match wont work | ||
729 | */ | ||
730 | if (utype == V_ASN1_OTHER) { | ||
731 | asn1_tlc_invalidate(ctx); | ||
732 | } else if (!cst) { | ||
733 | /* SEQUENCE and SET must be constructed */ | 710 | /* SEQUENCE and SET must be constructed */ |
734 | ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); | 711 | ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); |
735 | return 0; | 712 | return 0; |
@@ -964,7 +941,7 @@ asn1_find_end(const unsigned char **in, long len, char inf) | |||
964 | q = p; | 941 | q = p; |
965 | /* Just read in a header: only care about the length */ | 942 | /* Just read in a header: only care about the length */ |
966 | if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, | 943 | if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, |
967 | -1, 0, 0, NULL)) { | 944 | -1, 0, 0)) { |
968 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 945 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
969 | return 0; | 946 | return 0; |
970 | } | 947 | } |
@@ -1027,7 +1004,7 @@ asn1_collect(CBB *cbb, const unsigned char **in, long len, char inf, | |||
1027 | } | 1004 | } |
1028 | 1005 | ||
1029 | if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, | 1006 | if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, |
1030 | len, tag, aclass, 0, NULL)) { | 1007 | len, tag, aclass, 0)) { |
1031 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 1008 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
1032 | return 0; | 1009 | return 0; |
1033 | } | 1010 | } |
@@ -1079,7 +1056,7 @@ asn1_check_eoc(const unsigned char **in, long len) | |||
1079 | static int | 1056 | static int |
1080 | asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, | 1057 | asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, |
1081 | char *cst, const unsigned char **in, long len, int exptag, int expclass, | 1058 | char *cst, const unsigned char **in, long len, int exptag, int expclass, |
1082 | char opt, ASN1_TLC *ctx) | 1059 | char opt) |
1083 | { | 1060 | { |
1084 | int i; | 1061 | int i; |
1085 | int ptag, pclass; | 1062 | int ptag, pclass; |
@@ -1089,35 +1066,9 @@ asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, | |||
1089 | p = *in; | 1066 | p = *in; |
1090 | q = p; | 1067 | q = p; |
1091 | 1068 | ||
1092 | if (ctx && ctx->valid) { | 1069 | i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); |
1093 | i = ctx->ret; | ||
1094 | plen = ctx->plen; | ||
1095 | pclass = ctx->pclass; | ||
1096 | ptag = ctx->ptag; | ||
1097 | p += ctx->hdrlen; | ||
1098 | } else { | ||
1099 | i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); | ||
1100 | if (ctx) { | ||
1101 | ctx->ret = i; | ||
1102 | ctx->plen = plen; | ||
1103 | ctx->pclass = pclass; | ||
1104 | ctx->ptag = ptag; | ||
1105 | ctx->hdrlen = p - q; | ||
1106 | ctx->valid = 1; | ||
1107 | /* If definite length, and no error, length + | ||
1108 | * header can't exceed total amount of data available. | ||
1109 | */ | ||
1110 | if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { | ||
1111 | ASN1error(ASN1_R_TOO_LONG); | ||
1112 | asn1_tlc_invalidate(ctx); | ||
1113 | return 0; | ||
1114 | } | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | if (i & 0x80) { | 1070 | if (i & 0x80) { |
1119 | ASN1error(ASN1_R_BAD_OBJECT_HEADER); | 1071 | ASN1error(ASN1_R_BAD_OBJECT_HEADER); |
1120 | asn1_tlc_invalidate(ctx); | ||
1121 | return 0; | 1072 | return 0; |
1122 | } | 1073 | } |
1123 | if (exptag >= 0) { | 1074 | if (exptag >= 0) { |
@@ -1127,13 +1078,9 @@ asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, | |||
1127 | */ | 1078 | */ |
1128 | if (opt) | 1079 | if (opt) |
1129 | return -1; | 1080 | return -1; |
1130 | asn1_tlc_invalidate(ctx); | ||
1131 | ASN1error(ASN1_R_WRONG_TAG); | 1081 | ASN1error(ASN1_R_WRONG_TAG); |
1132 | return 0; | 1082 | return 0; |
1133 | } | 1083 | } |
1134 | /* We have a tag and class match: | ||
1135 | * assume we are going to do something with it */ | ||
1136 | asn1_tlc_invalidate(ctx); | ||
1137 | } | 1084 | } |
1138 | 1085 | ||
1139 | if (i & 1) | 1086 | if (i & 1) |