diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 183 |
1 files changed, 125 insertions, 58 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index de0b819064..f3e032c1c1 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.62 2022/05/10 05:19:22 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.63 2022/05/10 18:40:06 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,13 +83,16 @@ static int asn1_collect(CBB *cbb, CBS *cbs, char indefinite, int expected_tag, | |||
83 | int expected_class, int depth); | 83 | int expected_class, int depth); |
84 | 84 | ||
85 | static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, | 85 | static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, |
86 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt, int depth); | 86 | long len, const ASN1_ITEM *it, int tag_number, int tag_class, char optional, |
87 | int depth); | ||
88 | static int asn1_template_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, | ||
89 | const ASN1_TEMPLATE *tt, char optional, int depth); | ||
87 | 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, |
88 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); | 91 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); |
89 | 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, |
90 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); | 93 | long len, const ASN1_TEMPLATE *tt, char opt, int depth); |
91 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, | 94 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, |
92 | long len, const ASN1_ITEM *it, int tag, int aclass, char opt); | 95 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional); |
93 | 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, |
94 | const ASN1_ITEM *it); | 97 | const ASN1_ITEM *it); |
95 | 98 | ||
@@ -218,6 +221,26 @@ asn1_item_ex_d2i_choice(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
218 | } | 221 | } |
219 | 222 | ||
220 | static int | 223 | static int |
224 | asn1_item_ex_d2i_choice_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | ||
225 | int tag_number, int tag_class, char optional, int depth) | ||
226 | { | ||
227 | const unsigned char *p; | ||
228 | int ret; | ||
229 | |||
230 | if (CBS_len(cbs) > LONG_MAX) | ||
231 | return 0; | ||
232 | |||
233 | p = CBS_data(cbs); | ||
234 | ret = asn1_item_ex_d2i_choice(pval, &p, (long)CBS_len(cbs), it, | ||
235 | tag_number, tag_class, optional, depth); | ||
236 | if (ret == 1) { | ||
237 | if (!CBS_skip(cbs, p - CBS_data(cbs))) | ||
238 | return 0; | ||
239 | } | ||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | static int | ||
221 | asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, const unsigned char **in, long len, | 244 | asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, const unsigned char **in, long len, |
222 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) | 245 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) |
223 | { | 246 | { |
@@ -390,22 +413,43 @@ asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
390 | return 0; | 413 | return 0; |
391 | } | 414 | } |
392 | 415 | ||
416 | static int | ||
417 | asn1_item_ex_d2i_sequence_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | ||
418 | int tag_number, int tag_class, char optional, int depth) | ||
419 | { | ||
420 | const unsigned char *p; | ||
421 | int ret; | ||
422 | |||
423 | if (CBS_len(cbs) > LONG_MAX) | ||
424 | return 0; | ||
425 | |||
426 | p = CBS_data(cbs); | ||
427 | ret = asn1_item_ex_d2i_sequence(pval, &p, (long)CBS_len(cbs), it, | ||
428 | tag_number, tag_class, optional, depth); | ||
429 | if (ret == 1) { | ||
430 | if (!CBS_skip(cbs, p - CBS_data(cbs))) | ||
431 | return 0; | ||
432 | } | ||
433 | return ret; | ||
434 | } | ||
435 | |||
393 | /* | 436 | /* |
394 | * Decode an item, taking care of IMPLICIT tagging, if any. | 437 | * Decode an item, taking care of IMPLICIT tagging, if any. |
395 | * If 'opt' set and tag mismatch return -1 to handle OPTIONAL | 438 | * If 'opt' set and tag mismatch return -1 to handle OPTIONAL |
396 | */ | 439 | */ |
397 | static int | 440 | static int |
398 | asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 441 | asn1_item_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, |
399 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) | 442 | int tag_number, int tag_class, char optional, int depth) |
400 | { | 443 | { |
401 | const ASN1_EXTERN_FUNCS *ef; | 444 | const ASN1_EXTERN_FUNCS *ef = it->funcs; |
402 | ASN1_TLC ctx = { 0 }; | ||
403 | const unsigned char *p = NULL; | 445 | const unsigned char *p = NULL; |
446 | ASN1_TLC ctx = { 0 }; | ||
447 | CBS cbs_mstring; | ||
404 | unsigned char oclass; | 448 | unsigned char oclass; |
405 | int otag; | 449 | int otag; |
406 | int ret = 0; | 450 | int ret = 0; |
407 | 451 | ||
408 | if (!pval) | 452 | if (pval == NULL) |
409 | return 0; | 453 | return 0; |
410 | 454 | ||
411 | if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { | 455 | if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { |
@@ -415,23 +459,23 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
415 | 459 | ||
416 | switch (it->itype) { | 460 | switch (it->itype) { |
417 | case ASN1_ITYPE_PRIMITIVE: | 461 | case ASN1_ITYPE_PRIMITIVE: |
418 | if (it->templates) { | 462 | if (it->templates != NULL) { |
419 | /* tagging or OPTIONAL is currently illegal on an item | 463 | /* |
464 | * Tagging or OPTIONAL is currently illegal on an item | ||
420 | * template because the flags can't get passed down. | 465 | * template because the flags can't get passed down. |
421 | * In practice this isn't a problem: we include the | 466 | * In practice this isn't a problem: we include the |
422 | * relevant flags from the item template in the | 467 | * relevant flags from the item template in the |
423 | * template itself. | 468 | * template itself. |
424 | */ | 469 | */ |
425 | if ((tag != -1) || opt) { | 470 | if (tag_number != -1 || optional) { |
426 | ASN1error(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); | 471 | ASN1error(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); |
427 | goto err; | 472 | goto err; |
428 | } | 473 | } |
429 | return asn1_template_ex_d2i(pval, in, len, | 474 | return asn1_template_ex_d2i_cbs(pval, cbs, |
430 | it->templates, opt, depth); | 475 | it->templates, optional, depth); |
431 | } | 476 | } |
432 | return asn1_d2i_ex_primitive(pval, in, len, it, | 477 | return asn1_d2i_ex_primitive(pval, cbs, it, tag_number, |
433 | tag, aclass, opt); | 478 | tag_class, optional); |
434 | break; | ||
435 | 479 | ||
436 | case ASN1_ITYPE_MSTRING: | 480 | case ASN1_ITYPE_MSTRING: |
437 | /* | 481 | /* |
@@ -439,52 +483,54 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
439 | * tagging, so if tag != -1, then this looks like an error in | 483 | * tagging, so if tag != -1, then this looks like an error in |
440 | * the template. | 484 | * the template. |
441 | */ | 485 | */ |
442 | if (tag != -1) { | 486 | if (tag_number != -1) { |
443 | ASN1error(ASN1_R_BAD_TEMPLATE); | 487 | ASN1error(ASN1_R_BAD_TEMPLATE); |
444 | goto err; | 488 | goto err; |
445 | } | 489 | } |
446 | 490 | ||
447 | p = *in; | 491 | /* XXX - avoid reading the header twice for MSTRING. */ |
448 | /* Just read in tag and class */ | 492 | CBS_dup(cbs, &cbs_mstring); |
449 | ret = asn1_check_tag(NULL, &otag, &oclass, NULL, NULL, &p, len, | 493 | if (asn1_check_tag_cbs(&cbs_mstring, NULL, &otag, &oclass, |
450 | -1, 0, 1); | 494 | NULL, NULL, -1, 0, 1) != 1) { |
451 | if (!ret) { | ||
452 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 495 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
453 | goto err; | 496 | goto err; |
454 | } | 497 | } |
455 | 498 | ||
456 | /* Must be UNIVERSAL class */ | 499 | /* Must be UNIVERSAL class */ |
457 | if (oclass != V_ASN1_UNIVERSAL) { | 500 | if (oclass != V_ASN1_UNIVERSAL) { |
458 | /* If OPTIONAL, assume this is OK */ | 501 | if (optional) |
459 | if (opt) | ||
460 | return -1; | 502 | return -1; |
461 | ASN1error(ASN1_R_MSTRING_NOT_UNIVERSAL); | 503 | ASN1error(ASN1_R_MSTRING_NOT_UNIVERSAL); |
462 | goto err; | 504 | goto err; |
463 | } | 505 | } |
464 | /* Check tag matches bit map */ | 506 | /* Check tag matches bit map */ |
465 | if (!(ASN1_tag2bit(otag) & it->utype)) { | 507 | if (!(ASN1_tag2bit(otag) & it->utype)) { |
466 | /* If OPTIONAL, assume this is OK */ | 508 | if (optional) |
467 | if (opt) | ||
468 | return -1; | 509 | return -1; |
469 | ASN1error(ASN1_R_MSTRING_WRONG_TAG); | 510 | ASN1error(ASN1_R_MSTRING_WRONG_TAG); |
470 | goto err; | 511 | goto err; |
471 | } | 512 | } |
472 | return asn1_d2i_ex_primitive(pval, in, len, | 513 | return asn1_d2i_ex_primitive(pval, cbs, it, otag, 0, 0); |
473 | it, otag, 0, 0); | ||
474 | 514 | ||
475 | case ASN1_ITYPE_EXTERN: | 515 | case ASN1_ITYPE_EXTERN: |
476 | /* Use new style d2i */ | 516 | if (CBS_len(cbs) > LONG_MAX) |
477 | ef = it->funcs; | 517 | return 0; |
478 | return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, &ctx); | 518 | p = CBS_data(cbs); |
519 | if ((ret = ef->asn1_ex_d2i(pval, &p, (long)CBS_len(cbs), it, | ||
520 | tag_number, tag_class, optional, &ctx)) == 1) { | ||
521 | if (!CBS_skip(cbs, p - CBS_data(cbs))) | ||
522 | goto err; | ||
523 | } | ||
524 | return ret; | ||
479 | 525 | ||
480 | case ASN1_ITYPE_CHOICE: | 526 | case ASN1_ITYPE_CHOICE: |
481 | return asn1_item_ex_d2i_choice(pval, in, len, it, tag, | 527 | return asn1_item_ex_d2i_choice_cbs(pval, cbs, it, tag_number, |
482 | aclass, opt, depth); | 528 | tag_class, optional, depth); |
483 | 529 | ||
484 | case ASN1_ITYPE_NDEF_SEQUENCE: | 530 | case ASN1_ITYPE_NDEF_SEQUENCE: |
485 | case ASN1_ITYPE_SEQUENCE: | 531 | case ASN1_ITYPE_SEQUENCE: |
486 | return asn1_item_ex_d2i_sequence(pval, in, len, it, tag, | 532 | return asn1_item_ex_d2i_sequence_cbs(pval, cbs, it, tag_number, |
487 | aclass, opt, depth); | 533 | tag_class, optional, depth); |
488 | 534 | ||
489 | default: | 535 | default: |
490 | return 0; | 536 | return 0; |
@@ -498,6 +544,28 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
498 | return 0; | 544 | return 0; |
499 | } | 545 | } |
500 | 546 | ||
547 | static int | ||
548 | asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen, | ||
549 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional, | ||
550 | int depth) | ||
551 | { | ||
552 | CBS cbs; | ||
553 | int ret; | ||
554 | |||
555 | if (inlen < 0) | ||
556 | return 0; | ||
557 | |||
558 | CBS_init(&cbs, *in, inlen); | ||
559 | |||
560 | ret = asn1_item_ex_d2i_cbs(pval, &cbs, it, tag_number, tag_class, | ||
561 | optional, depth); | ||
562 | |||
563 | if (ret == 1) | ||
564 | *in = CBS_data(&cbs); | ||
565 | |||
566 | return ret; | ||
567 | } | ||
568 | |||
501 | int | 569 | int |
502 | ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 570 | ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
503 | const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) | 571 | const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) |
@@ -579,6 +647,26 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, | |||
579 | } | 647 | } |
580 | 648 | ||
581 | static int | 649 | static int |
650 | asn1_template_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt, | ||
651 | char optional, int depth) | ||
652 | { | ||
653 | const unsigned char *p; | ||
654 | int ret; | ||
655 | |||
656 | if (CBS_len(cbs) > LONG_MAX) | ||
657 | return 0; | ||
658 | |||
659 | p = CBS_data(cbs); | ||
660 | ret = asn1_template_ex_d2i(pval, &p, (long)CBS_len(cbs), tt, | ||
661 | optional, depth); | ||
662 | if (ret == 1) { | ||
663 | if (!CBS_skip(cbs, p - CBS_data(cbs))) | ||
664 | return 0; | ||
665 | } | ||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | static int | ||
582 | asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | 670 | asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, |
583 | const ASN1_TEMPLATE *tt, char opt, int depth) | 671 | const ASN1_TEMPLATE *tt, char opt, int depth) |
584 | { | 672 | { |
@@ -696,7 +784,7 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, | |||
696 | } | 784 | } |
697 | 785 | ||
698 | static int | 786 | static int |
699 | asn1_d2i_ex_primitive_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | 787 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, |
700 | int tag_number, int tag_class, char optional) | 788 | int tag_number, int tag_class, char optional) |
701 | { | 789 | { |
702 | CBS cbs_any, cbs_content, cbs_object, cbs_initial; | 790 | CBS cbs_any, cbs_content, cbs_object, cbs_initial; |
@@ -816,27 +904,6 @@ asn1_d2i_ex_primitive_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | |||
816 | } | 904 | } |
817 | 905 | ||
818 | static int | 906 | static int |
819 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, | ||
820 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional) | ||
821 | { | ||
822 | CBS cbs; | ||
823 | int ret; | ||
824 | |||
825 | if (inlen < 0) | ||
826 | return 0; | ||
827 | |||
828 | CBS_init(&cbs, *in, inlen); | ||
829 | |||
830 | ret = asn1_d2i_ex_primitive_cbs(pval, &cbs, it, tag_number, tag_class, | ||
831 | optional); | ||
832 | |||
833 | if (ret == 1) | ||
834 | *in = CBS_data(&cbs); | ||
835 | |||
836 | return ret; | ||
837 | } | ||
838 | |||
839 | static int | ||
840 | asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | 907 | asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) |
841 | { | 908 | { |
842 | ASN1_STRING *stmp; | 909 | ASN1_STRING *stmp; |