From: jsing Date: Wed, 19 Apr 2023 11:12:43 +0000 (+0000) Subject: Move the BN_bn2bin()/BN_bin2bn() family to bn_convert.c X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=8eccbb368d208aa917393e3dd3e328d77316c3e6;p=openbsd Move the BN_bn2bin()/BN_bin2bn() family to bn_convert.c --- diff --git a/lib/libcrypto/bn/bn_convert.c b/lib/libcrypto/bn/bn_convert.c index 6fe30fdbb9b..5df79fded6b 100644 --- a/lib/libcrypto/bn/bn_convert.c +++ b/lib/libcrypto/bn/bn_convert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_convert.c,v 1.4 2023/04/19 11:05:11 jsing Exp $ */ +/* $OpenBSD: bn_convert.c,v 1.5 2023/04/19 11:12:43 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -59,6 +59,7 @@ #include #include #include +#include #include @@ -70,6 +71,186 @@ static const char Hex[]="0123456789ABCDEF"; +typedef enum { + big, + little, +} endianness_t; + +/* ignore negative */ +static int +bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianness_t endianness) +{ + int n; + size_t i, lasti, j, atop, mask; + BN_ULONG l; + + /* + * In case |a| is fixed-top, BN_num_bytes can return bogus length, + * but it's assumed that fixed-top inputs ought to be "nominated" + * even for padded output, so it works out... + */ + n = BN_num_bytes(a); + if (tolen == -1) + tolen = n; + else if (tolen < n) { /* uncommon/unlike case */ + BIGNUM temp = *a; + + bn_correct_top(&temp); + + n = BN_num_bytes(&temp); + if (tolen < n) + return -1; + } + + /* Swipe through whole available data and don't give away padded zero. */ + atop = a->dmax * BN_BYTES; + if (atop == 0) { + explicit_bzero(to, tolen); + return tolen; + } + + lasti = atop - 1; + atop = a->top * BN_BYTES; + + if (endianness == big) + to += tolen; /* start from the end of the buffer */ + + for (i = 0, j = 0; j < (size_t)tolen; j++) { + unsigned char val; + + l = a->d[i / BN_BYTES]; + mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1)); + val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask); + + if (endianness == big) + *--to = val; + else + *to++ = val; + + i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */ + } + + return tolen; +} + +int +BN_bn2bin(const BIGNUM *a, unsigned char *to) +{ + return bn2binpad(a, to, -1, big); +} + +int +BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + if (tolen < 0) + return -1; + return bn2binpad(a, to, tolen, big); +} + +BIGNUM * +BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + unsigned int i, m; + unsigned int n; + BN_ULONG l; + BIGNUM *bn = NULL; + + if (len < 0) + return (NULL); + if (ret == NULL) + ret = bn = BN_new(); + if (ret == NULL) + return (NULL); + l = 0; + n = len; + if (n == 0) { + ret->top = 0; + return (ret); + } + i = ((n - 1) / BN_BYTES) + 1; + m = ((n - 1) % (BN_BYTES)); + if (!bn_wexpand(ret, (int)i)) { + BN_free(bn); + return NULL; + } + ret->top = i; + ret->neg = 0; + while (n--) { + l = (l << 8L) | *(s++); + if (m-- == 0) { + ret->d[--i] = l; + l = 0; + m = BN_BYTES - 1; + } + } + /* need to call this due to clear byte at top if avoiding + * having the top bit set (-ve number) */ + bn_correct_top(ret); + return (ret); +} + +int +BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + if (tolen < 0) + return -1; + + return bn2binpad(a, to, tolen, little); +} + +BIGNUM * +BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + unsigned int i, m, n; + BN_ULONG l; + BIGNUM *bn = NULL; + + if (ret == NULL) + ret = bn = BN_new(); + if (ret == NULL) + return NULL; + + + s += len; + /* Skip trailing zeroes. */ + for (; len > 0 && s[-1] == 0; s--, len--) + continue; + + n = len; + if (n == 0) { + ret->top = 0; + return ret; + } + + i = ((n - 1) / BN_BYTES) + 1; + m = (n - 1) % BN_BYTES; + if (!bn_wexpand(ret, (int)i)) { + BN_free(bn); + return NULL; + } + + ret->top = i; + ret->neg = 0; + l = 0; + while (n-- > 0) { + s--; + l = (l << 8L) | *s; + if (m-- == 0) { + ret->d[--i] = l; + l = 0; + m = BN_BYTES - 1; + } + } + + /* + * need to call this due to clear byte at top if avoiding having the + * top bit set (-ve number) + */ + bn_correct_top(ret); + + return ret; +} + int BN_asc2bn(BIGNUM **bn, const char *a) { diff --git a/lib/libcrypto/bn/bn_lib.c b/lib/libcrypto/bn/bn_lib.c index cd06563a5d2..78410e2133d 100644 --- a/lib/libcrypto/bn/bn_lib.c +++ b/lib/libcrypto/bn/bn_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_lib.c,v 1.83 2023/04/19 10:54:49 jsing Exp $ */ +/* $OpenBSD: bn_lib.c,v 1.84 2023/04/19 11:12:43 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -435,186 +435,6 @@ BN_set_word(BIGNUM *a, BN_ULONG w) return (1); } -BIGNUM * -BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) -{ - unsigned int i, m; - unsigned int n; - BN_ULONG l; - BIGNUM *bn = NULL; - - if (len < 0) - return (NULL); - if (ret == NULL) - ret = bn = BN_new(); - if (ret == NULL) - return (NULL); - l = 0; - n = len; - if (n == 0) { - ret->top = 0; - return (ret); - } - i = ((n - 1) / BN_BYTES) + 1; - m = ((n - 1) % (BN_BYTES)); - if (!bn_wexpand(ret, (int)i)) { - BN_free(bn); - return NULL; - } - ret->top = i; - ret->neg = 0; - while (n--) { - l = (l << 8L) | *(s++); - if (m-- == 0) { - ret->d[--i] = l; - l = 0; - m = BN_BYTES - 1; - } - } - /* need to call this due to clear byte at top if avoiding - * having the top bit set (-ve number) */ - bn_correct_top(ret); - return (ret); -} - -typedef enum { - big, - little, -} endianness_t; - -/* ignore negative */ -static int -bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianness_t endianness) -{ - int n; - size_t i, lasti, j, atop, mask; - BN_ULONG l; - - /* - * In case |a| is fixed-top, BN_num_bytes can return bogus length, - * but it's assumed that fixed-top inputs ought to be "nominated" - * even for padded output, so it works out... - */ - n = BN_num_bytes(a); - if (tolen == -1) - tolen = n; - else if (tolen < n) { /* uncommon/unlike case */ - BIGNUM temp = *a; - - bn_correct_top(&temp); - - n = BN_num_bytes(&temp); - if (tolen < n) - return -1; - } - - /* Swipe through whole available data and don't give away padded zero. */ - atop = a->dmax * BN_BYTES; - if (atop == 0) { - explicit_bzero(to, tolen); - return tolen; - } - - lasti = atop - 1; - atop = a->top * BN_BYTES; - - if (endianness == big) - to += tolen; /* start from the end of the buffer */ - - for (i = 0, j = 0; j < (size_t)tolen; j++) { - unsigned char val; - - l = a->d[i / BN_BYTES]; - mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1)); - val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask); - - if (endianness == big) - *--to = val; - else - *to++ = val; - - i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */ - } - - return tolen; -} - -int -BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) -{ - if (tolen < 0) - return -1; - return bn2binpad(a, to, tolen, big); -} - -int -BN_bn2bin(const BIGNUM *a, unsigned char *to) -{ - return bn2binpad(a, to, -1, big); -} - -BIGNUM * -BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret) -{ - unsigned int i, m, n; - BN_ULONG l; - BIGNUM *bn = NULL; - - if (ret == NULL) - ret = bn = BN_new(); - if (ret == NULL) - return NULL; - - - s += len; - /* Skip trailing zeroes. */ - for (; len > 0 && s[-1] == 0; s--, len--) - continue; - - n = len; - if (n == 0) { - ret->top = 0; - return ret; - } - - i = ((n - 1) / BN_BYTES) + 1; - m = (n - 1) % BN_BYTES; - if (!bn_wexpand(ret, (int)i)) { - BN_free(bn); - return NULL; - } - - ret->top = i; - ret->neg = 0; - l = 0; - while (n-- > 0) { - s--; - l = (l << 8L) | *s; - if (m-- == 0) { - ret->d[--i] = l; - l = 0; - m = BN_BYTES - 1; - } - } - - /* - * need to call this due to clear byte at top if avoiding having the - * top bit set (-ve number) - */ - bn_correct_top(ret); - - return ret; -} - -int -BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen) -{ - if (tolen < 0) - return -1; - - return bn2binpad(a, to, tolen, little); -} - int BN_ucmp(const BIGNUM *a, const BIGNUM *b) {