summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/asn1/a_int.c197
1 files changed, 100 insertions, 97 deletions
diff --git a/src/lib/libcrypto/asn1/a_int.c b/src/lib/libcrypto/asn1/a_int.c
index d7790c787d..6a24c5183c 100644
--- a/src/lib/libcrypto/asn1/a_int.c
+++ b/src/lib/libcrypto/asn1/a_int.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: a_int.c,v 1.44 2022/07/13 20:07:44 jsing Exp $ */ 1/* $OpenBSD: a_int.c,v 1.45 2022/08/20 18:17:33 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 *
@@ -510,100 +510,6 @@ a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
510 return (ret); 510 return (ret);
511} 511}
512 512
513/*
514 * This converts an ASN1 INTEGER into its content encoding.
515 * The internal representation is an ASN1_STRING whose data is a big endian
516 * representation of the value, ignoring the sign. The sign is determined by
517 * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
518 *
519 * Positive integers are no problem: they are almost the same as the DER
520 * encoding, except if the first byte is >= 0x80 we need to add a zero pad.
521 *
522 * Negative integers are a bit trickier...
523 * The DER representation of negative integers is in 2s complement form.
524 * The internal form is converted by complementing each octet and finally
525 * adding one to the result. This can be done less messily with a little trick.
526 * If the internal form has trailing zeroes then they will become FF by the
527 * complement and 0 by the add one (due to carry) so just copy as many trailing
528 * zeros to the destination as there are in the source. The carry will add one
529 * to the last none zero octet: so complement this octet and add one and finally
530 * complement any left over until you get to the start of the string.
531 *
532 * Padding is a little trickier too. If the first bytes is > 0x80 then we pad
533 * with 0xff. However if the first byte is 0x80 and one of the following bytes
534 * is non-zero we pad with 0xff. The reason for this distinction is that 0x80
535 * followed by optional zeros isn't padded.
536 */
537
538int
539i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
540{
541 int pad = 0, ret, i, neg;
542 unsigned char *p, *n, pb = 0;
543
544 if (!ASN1_INTEGER_valid(a))
545 return 0;
546
547 neg = a->type & V_ASN1_NEG;
548 if (a->length == 0)
549 ret = 1;
550 else {
551 ret = a->length;
552 i = a->data[0];
553 if (!neg && (i > 127)) {
554 pad = 1;
555 pb = 0;
556 } else if (neg) {
557 if (i > 128) {
558 pad = 1;
559 pb = 0xFF;
560 } else if (i == 128) {
561 /*
562 * Special case: if any other bytes non zero we pad:
563 * otherwise we don't.
564 */
565 for (i = 1; i < a->length; i++) if (a->data[i]) {
566 pad = 1;
567 pb = 0xFF;
568 break;
569 }
570 }
571 }
572 ret += pad;
573 }
574 if (pp == NULL)
575 return (ret);
576 p= *pp;
577
578 if (pad)
579 *(p++) = pb;
580 if (a->length == 0)
581 *(p++) = 0;
582 else if (!neg)
583 memcpy(p, a->data, a->length);
584 else {
585 /* Begin at the end of the encoding */
586 n = a->data + a->length - 1;
587 p += a->length - 1;
588 i = a->length;
589 /* Copy zeros to destination as long as source is zero */
590 while (!*n) {
591 *(p--) = 0;
592 n--;
593 i--;
594 }
595 /* Complement and increment next octet */
596 *(p--) = ((*(n--)) ^ 0xff) + 1;
597 i--;
598 /* Complement any octets left */
599 for (; i > 0; i--)
600 *(p--) = *(n--) ^ 0xff;
601 }
602
603 *pp += ret;
604 return (ret);
605}
606
607static void 513static void
608asn1_aint_twos_complement(uint8_t *data, size_t data_len) 514asn1_aint_twos_complement(uint8_t *data, size_t data_len)
609{ 515{
@@ -637,6 +543,103 @@ asn1_aint_keep_twos_padding(const uint8_t *data, size_t data_len)
637 return 1; 543 return 1;
638} 544}
639 545
546static int
547i2c_ASN1_INTEGER_cbb(ASN1_INTEGER *aint, CBB *cbb)
548{
549 uint8_t *data = NULL;
550 size_t data_len = 0;
551 uint8_t padding, val;
552 uint8_t msb;
553 CBS cbs;
554 int ret = 0;
555
556 if (aint->data == NULL || aint->length < 0)
557 goto err;
558
559 if ((aint->type & ~V_ASN1_NEG) != V_ASN1_ENUMERATED &&
560 (aint->type & ~V_ASN1_NEG) != V_ASN1_INTEGER)
561 goto err;
562
563 CBS_init(&cbs, aint->data, aint->length);
564
565 /* Find the first non-zero byte. */
566 while (CBS_len(&cbs) > 0) {
567 if (!CBS_peek_u8(&cbs, &val))
568 goto err;
569 if (val != 0)
570 break;
571 if (!CBS_skip(&cbs, 1))
572 goto err;
573 }
574
575 /* A zero value is encoded as a single octet. */
576 if (CBS_len(&cbs) == 0) {
577 if (!CBB_add_u8(cbb, 0))
578 goto err;
579 goto done;
580 }
581
582 if (!CBS_stow(&cbs, &data, &data_len))
583 goto err;
584
585 if ((aint->type & V_ASN1_NEG) != 0)
586 asn1_aint_twos_complement(data, data_len);
587
588 /* Topmost bit indicates sign, padding is all zeros or all ones. */
589 msb = (data[0] >> 7);
590 padding = (msb - 1) & 0xff;
591
592 /* See if we need a padding octet to avoid incorrect sign. */
593 if (((aint->type & V_ASN1_NEG) == 0 && msb == 1) ||
594 ((aint->type & V_ASN1_NEG) != 0 && msb == 0)) {
595 if (!CBB_add_u8(cbb, padding))
596 goto err;
597 }
598 if (!CBB_add_bytes(cbb, data, data_len))
599 goto err;
600
601 done:
602 ret = 1;
603
604 err:
605 freezero(data, data_len);
606
607 return ret;
608}
609
610int
611i2c_ASN1_INTEGER(ASN1_INTEGER *aint, unsigned char **pp)
612{
613 uint8_t *data = NULL;
614 size_t data_len = 0;
615 CBB cbb;
616 int ret = -3;
617
618 if (!CBB_init(&cbb, 0))
619 goto err;
620 if (!i2c_ASN1_INTEGER_cbb(aint, &cbb))
621 goto err;
622 if (!CBB_finish(&cbb, &data, &data_len))
623 goto err;
624 if (data_len > INT_MAX)
625 goto err;
626
627 if (pp != NULL) {
628 if ((uintptr_t)*pp > UINTPTR_MAX - data_len)
629 goto err;
630 memcpy(*pp, data, data_len);
631 *pp += data_len;
632 }
633
634 ret = data_len;
635
636 err:
637 freezero(data, data_len);
638 CBB_cleanup(&cbb);
639
640 return ret;
641}
642
640int 643int
641c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs) 644c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs)
642{ 645{
@@ -644,7 +647,7 @@ c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs)
644 uint8_t *data = NULL; 647 uint8_t *data = NULL;
645 size_t data_len = 0; 648 size_t data_len = 0;
646 uint8_t padding, val; 649 uint8_t padding, val;
647 uint8_t negative = 0; 650 uint8_t negative;
648 int ret = 0; 651 int ret = 0;
649 652
650 if (out_aint == NULL) 653 if (out_aint == NULL)
@@ -663,7 +666,7 @@ c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs)
663 if (!CBS_peek_u8(cbs, &val)) 666 if (!CBS_peek_u8(cbs, &val))
664 goto err; 667 goto err;
665 668
666 /* Top most bit indicates sign, padding is all zeros or all ones. */ 669 /* Topmost bit indicates sign, padding is all zeros or all ones. */
667 negative = (val >> 7); 670 negative = (val >> 7);
668 padding = ~(negative - 1) & 0xff; 671 padding = ~(negative - 1) & 0xff;
669 672