diff options
author | Rich Salz <rsalz@openssl.org> | 2016-09-05 18:08:43 -0400 |
---|---|---|
committer | Rich Salz <rsalz@openssl.org> | 2016-09-06 10:42:28 -0400 |
commit | e9590d00fc7c269f3e90b93cf6ac17238f0ca2c6 (patch) | |
tree | b437dc4c773addf2fc7cb391ee80b3ed452e98f2 /crypto/bn | |
parent | f52d16ac1d0f0bc3a13e32cc62dcbd4fed4ac649 (diff) |
Misc BN fixes
Never output -0; make "negative zero" an impossibility.
Do better checking on BN_rand top/bottom requirements and #bits.
Update doc.
Ignoring trailing garbage in BN_asc2bn.
Port this commit from boringSSL: https://boringssl.googlesource.com/boringssl/+/899b9b19a4cd3fe526aaf5047ab9234cdca19f7d%5E!/
Ensure |BN_div| never gives negative zero in the no_branch code.
Have |bn_correct_top| fix |bn->neg| if the input is zero so that we
don't have negative zeros lying around.
Thanks to Brian Smith for noticing.
Reviewed-by: Richard Levitte <levitte@openssl.org>
(cherry picked from commit 01c09f9fde5793e0b3712d602b02e2aed4908e8d)
Diffstat (limited to 'crypto/bn')
-rw-r--r-- | crypto/bn/bn_lib.c | 2 | ||||
-rw-r--r-- | crypto/bn/bn_print.c | 23 | ||||
-rw-r--r-- | crypto/bn/bn_rand.c | 13 |
3 files changed, 23 insertions, 15 deletions
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 0be42f8350..17d34c319e 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -1031,5 +1031,7 @@ void bn_correct_top(BIGNUM *a) } a->top = tmp_top; } + if (a->top == 0) + a->neg = 0; bn_pollute(a); } diff --git a/crypto/bn/bn_print.c b/crypto/bn/bn_print.c index 39fb03412e..a16bde862c 100644 --- a/crypto/bn/bn_print.c +++ b/crypto/bn/bn_print.c @@ -23,12 +23,9 @@ char *BN_bn2hex(const BIGNUM *a) char *buf; char *p; - if (a->neg && BN_is_zero(a)) { - /* "-0" == 3 bytes including NULL terminator */ - buf = OPENSSL_malloc(3); - } else { - buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); - } + if (BN_is_zero(a)) + return OPENSSL_strdup("0"); + buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); if (buf == NULL) { BNerr(BN_F_BN_BN2HEX, ERR_R_MALLOC_FAILURE); goto err; @@ -186,10 +183,12 @@ int BN_hex2bn(BIGNUM **bn, const char *a) } ret->top = h; bn_correct_top(ret); - ret->neg = neg; *bn = ret; bn_check_top(ret); + /* Don't set the negative flag if it's zero. */ + if (ret->top != 0) + ret->neg = neg; return (num); err: if (*bn == NULL) @@ -241,7 +240,7 @@ int BN_dec2bn(BIGNUM **bn, const char *a) if (j == BN_DEC_NUM) j = 0; l = 0; - while (*a) { + while (--i >= 0) { l *= 10; l += *a - '0'; a++; @@ -253,11 +252,13 @@ int BN_dec2bn(BIGNUM **bn, const char *a) j = 0; } } - ret->neg = neg; bn_correct_top(ret); *bn = ret; bn_check_top(ret); + /* Don't set the negative flag if it's zero. */ + if (ret->top != 0) + ret->neg = neg; return (num); err: if (*bn == NULL) @@ -268,6 +269,7 @@ int BN_dec2bn(BIGNUM **bn, const char *a) int BN_asc2bn(BIGNUM **bn, const char *a) { const char *p = a; + if (*p == '-') p++; @@ -278,7 +280,8 @@ int BN_asc2bn(BIGNUM **bn, const char *a) if (!BN_dec2bn(bn, p)) return 0; } - if (*a == '-') + /* Don't set the negative flag if it's zero. */ + if (*a == '-' && (*bn)->top != 0) (*bn)->neg = 1; return 1; } diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c index 5ad80507b0..c577fd169d 100644 --- a/crypto/bn/bn_rand.c +++ b/crypto/bn/bn_rand.c @@ -20,15 +20,14 @@ static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) int ret = 0, bit, bytes, mask; time_t tim; - if (bits < 0 || (bits == 1 && top > 0)) { - BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL); - return 0; - } - if (bits == 0) { + if (top != BN_RAND_TOP_ANY || bottom != BN_RAND_BOTTOM_ANY) + goto toosmall; BN_zero(rnd); return 1; } + if (bits < 0 || (bits == 1 && top > 0)) + goto toosmall; bytes = (bits + 7) / 8; bit = (bits - 1) % 8; @@ -88,6 +87,10 @@ static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) OPENSSL_clear_free(buf, bytes); bn_check_top(rnd); return (ret); + +toosmall: + BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL); + return 0; } int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) |