diff options
| author | jsing <> | 2022-03-26 14:54:58 +0000 |
|---|---|---|
| committer | jsing <> | 2022-03-26 14:54:58 +0000 |
| commit | 20c8d5e654c79295ab91cfcd49160d5d096494bd (patch) | |
| tree | 13e45ed0ae5c37667b0c07f86645e65bf9b2c686 /src | |
| parent | d10bc75275e54a97decc3a71a607af1535e2f2b3 (diff) | |
| download | openbsd-20c8d5e654c79295ab91cfcd49160d5d096494bd.tar.gz openbsd-20c8d5e654c79295ab91cfcd49160d5d096494bd.tar.bz2 openbsd-20c8d5e654c79295ab91cfcd49160d5d096494bd.zip | |
Convert c2i_ASN1_OBJECT() and d2i_ASN1_OBJECT to CBS.
Along the way, rather than having yet another piece of code that parses
OID arcs, reuse oid_parse_arc(). Always allocate a new ASN1_OBJECT rather
than doing a crazy dance with ASN1_OBJECT_FLAG_DYNAMIC and trying to free
parts of an ASN1_OBJECT if one is passed in.
ok inoguchi@ tb@
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/asn1/a_object.c | 173 |
1 files changed, 92 insertions, 81 deletions
diff --git a/src/lib/libcrypto/asn1/a_object.c b/src/lib/libcrypto/asn1/a_object.c index 1d94d49679..0cf649910b 100644 --- a/src/lib/libcrypto/asn1/a_object.c +++ b/src/lib/libcrypto/asn1/a_object.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: a_object.c,v 1.44 2022/03/20 13:27:23 jsing Exp $ */ | 1 | /* $OpenBSD: a_object.c,v 1.45 2022/03/26 14:54:58 jsing Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -155,12 +155,13 @@ oid_parse_arc(CBS *cbs, uint64_t *out_arc) | |||
| 155 | return 0; | 155 | return 0; |
| 156 | if (arc == 0 && val == 0x80) | 156 | if (arc == 0 && val == 0x80) |
| 157 | return 0; | 157 | return 0; |
| 158 | if (arc > (UINT64_MAX >> 7)) | 158 | if (out_arc != NULL && arc > (UINT64_MAX >> 7)) |
| 159 | return 0; | 159 | return 0; |
| 160 | arc = (arc << 7) | (val & 0x7f); | 160 | arc = (arc << 7) | (val & 0x7f); |
| 161 | } while (val & 0x80); | 161 | } while (val & 0x80); |
| 162 | 162 | ||
| 163 | *out_arc = arc; | 163 | if (out_arc != NULL) |
| 164 | *out_arc = arc; | ||
| 164 | 165 | ||
| 165 | return 1; | 166 | return 1; |
| 166 | } | 167 | } |
| @@ -519,80 +520,81 @@ i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *aobj) | |||
| 519 | return ret; | 520 | return ret; |
| 520 | } | 521 | } |
| 521 | 522 | ||
| 522 | ASN1_OBJECT * | 523 | int |
| 523 | c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len) | 524 | c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content) |
| 524 | { | 525 | { |
| 525 | ASN1_OBJECT *ret; | 526 | ASN1_OBJECT *aobj = NULL; |
| 526 | const unsigned char *p; | 527 | uint8_t *data = NULL; |
| 527 | unsigned char *data; | 528 | size_t data_len; |
| 528 | int i, length; | 529 | CBS cbs; |
| 529 | 530 | ||
| 530 | /* | 531 | if (out_aobj == NULL || *out_aobj != NULL) |
| 531 | * Sanity check OID encoding: | 532 | goto err; |
| 532 | * - need at least one content octet | 533 | |
| 533 | * - MSB must be clear in the last octet | 534 | /* Parse and validate OID encoding per X.690 8.19.2. */ |
| 534 | * - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2 | 535 | CBS_dup(content, &cbs); |
| 535 | */ | 536 | if (CBS_len(&cbs) == 0) { |
| 536 | if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || | ||
| 537 | p[len - 1] & 0x80) { | ||
| 538 | ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); | 537 | ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); |
| 539 | return (NULL); | 538 | goto err; |
| 540 | } | 539 | } |
| 541 | 540 | while (CBS_len(&cbs) > 0) { | |
| 542 | /* Now 0 < len <= INT_MAX, so the cast is safe. */ | 541 | if (!oid_parse_arc(&cbs, NULL)) { |
| 543 | length = (int)len; | ||
| 544 | for (i = 0; i < length; i++, p++) { | ||
| 545 | if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { | ||
| 546 | ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); | 542 | ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); |
| 547 | return (NULL); | 543 | goto err; |
| 548 | } | 544 | } |
| 549 | } | 545 | } |
| 550 | 546 | ||
| 551 | if ((a == NULL) || ((*a) == NULL) || | 547 | if (!CBS_stow(content, &data, &data_len)) |
| 552 | !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { | 548 | goto err; |
| 553 | if ((ret = ASN1_OBJECT_new()) == NULL) | ||
| 554 | return (NULL); | ||
| 555 | } else | ||
| 556 | ret = *a; | ||
| 557 | |||
| 558 | p = *pp; | ||
| 559 | 549 | ||
| 560 | /* detach data from object */ | 550 | if (data_len > INT_MAX) |
| 561 | data = (unsigned char *)ret->data; | 551 | goto err; |
| 562 | freezero(data, ret->length); | ||
| 563 | 552 | ||
| 564 | data = malloc(length); | 553 | if ((aobj = ASN1_OBJECT_new()) == NULL) |
| 565 | if (data == NULL) { | ||
| 566 | ASN1error(ERR_R_MALLOC_FAILURE); | ||
| 567 | goto err; | 554 | goto err; |
| 568 | } | ||
| 569 | 555 | ||
| 570 | memcpy(data, p, length); | 556 | aobj->data = data; |
| 557 | aobj->length = (int)data_len; /* XXX - change length to size_t. */ | ||
| 558 | aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; | ||
| 559 | |||
| 560 | *out_aobj = aobj; | ||
| 571 | 561 | ||
| 572 | /* If there are dynamic strings, free them here, and clear the flag. */ | 562 | return 1; |
| 573 | if ((ret->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) != 0) { | 563 | |
| 574 | free((void *)ret->sn); | 564 | err: |
| 575 | free((void *)ret->ln); | 565 | ASN1_OBJECT_free(aobj); |
| 576 | ret->flags &= ~ASN1_OBJECT_FLAG_DYNAMIC_STRINGS; | 566 | free(data); |
| 567 | |||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | ASN1_OBJECT * | ||
| 572 | c2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long len) | ||
| 573 | { | ||
| 574 | ASN1_OBJECT *aobj = NULL; | ||
| 575 | CBS content; | ||
| 576 | |||
| 577 | if (out_aobj != NULL) { | ||
| 578 | ASN1_OBJECT_free(*out_aobj); | ||
| 579 | *out_aobj = NULL; | ||
| 577 | } | 580 | } |
| 578 | 581 | ||
| 579 | /* reattach data to object, after which it remains const */ | 582 | if (len < 0) { |
| 580 | ret->data = data; | 583 | ASN1error(ASN1_R_LENGTH_ERROR); |
| 581 | ret->length = length; | 584 | return NULL; |
| 582 | ret->sn = NULL; | 585 | } |
| 583 | ret->ln = NULL; | ||
| 584 | ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; | ||
| 585 | p += length; | ||
| 586 | 586 | ||
| 587 | if (a != NULL) | 587 | CBS_init(&content, *pp, len); |
| 588 | *a = ret; | ||
| 589 | *pp = p; | ||
| 590 | return (ret); | ||
| 591 | 588 | ||
| 592 | err: | 589 | if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) |
| 593 | if (a == NULL || ret != *a) | 590 | return NULL; |
| 594 | ASN1_OBJECT_free(ret); | 591 | |
| 595 | return (NULL); | 592 | *pp = CBS_data(&content); |
| 593 | |||
| 594 | if (out_aobj != NULL) | ||
| 595 | *out_aobj = aobj; | ||
| 596 | |||
| 597 | return aobj; | ||
| 596 | } | 598 | } |
| 597 | 599 | ||
| 598 | int | 600 | int |
| @@ -618,31 +620,40 @@ i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) | |||
| 618 | } | 620 | } |
| 619 | 621 | ||
| 620 | ASN1_OBJECT * | 622 | ASN1_OBJECT * |
| 621 | d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long length) | 623 | d2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long length) |
| 622 | { | 624 | { |
| 623 | const unsigned char *p; | 625 | ASN1_OBJECT *aobj = NULL; |
| 624 | long len; | 626 | uint32_t tag_number; |
| 625 | int tag, xclass; | 627 | CBS cbs, content; |
| 626 | int inf, i; | ||
| 627 | ASN1_OBJECT *ret = NULL; | ||
| 628 | 628 | ||
| 629 | p = *pp; | 629 | if (out_aobj != NULL) { |
| 630 | inf = ASN1_get_object(&p, &len, &tag, &xclass, length); | 630 | ASN1_OBJECT_free(*out_aobj); |
| 631 | if (inf & 0x80) { | 631 | *out_aobj = NULL; |
| 632 | i = ASN1_R_BAD_OBJECT_HEADER; | ||
| 633 | goto err; | ||
| 634 | } | 632 | } |
| 635 | 633 | ||
| 636 | if (tag != V_ASN1_OBJECT) { | 634 | if (length < 0) { |
| 637 | i = ASN1_R_EXPECTING_AN_OBJECT; | 635 | ASN1error(ASN1_R_LENGTH_ERROR); |
| 638 | goto err; | 636 | return NULL; |
| 639 | } | 637 | } |
| 640 | ret = c2i_ASN1_OBJECT(a, &p, len); | ||
| 641 | if (ret) | ||
| 642 | *pp = p; | ||
| 643 | return ret; | ||
| 644 | 638 | ||
| 645 | err: | 639 | CBS_init(&cbs, *pp, length); |
| 646 | ASN1error(i); | 640 | |
| 647 | return (NULL); | 641 | if (!asn1_get_primitive(&cbs, 0, &tag_number, &content)) { |
| 642 | ASN1error(ASN1_R_BAD_OBJECT_HEADER); | ||
| 643 | return NULL; | ||
| 644 | } | ||
| 645 | if (tag_number != V_ASN1_OBJECT) { | ||
| 646 | ASN1error(ASN1_R_EXPECTING_AN_OBJECT); | ||
| 647 | return NULL; | ||
| 648 | } | ||
| 649 | |||
| 650 | if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) | ||
| 651 | return NULL; | ||
| 652 | |||
| 653 | *pp = CBS_data(&content); | ||
| 654 | |||
| 655 | if (out_aobj != NULL) | ||
| 656 | *out_aobj = aobj; | ||
| 657 | |||
| 658 | return aobj; | ||
| 648 | } | 659 | } |
