summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2022-04-27 17:28:34 +0000
committerjsing <>2022-04-27 17:28:34 +0000
commit066ee7e25f2f9510191df30325a50ed15a2b910a (patch)
treece2fe813fb0707c8eef7760eb692261e035d1948 /src/lib
parent4690f6229c18faef6d9158d023c5da46d0877da1 (diff)
downloadopenbsd-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.c127
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
84static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, 84static 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
88static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, 88static 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);
91static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, 90static 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);
93static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, 92static 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);
95static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, 94static 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);
98static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, 96static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype,
99 const ASN1_ITEM *it); 97 const ASN1_ITEM *it);
100 98
101static void
102asn1_tlc_invalidate(ASN1_TLC *ctx)
103{
104 if (ctx != NULL)
105 ctx->valid = 0;
106}
107
108ASN1_VALUE * 99ASN1_VALUE *
109ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, 100ASN1_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
126ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, 114ASN1_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
140static int 124static int
141asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, 125asn1_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
464ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, 447ASN1_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
474static int 457static int
475asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, 458asn1_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
544static int 526static int
545asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, 527asn1_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
661static int 643static int
662asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, 644asn1_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)
1079static int 1056static int
1080asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, 1057asn1_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)