summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2022-05-19 19:31:39 +0000
committerjsing <>2022-05-19 19:31:39 +0000
commit94f8e2dd8817ff74b89e103a09ba4b9b884f75ec (patch)
treed5a8d51f4e6231a9fa37f965f0c30ea726552ffa /src
parent7872788c306d2030b56275c8d2970b04967c6f3b (diff)
downloadopenbsd-94f8e2dd8817ff74b89e103a09ba4b9b884f75ec.tar.gz
openbsd-94f8e2dd8817ff74b89e103a09ba4b9b884f75ec.tar.bz2
openbsd-94f8e2dd8817ff74b89e103a09ba4b9b884f75ec.zip
Rewrite the asn1_template_*() functions with CBS.
Rewrite the asn1_template_*() functions with CBS, readable variable names and free then alloc. This was the last caller of asn1_check_eoc() and asn1_check_tag(), hence remove them and rename the _cbs suffixed versions in their place. ok tb@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/asn1/tasn_dec.c386
1 files changed, 168 insertions, 218 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c
index 234484d6b2..79cbd4c75b 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.70 2022/05/17 19:09:16 jsing Exp $ */ 1/* $OpenBSD: tasn_dec.c,v 1.71 2022/05/19 19:31:39 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 */
@@ -75,22 +75,16 @@
75 */ 75 */
76#define ASN1_MAX_CONSTRUCTED_NEST 30 76#define ASN1_MAX_CONSTRUCTED_NEST 30
77 77
78static int asn1_check_eoc(const unsigned char **in, long len); 78static int asn1_check_eoc(CBS *cbs);
79static int asn1_check_eoc_cbs(CBS *cbs);
80static int asn1_find_end(CBS *cbs, size_t length, char indefinite); 79static int asn1_find_end(CBS *cbs, size_t length, char indefinite);
81 80
82static int asn1_collect(CBB *cbb, CBS *cbs, char indefinite, int expected_tag, 81static int asn1_collect(CBB *cbb, CBS *cbs, char indefinite, int expected_tag,
83 int expected_class, int depth); 82 int expected_class, int depth);
84 83
85static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, 84static int asn1_template_ex_d2i(ASN1_VALUE **pval, CBS *cbs,
86 long len, const ASN1_ITEM *it, int tag_number, int tag_class, char optional, 85 const ASN1_TEMPLATE *tt, char optional, int depth);
87 int depth); 86static int asn1_template_noexp_d2i(ASN1_VALUE **pval, CBS *cbs,
88static int asn1_template_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs,
89 const ASN1_TEMPLATE *tt, char optional, int depth); 87 const ASN1_TEMPLATE *tt, char optional, int depth);
90static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
91 long len, const ASN1_TEMPLATE *tt, char opt, int depth);
92static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
93 long len, const ASN1_TEMPLATE *tt, char opt, int depth);
94static int asn1_d2i_ex_mstring(ASN1_VALUE **pval, CBS *CBS, 88static int asn1_d2i_ex_mstring(ASN1_VALUE **pval, CBS *CBS,
95 const ASN1_ITEM *it, int tag_number, int tag_class, char optional); 89 const ASN1_ITEM *it, int tag_number, int tag_class, char optional);
96static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, 90static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs,
@@ -98,22 +92,19 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs,
98static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, 92static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype,
99 const ASN1_ITEM *it); 93 const ASN1_ITEM *it);
100 94
101static int asn1_check_tag_cbs(CBS *cbs, size_t *out_len, int *out_tag, 95static int asn1_check_tag(CBS *cbs, size_t *out_len, int *out_tag,
102 uint8_t *out_class, char *out_indefinite, char *out_constructed, 96 uint8_t *out_class, char *out_indefinite, char *out_constructed,
103 int expected_tag, int expected_class, char optional); 97 int expected_tag, int expected_class, char optional);
104static int asn1_check_tag(long *out_len, int *out_tag, uint8_t *out_class,
105 char *out_indefinite, char *out_constructed, const unsigned char **in,
106 long len, int expected_tag, int expected_class, char optional);
107 98
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 inlen,
110 const ASN1_ITEM *it) 101 const ASN1_ITEM *it)
111{ 102{
112 ASN1_VALUE *ptmpval = NULL; 103 ASN1_VALUE *ptmpval = NULL;
113 104
114 if (pval == NULL) 105 if (pval == NULL)
115 pval = &ptmpval; 106 pval = &ptmpval;
116 if (asn1_item_ex_d2i(pval, in, len, it, -1, 0, 0, 0) <= 0) 107 if (ASN1_item_ex_d2i(pval, in, inlen, it, -1, 0, 0, 0) <= 0)
117 return NULL; 108 return NULL;
118 109
119 return *pval; 110 return *pval;
@@ -123,7 +114,17 @@ int
123ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, 114ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
124 const ASN1_TEMPLATE *tt) 115 const ASN1_TEMPLATE *tt)
125{ 116{
126 return asn1_template_ex_d2i(pval, in, len, tt, 0, 0); 117 CBS cbs;
118 int ret;
119
120 if (len < 0)
121 return 0;
122
123 CBS_init(&cbs, *in, len);
124 if ((ret = asn1_template_ex_d2i(pval, &cbs, tt, 0, 0)) == 1)
125 *in = CBS_data(&cbs);
126
127 return ret;
127} 128}
128 129
129static int 130static int
@@ -172,7 +173,7 @@ asn1_item_ex_d2i_choice(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
172 pchptr = asn1_get_field_ptr(&achoice, tt); 173 pchptr = asn1_get_field_ptr(&achoice, tt);
173 174
174 /* Mark field as OPTIONAL so its absence can be identified. */ 175 /* Mark field as OPTIONAL so its absence can be identified. */
175 ret = asn1_template_ex_d2i_cbs(pchptr, cbs, tt, 1, depth); 176 ret = asn1_template_ex_d2i(pchptr, cbs, tt, 1, depth);
176 if (ret == -1) 177 if (ret == -1)
177 continue; 178 continue;
178 if (ret != 1) { 179 if (ret != 1) {
@@ -255,7 +256,7 @@ asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
255 } 256 }
256 257
257 /* Read ASN.1 SEQUENCE header. */ 258 /* Read ASN.1 SEQUENCE header. */
258 ret = asn1_check_tag_cbs(&cbs_seq, &length, NULL, NULL, &indefinite, 259 ret = asn1_check_tag(&cbs_seq, &length, NULL, NULL, &indefinite,
259 &constructed, tag_number, tag_class, optional); 260 &constructed, tag_number, tag_class, optional);
260 if (ret == -1) 261 if (ret == -1)
261 return -1; 262 return -1;
@@ -289,7 +290,7 @@ asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
289 } 290 }
290 291
291 for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { 292 for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
292 if (asn1_check_eoc_cbs(&cbs_seq_content)) { 293 if (asn1_check_eoc(&cbs_seq_content)) {
293 if (!indefinite) { 294 if (!indefinite) {
294 ASN1error(ASN1_R_UNEXPECTED_EOC); 295 ASN1error(ASN1_R_UNEXPECTED_EOC);
295 goto err; 296 goto err;
@@ -315,7 +316,7 @@ asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
315 if (i == it->tcount - 1) 316 if (i == it->tcount - 1)
316 optional_field = 0; 317 optional_field = 0;
317 318
318 ret = asn1_template_ex_d2i_cbs(pseqval, &cbs_seq_content, 319 ret = asn1_template_ex_d2i(pseqval, &cbs_seq_content,
319 seqtt, optional_field, depth); 320 seqtt, optional_field, depth);
320 if (ret == -1) { 321 if (ret == -1) {
321 /* Absent OPTIONAL component. */ 322 /* Absent OPTIONAL component. */
@@ -328,7 +329,7 @@ asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
328 } 329 }
329 } 330 }
330 331
331 if (eoc_needed && !asn1_check_eoc_cbs(&cbs_seq_content)) { 332 if (eoc_needed && !asn1_check_eoc(&cbs_seq_content)) {
332 ASN1error(ASN1_R_MISSING_EOC); 333 ASN1error(ASN1_R_MISSING_EOC);
333 goto err; 334 goto err;
334 } 335 }
@@ -395,7 +396,7 @@ asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
395 * If 'opt' set and tag mismatch return -1 to handle OPTIONAL 396 * If 'opt' set and tag mismatch return -1 to handle OPTIONAL
396 */ 397 */
397static int 398static int
398asn1_item_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, 399asn1_item_ex_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
399 int tag_number, int tag_class, char optional, int depth) 400 int tag_number, int tag_class, char optional, int depth)
400{ 401{
401 const ASN1_EXTERN_FUNCS *ef = it->funcs; 402 const ASN1_EXTERN_FUNCS *ef = it->funcs;
@@ -425,7 +426,7 @@ asn1_item_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
425 ASN1error(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); 426 ASN1error(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
426 goto err; 427 goto err;
427 } 428 }
428 return asn1_template_ex_d2i_cbs(pval, cbs, 429 return asn1_template_ex_d2i(pval, cbs,
429 it->templates, optional, depth); 430 it->templates, optional, depth);
430 } 431 }
431 return asn1_d2i_ex_primitive(pval, cbs, it, tag_number, 432 return asn1_d2i_ex_primitive(pval, cbs, it, tag_number,
@@ -467,10 +468,10 @@ asn1_item_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
467 return 0; 468 return 0;
468} 469}
469 470
470static int 471int
471asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen, 472ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen,
472 const ASN1_ITEM *it, int tag_number, int tag_class, char optional, 473 const ASN1_ITEM *it, int tag_number, int tag_class, char optional,
473 int depth) 474 ASN1_TLC *ctx)
474{ 475{
475 CBS cbs; 476 CBS cbs;
476 int ret; 477 int ret;
@@ -480,219 +481,210 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen,
480 481
481 CBS_init(&cbs, *in, inlen); 482 CBS_init(&cbs, *in, inlen);
482 483
483 ret = asn1_item_ex_d2i_cbs(pval, &cbs, it, tag_number, tag_class, 484 if ((ret = asn1_item_ex_d2i(pval, &cbs, it, tag_number, tag_class,
484 optional, depth); 485 optional, 0)) == 1)
485
486 if (ret == 1)
487 *in = CBS_data(&cbs); 486 *in = CBS_data(&cbs);
488 487
489 return ret; 488 return ret;
490} 489}
491 490
492int
493ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
494 const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx)
495{
496 return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, 0);
497}
498
499static int 491static int
500asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, 492asn1_template_ex_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt,
501 const ASN1_TEMPLATE *tt, char opt, int depth) 493 char optional, int depth)
502{ 494{
503 int flags, aclass; 495 CBS cbs_exp, cbs_exp_content;
496 char constructed, indefinite;
497 size_t length;
504 int ret; 498 int ret;
505 long len;
506 const unsigned char *p, *q;
507 char exp_eoc;
508 char cst;
509 499
510 if (!val) 500 if (pval == NULL)
511 return 0; 501 return 0;
512 flags = tt->flags;
513 aclass = flags & ASN1_TFLG_TAG_CLASS;
514 502
515 p = *in; 503 /* Check if EXPLICIT tag is expected. */
504 if ((tt->flags & ASN1_TFLG_EXPTAG) == 0)
505 return asn1_template_noexp_d2i(pval, cbs, tt, optional, depth);
516 506
517 /* Check if EXPLICIT tag expected */ 507 CBS_init(&cbs_exp, CBS_data(cbs), CBS_len(cbs));
518 if ((flags & ASN1_TFLG_EXPTAG) == 0)
519 return asn1_template_noexp_d2i(val, in, inlen, tt, opt, depth);
520 508
521 /* Need to work out amount of data available to the inner 509 /* Read ASN.1 header for EXPLICIT tagged object. */
522 * content and where it starts: so read in EXPLICIT header to 510 ret = asn1_check_tag(&cbs_exp, &length, NULL, NULL, &indefinite,
523 * get the info. 511 &constructed, tt->tag, tt->flags & ASN1_TFLG_TAG_CLASS, optional);
524 */ 512 if (ret == -1)
525 ret = asn1_check_tag(&len, NULL, NULL, &exp_eoc, &cst, &p, 513 return -1;
526 inlen, tt->tag, aclass, opt); 514 if (ret != 1) {
527 q = p;
528 if (!ret) {
529 ASN1error(ERR_R_NESTED_ASN1_ERROR); 515 ASN1error(ERR_R_NESTED_ASN1_ERROR);
530 return 0; 516 return 0;
531 } else if (ret == -1) 517 }
532 return -1; 518
533 if (!cst) { 519 if (!constructed) {
534 ASN1error(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); 520 ASN1error(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
535 return 0; 521 return 0;
536 } 522 }
537 /* We've found the field so it can't be OPTIONAL now */ 523
538 ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, depth); 524 if (indefinite) {
539 if (!ret) { 525 CBS_init(&cbs_exp_content, CBS_data(&cbs_exp), CBS_len(&cbs_exp));
526 } else {
527 if (!CBS_get_bytes(&cbs_exp, &cbs_exp_content, length))
528 goto err;
529 }
530
531 if ((ret = asn1_template_noexp_d2i(pval, &cbs_exp_content, tt, 0,
532 depth)) != 1) {
540 ASN1error(ERR_R_NESTED_ASN1_ERROR); 533 ASN1error(ERR_R_NESTED_ASN1_ERROR);
541 return 0; 534 return 0;
542 } 535 }
543 /* We read the field in OK so update length */ 536
544 len -= p - q; 537 if (indefinite) {
545 if (exp_eoc) { 538 if (!asn1_check_eoc(&cbs_exp_content)) {
546 /* If NDEF we must have an EOC here */
547 if (!asn1_check_eoc(&p, len)) {
548 ASN1error(ASN1_R_MISSING_EOC); 539 ASN1error(ASN1_R_MISSING_EOC);
549 goto err; 540 goto err;
550 } 541 }
551 } else { 542 if (!CBS_skip(&cbs_exp, CBS_offset(&cbs_exp_content)))
552 /* Otherwise we must hit the EXPLICIT tag end or its
553 * an error */
554 if (len) {
555 ASN1error(ASN1_R_EXPLICIT_LENGTH_MISMATCH);
556 goto err; 543 goto err;
557 } 544 } else if (CBS_len(&cbs_exp_content) != 0) {
545 ASN1error(ASN1_R_SEQUENCE_LENGTH_MISMATCH);
546 goto err;
558 } 547 }
559 548
560 *in = p; 549 if (!CBS_skip(cbs, CBS_offset(&cbs_exp)))
550 goto err;
551
561 return 1; 552 return 1;
562 553
563 err: 554 err:
564 ASN1_template_free(val, tt); 555 ASN1_template_free(pval, tt);
565 return 0; 556 return 0;
566} 557}
567 558
568static int 559static void
569asn1_template_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt, 560asn1_template_stack_of_free(STACK_OF(ASN1_VALUE) *avals, const ASN1_TEMPLATE *tt) {
570 char optional, int depth) 561 ASN1_VALUE *aval;
571{
572 const unsigned char *p;
573 int ret;
574 562
575 if (CBS_len(cbs) > LONG_MAX) 563 if (avals == NULL)
576 return 0; 564 return;
577 565
578 p = CBS_data(cbs); 566 while (sk_ASN1_VALUE_num(avals) > 0) {
579 ret = asn1_template_ex_d2i(pval, &p, (long)CBS_len(cbs), tt, 567 aval = sk_ASN1_VALUE_pop(avals);
580 optional, depth); 568 ASN1_item_ex_free(&aval, tt->item);
581 if (ret == 1) {
582 if (!CBS_skip(cbs, p - CBS_data(cbs)))
583 return 0;
584 } 569 }
585 return ret; 570 sk_ASN1_VALUE_free(avals);
586} 571}
587 572
588static int 573static int
589asn1_template_stack_of_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, 574asn1_template_stack_of_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt,
590 const ASN1_TEMPLATE *tt, char opt, int depth) 575 char optional, int depth)
591{ 576{
592 const unsigned char *p, *q; 577 CBS cbs_object, cbs_object_content;
593 int sktag, skaclass; 578 STACK_OF(ASN1_VALUE) *avals = NULL;
594 char sk_eoc; 579 ASN1_VALUE *aval = NULL;
595 long len; 580 int tag_number, tag_class;
581 int eoc_needed;
582 char indefinite;
583 size_t length;
596 int ret; 584 int ret;
597 585
598 /* SET OF, SEQUENCE OF */ 586 CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs));
599 587
600 p = *in; 588 if (pval == NULL)
601 q = p; 589 return 0;
602 590
603 /* First work out expected inner tag value */ 591 asn1_template_stack_of_free((STACK_OF(ASN1_VALUE) *)*pval, tt);
604 if (tt->flags & ASN1_TFLG_IMPTAG) { 592 *pval = NULL;
605 sktag = tt->tag; 593
606 skaclass = tt->flags & ASN1_TFLG_TAG_CLASS; 594 tag_number = tt->tag;
607 } else { 595 tag_class = tt->flags & ASN1_TFLG_TAG_CLASS;
608 skaclass = V_ASN1_UNIVERSAL; 596
609 if (tt->flags & ASN1_TFLG_SET_OF) 597 /* Determine the inner tag value for SET OF or SEQUENCE OF. */
610 sktag = V_ASN1_SET; 598 if ((tt->flags & ASN1_TFLG_IMPTAG) == 0) {
611 else 599 tag_number = V_ASN1_SEQUENCE;
612 sktag = V_ASN1_SEQUENCE; 600 tag_class = V_ASN1_UNIVERSAL;
613 } 601 if ((tt->flags & ASN1_TFLG_SET_OF) != 0)
614 /* Get the tag */ 602 tag_number = V_ASN1_SET;
615 ret = asn1_check_tag(&len, NULL, NULL, &sk_eoc, NULL, &p, inlen, 603 }
616 sktag, skaclass, opt); 604
617 if (!ret) { 605 ret = asn1_check_tag(&cbs_object, &length, NULL, NULL, &indefinite,
606 NULL, tag_number, tag_class, optional);
607 if (ret == -1)
608 return -1;
609 if (ret != 1) {
618 ASN1error(ERR_R_NESTED_ASN1_ERROR); 610 ASN1error(ERR_R_NESTED_ASN1_ERROR);
619 return 0; 611 return 0;
620 } else if (ret == -1)
621 return -1;
622 if (!*val)
623 *val = (ASN1_VALUE *)sk_new_null();
624 else {
625 /* We've got a valid STACK: free up any items present */
626 STACK_OF(ASN1_VALUE) *sktmp =
627 (STACK_OF(ASN1_VALUE) *)*val;
628 ASN1_VALUE *vtmp;
629 while (sk_ASN1_VALUE_num(sktmp) > 0) {
630 vtmp = sk_ASN1_VALUE_pop(sktmp);
631 ASN1_item_ex_free(&vtmp,
632 tt->item);
633 }
634 } 612 }
635 613
636 if (!*val) { 614 if (indefinite) {
615 eoc_needed = 1;
616 CBS_init(&cbs_object_content, CBS_data(&cbs_object),
617 CBS_len(&cbs_object));
618 } else {
619 eoc_needed = 0;
620 if (!CBS_get_bytes(&cbs_object, &cbs_object_content,
621 length))
622 goto err;
623 }
624
625 if ((avals = sk_ASN1_VALUE_new_null()) == NULL) {
637 ASN1error(ERR_R_MALLOC_FAILURE); 626 ASN1error(ERR_R_MALLOC_FAILURE);
638 goto err; 627 goto err;
639 } 628 }
640 629
641 /* Read as many items as we can */ 630 /* Read as many items as possible. */
642 while (len > 0) { 631 while (CBS_len(&cbs_object_content) > 0) {
643 ASN1_VALUE *skfield; 632 if (asn1_check_eoc(&cbs_object_content)) {
644 q = p; 633 if (!eoc_needed) {
645 /* See if EOC found */
646 if (asn1_check_eoc(&p, len)) {
647 if (!sk_eoc) {
648 ASN1error(ASN1_R_UNEXPECTED_EOC); 634 ASN1error(ASN1_R_UNEXPECTED_EOC);
649 goto err; 635 goto err;
650 } 636 }
651 len -= p - q; 637 eoc_needed = 0;
652 sk_eoc = 0;
653 break; 638 break;
654 } 639 }
655 skfield = NULL; 640 if (!asn1_item_ex_d2i(&aval, &cbs_object_content, tt->item,
656 if (!asn1_item_ex_d2i(&skfield, &p, len, 641 -1, 0, 0, depth)) {
657 tt->item, -1, 0, 0, depth)) {
658 ASN1error(ERR_R_NESTED_ASN1_ERROR); 642 ASN1error(ERR_R_NESTED_ASN1_ERROR);
659 goto err; 643 goto err;
660 } 644 }
661 len -= p - q; 645 if (!sk_ASN1_VALUE_push(avals, aval)) {
662 if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val,
663 skfield)) {
664 ASN1error(ERR_R_MALLOC_FAILURE); 646 ASN1error(ERR_R_MALLOC_FAILURE);
665 goto err; 647 goto err;
666 } 648 }
649 aval = NULL;
667 } 650 }
668 if (sk_eoc) { 651 if (eoc_needed) {
669 ASN1error(ASN1_R_MISSING_EOC); 652 ASN1error(ASN1_R_MISSING_EOC);
670 goto err; 653 goto err;
671 } 654 }
672 655
673 *in = p; 656 if (indefinite) {
657 if (!CBS_skip(&cbs_object, CBS_offset(&cbs_object_content)))
658 goto err;
659 }
660
661 if (!CBS_skip(cbs, CBS_offset(&cbs_object)))
662 goto err;
663
664 *pval = (ASN1_VALUE *)avals;
665 avals = NULL;
666
674 return 1; 667 return 1;
675 668
676 err: 669 err:
677 ASN1_template_free(val, tt); 670 asn1_template_stack_of_free(avals, tt);
671 ASN1_item_ex_free(&aval, tt->item);
672
678 return 0; 673 return 0;
679} 674}
680 675
681static int 676static int
682asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, 677asn1_template_noexp_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt,
683 const ASN1_TEMPLATE *tt, char opt, int depth) 678 char optional, int depth)
684{ 679{
685 const unsigned char *p;
686 int tag_number, tag_class; 680 int tag_number, tag_class;
687 int ret; 681 int ret;
688 682
689 if (!val) 683 if (pval == NULL)
690 return 0; 684 return 0;
691 685
692 p = *in;
693
694 if ((tt->flags & ASN1_TFLG_SK_MASK) != 0) 686 if ((tt->flags & ASN1_TFLG_SK_MASK) != 0)
695 return asn1_template_stack_of_d2i(val, in, len, tt, opt, depth); 687 return asn1_template_stack_of_d2i(pval, cbs, tt, optional, depth);
696 688
697 tag_number = -1; 689 tag_number = -1;
698 tag_class = V_ASN1_UNIVERSAL; 690 tag_class = V_ASN1_UNIVERSAL;
@@ -703,18 +695,20 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
703 tag_class = tt->flags & ASN1_TFLG_TAG_CLASS; 695 tag_class = tt->flags & ASN1_TFLG_TAG_CLASS;
704 } 696 }
705 697
706 ret = asn1_item_ex_d2i(val, &p, len, tt->item, tag_number, tag_class, opt, depth); 698 ret = asn1_item_ex_d2i(pval, cbs, tt->item, tag_number, tag_class,
707 if (!ret) { 699 optional, depth);
700 if (ret == -1)
701 return -1;
702 if (ret != 1) {
708 ASN1error(ERR_R_NESTED_ASN1_ERROR); 703 ASN1error(ERR_R_NESTED_ASN1_ERROR);
709 goto err; 704 goto err;
710 } else if (ret == -1) 705 }
711 return -1;
712 706
713 *in = p;
714 return 1; 707 return 1;
715 708
716 err: 709 err:
717 ASN1_template_free(val, tt); 710 /* XXX - The called function should have freed already. */
711 ASN1_template_free(pval, tt);
718 return 0; 712 return 0;
719} 713}
720 714
@@ -824,7 +818,7 @@ asn1_d2i_ex_any(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
824 } 818 }
825 819
826 /* Determine type from ASN.1 tag. */ 820 /* Determine type from ASN.1 tag. */
827 if (asn1_check_tag_cbs(&cbs_object, &length, &object_type, &object_class, 821 if (asn1_check_tag(&cbs_object, &length, &object_type, &object_class,
828 &indefinite, &constructed, -1, 0, 0) != 1) { 822 &indefinite, &constructed, -1, 0, 0) != 1) {
829 ASN1error(ERR_R_NESTED_ASN1_ERROR); 823 ASN1error(ERR_R_NESTED_ASN1_ERROR);
830 return 0; 824 return 0;
@@ -857,7 +851,7 @@ asn1_d2i_ex_mstring(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
857 return 0; 851 return 0;
858 } 852 }
859 853
860 if (asn1_check_tag_cbs(&cbs_object, &length, &object_tag, &object_class, 854 if (asn1_check_tag(&cbs_object, &length, &object_tag, &object_class,
861 &indefinite, &constructed, -1, 0, 1) != 1) { 855 &indefinite, &constructed, -1, 0, 1) != 1) {
862 ASN1error(ERR_R_NESTED_ASN1_ERROR); 856 ASN1error(ERR_R_NESTED_ASN1_ERROR);
863 return 0; 857 return 0;
@@ -905,7 +899,7 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
905 tag_class = V_ASN1_UNIVERSAL; 899 tag_class = V_ASN1_UNIVERSAL;
906 } 900 }
907 901
908 ret = asn1_check_tag_cbs(&cbs_object, &length, NULL, NULL, &indefinite, 902 ret = asn1_check_tag(&cbs_object, &length, NULL, NULL, &indefinite,
909 &constructed, tag_number, tag_class, optional); 903 &constructed, tag_number, tag_class, optional);
910 if (ret == -1) 904 if (ret == -1)
911 return -1; 905 return -1;
@@ -1094,12 +1088,12 @@ asn1_find_end(CBS *cbs, size_t length, char indefinite)
1094 eoc_count = 1; 1088 eoc_count = 1;
1095 1089
1096 while (CBS_len(cbs) > 0) { 1090 while (CBS_len(cbs) > 0) {
1097 if (asn1_check_eoc_cbs(cbs)) { 1091 if (asn1_check_eoc(cbs)) {
1098 if (--eoc_count == 0) 1092 if (--eoc_count == 0)
1099 break; 1093 break;
1100 continue; 1094 continue;
1101 } 1095 }
1102 if (!asn1_check_tag_cbs(cbs, &length, NULL, NULL, 1096 if (!asn1_check_tag(cbs, &length, NULL, NULL,
1103 &indefinite, NULL, -1, 0, 0)) { 1097 &indefinite, NULL, -1, 0, 0)) {
1104 ASN1error(ERR_R_NESTED_ASN1_ERROR); 1098 ASN1error(ERR_R_NESTED_ASN1_ERROR);
1105 return 0; 1099 return 0;
@@ -1147,14 +1141,14 @@ asn1_collect(CBB *cbb, CBS *cbs, char indefinite, int expected_tag,
1147 need_eoc = indefinite; 1141 need_eoc = indefinite;
1148 1142
1149 while (CBS_len(cbs) > 0) { 1143 while (CBS_len(cbs) > 0) {
1150 if (asn1_check_eoc_cbs(cbs)) { 1144 if (asn1_check_eoc(cbs)) {
1151 if (!need_eoc) { 1145 if (!need_eoc) {
1152 ASN1error(ASN1_R_UNEXPECTED_EOC); 1146 ASN1error(ASN1_R_UNEXPECTED_EOC);
1153 return 0; 1147 return 0;
1154 } 1148 }
1155 return 1; 1149 return 1;
1156 } 1150 }
1157 if (!asn1_check_tag_cbs(cbs, &length, NULL, NULL, &indefinite, 1151 if (!asn1_check_tag(cbs, &length, NULL, NULL, &indefinite,
1158 &constructed, expected_tag, expected_class, 0)) { 1152 &constructed, expected_tag, expected_class, 0)) {
1159 ASN1error(ERR_R_NESTED_ASN1_ERROR); 1153 ASN1error(ERR_R_NESTED_ASN1_ERROR);
1160 return 0; 1154 return 0;
@@ -1184,7 +1178,7 @@ asn1_collect(CBB *cbb, CBS *cbs, char indefinite, int expected_tag,
1184} 1178}
1185 1179
1186static int 1180static int
1187asn1_check_eoc_cbs(CBS *cbs) 1181asn1_check_eoc(CBS *cbs)
1188{ 1182{
1189 uint16_t eoc; 1183 uint16_t eoc;
1190 1184
@@ -1197,22 +1191,7 @@ asn1_check_eoc_cbs(CBS *cbs)
1197} 1191}
1198 1192
1199static int 1193static int
1200asn1_check_eoc(const unsigned char **in, long len) 1194asn1_check_tag(CBS *cbs, size_t *out_len, int *out_tag, uint8_t *out_class,
1201{
1202 const unsigned char *p;
1203
1204 if (len < 2)
1205 return 0;
1206 p = *in;
1207 if (!p[0] && !p[1]) {
1208 *in += 2;
1209 return 1;
1210 }
1211 return 0;
1212}
1213
1214static int
1215asn1_check_tag_cbs(CBS *cbs, size_t *out_len, int *out_tag, uint8_t *out_class,
1216 char *out_indefinite, char *out_constructed, int expected_tag, 1195 char *out_indefinite, char *out_constructed, int expected_tag,
1217 int expected_class, char optional) 1196 int expected_class, char optional)
1218{ 1197{
@@ -1285,32 +1264,3 @@ asn1_check_tag_cbs(CBS *cbs, size_t *out_len, int *out_tag, uint8_t *out_class,
1285 1264
1286 return 1; 1265 return 1;
1287} 1266}
1288
1289static int
1290asn1_check_tag(long *out_len, int *out_tag, unsigned char *out_class,
1291 char *out_indefinite, char *out_constructed, const unsigned char **in,
1292 long len, int expected_tag, int expected_class, char optional)
1293{
1294 size_t length;
1295 CBS cbs;
1296 int ret;
1297
1298 if (len < 0)
1299 return 0;
1300
1301 CBS_init(&cbs, *in, len);
1302
1303 ret = asn1_check_tag_cbs(&cbs, &length, out_tag, out_class,
1304 out_indefinite, out_constructed, expected_tag, expected_class,
1305 optional);
1306
1307 if (length > LONG_MAX)
1308 return 0;
1309 if (out_len != NULL)
1310 *out_len = (long)length;
1311
1312 if (ret == 1)
1313 *in = CBS_data(&cbs);
1314
1315 return ret;
1316}