summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2022-03-26 14:54:58 +0000
committerjsing <>2022-03-26 14:54:58 +0000
commit33c81c3e0f1ee210c394320c35bce015fbf8e11e (patch)
tree13e45ed0ae5c37667b0c07f86645e65bf9b2c686 /src/lib
parentc6fe14d607c4444cd5cbc220cf8ca19aee4d8609 (diff)
downloadopenbsd-33c81c3e0f1ee210c394320c35bce015fbf8e11e.tar.gz
openbsd-33c81c3e0f1ee210c394320c35bce015fbf8e11e.tar.bz2
openbsd-33c81c3e0f1ee210c394320c35bce015fbf8e11e.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/lib')
-rw-r--r--src/lib/libcrypto/asn1/a_object.c173
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
522ASN1_OBJECT * 523int
523c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len) 524c2i_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
571ASN1_OBJECT *
572c2i_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
598int 600int
@@ -618,31 +620,40 @@ i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
618} 620}
619 621
620ASN1_OBJECT * 622ASN1_OBJECT *
621d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long length) 623d2i_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}