summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2021-09-08 12:19:17 +0000
committertb <>2021-09-08 12:19:17 +0000
commitae0785bbe06a3bd6d1b155469685f3f19dd4c7e9 (patch)
tree6d7415ed4fa4fbe8aba04ef7c33529aa84e5361e
parent5ef15c706587fade4c981dda1523f9c5344a2cb0 (diff)
downloadopenbsd-ae0785bbe06a3bd6d1b155469685f3f19dd4c7e9.tar.gz
openbsd-ae0785bbe06a3bd6d1b155469685f3f19dd4c7e9.tar.bz2
openbsd-ae0785bbe06a3bd6d1b155469685f3f19dd4c7e9.zip
Prepare to provide BN_bn2{,le}binpad() and BN_lebin2bn()
As found by jsg and patrick, this is needed for newer uboot and will also be used in upcoming elliptic curve work. This is from OpenSSL 1.1.1l with minor style tweaks. ok beck inoguchi
-rw-r--r--src/lib/libcrypto/bn/bn.h7
-rw-r--r--src/lib/libcrypto/bn/bn_lib.c139
2 files changed, 137 insertions, 9 deletions
diff --git a/src/lib/libcrypto/bn/bn.h b/src/lib/libcrypto/bn/bn.h
index cc1f467523..f03b2c7be7 100644
--- a/src/lib/libcrypto/bn/bn.h
+++ b/src/lib/libcrypto/bn/bn.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn.h,v 1.39 2019/08/25 19:23:59 schwarze Exp $ */ 1/* $OpenBSD: bn.h,v 1.40 2021/09/08 12:19:17 tb Exp $ */
2/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -428,6 +428,11 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
428void BN_swap(BIGNUM *a, BIGNUM *b); 428void BN_swap(BIGNUM *a, BIGNUM *b);
429BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); 429BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
430int BN_bn2bin(const BIGNUM *a, unsigned char *to); 430int BN_bn2bin(const BIGNUM *a, unsigned char *to);
431#if defined(LIBRESSL_INTERNAL)
432int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen);
433BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret);
434int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen);
435#endif
431BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret); 436BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret);
432int BN_bn2mpi(const BIGNUM *a, unsigned char *to); 437int BN_bn2mpi(const BIGNUM *a, unsigned char *to);
433int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); 438int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
diff --git a/src/lib/libcrypto/bn/bn_lib.c b/src/lib/libcrypto/bn/bn_lib.c
index 1a91b9e60c..af837eed01 100644
--- a/src/lib/libcrypto/bn/bn_lib.c
+++ b/src/lib/libcrypto/bn/bn_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_lib.c,v 1.47 2019/06/17 17:11:48 tb Exp $ */ 1/* $OpenBSD: bn_lib.c,v 1.48 2021/09/08 12:19:17 tb 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 *
@@ -583,20 +583,143 @@ BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
583 return (ret); 583 return (ret);
584} 584}
585 585
586typedef enum {
587 big,
588 little,
589} endianness_t;
590
586/* ignore negative */ 591/* ignore negative */
592static int
593bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianness_t endianness)
594{
595 int n;
596 size_t i, lasti, j, atop, mask;
597 BN_ULONG l;
598
599 /*
600 * In case |a| is fixed-top, BN_num_bytes can return bogus length,
601 * but it's assumed that fixed-top inputs ought to be "nominated"
602 * even for padded output, so it works out...
603 */
604 n = BN_num_bytes(a);
605 if (tolen == -1)
606 tolen = n;
607 else if (tolen < n) { /* uncommon/unlike case */
608 BIGNUM temp = *a;
609
610 bn_correct_top(&temp);
611
612 n = BN_num_bytes(&temp);
613 if (tolen < n)
614 return -1;
615 }
616
617 /* Swipe through whole available data and don't give away padded zero. */
618 atop = a->dmax * BN_BYTES;
619 if (atop == 0) {
620 explicit_bzero(to, tolen);
621 return tolen;
622 }
623
624 lasti = atop - 1;
625 atop = a->top * BN_BYTES;
626
627 if (endianness == big)
628 to += tolen; /* start from the end of the buffer */
629
630 for (i = 0, j = 0; j < (size_t)tolen; j++) {
631 unsigned char val;
632
633 l = a->d[i / BN_BYTES];
634 mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
635 val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
636
637 if (endianness == big)
638 *--to = val;
639 else
640 *to++ = val;
641
642 i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
643 }
644
645 return tolen;
646}
647
648int
649BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
650{
651 if (tolen < 0)
652 return -1;
653 return bn2binpad(a, to, tolen, big);
654}
655
587int 656int
588BN_bn2bin(const BIGNUM *a, unsigned char *to) 657BN_bn2bin(const BIGNUM *a, unsigned char *to)
589{ 658{
590 int n, i; 659 return bn2binpad(a, to, -1, big);
660}
661
662BIGNUM *
663BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
664{
665 unsigned int i, m, n;
591 BN_ULONG l; 666 BN_ULONG l;
667 BIGNUM *bn = NULL;
592 668
593 bn_check_top(a); 669 if (ret == NULL)
594 n = i=BN_num_bytes(a); 670 ret = bn = BN_new();
595 while (i--) { 671 if (ret == NULL)
596 l = a->d[i / BN_BYTES]; 672 return NULL;
597 *(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; 673
674 bn_check_top(ret);
675
676 s += len;
677 /* Skip trailing zeroes. */
678 for (; len > 0 && s[-1] == 0; s--, len--)
679 continue;
680
681 n = len;
682 if (n == 0) {
683 ret->top = 0;
684 return ret;
598 } 685 }
599 return (n); 686
687 i = ((n - 1) / BN_BYTES) + 1;
688 m = (n - 1) % BN_BYTES;
689 if (bn_wexpand(ret, (int)i) == NULL) {
690 BN_free(bn);
691 return NULL;
692 }
693
694 ret->top = i;
695 ret->neg = 0;
696 l = 0;
697 while (n-- > 0) {
698 s--;
699 l = (l << 8L) | *s;
700 if (m-- == 0) {
701 ret->d[--i] = l;
702 l = 0;
703 m = BN_BYTES - 1;
704 }
705 }
706
707 /*
708 * need to call this due to clear byte at top if avoiding having the
709 * top bit set (-ve number)
710 */
711 bn_correct_top(ret);
712
713 return ret;
714}
715
716int
717BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
718{
719 if (tolen < 0)
720 return -1;
721
722 return bn2binpad(a, to, tolen, little);
600} 723}
601 724
602int 725int