Tolerate -0 better in BN_bn2{dec,hex}

Negative zeros are nuts, but it will probably be a while before we've
fixed everything that can create them. Fix both to consistently print
'-0' rather than '0' so failures are easier to diagnose (BN_cmp believes
the values are different.)

Change-Id: Ic38d90601b43f66219d8f44ca085432106cf98e3
Reviewed-on: https://boringssl-review.googlesource.com/9073
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
David Benjamin 2016-08-02 12:49:38 -04:00 committed by CQ bot account: commit-bot@chromium.org
parent 7fcbfdbdf3
commit 2b314fa3a9
2 changed files with 52 additions and 25 deletions

View File

@ -1138,7 +1138,7 @@ static bool TestNegativeZero(BN_CTX *ctx) {
return false; return false;
} }
if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) { if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
fprintf(stderr, "Multiplication test failed!\n"); fprintf(stderr, "Multiplication test failed.\n");
return false; return false;
} }
@ -1152,7 +1152,7 @@ static bool TestNegativeZero(BN_CTX *ctx) {
return false; return false;
} }
if (!BN_is_zero(d.get()) || BN_is_negative(d.get())) { if (!BN_is_zero(d.get()) || BN_is_negative(d.get())) {
fprintf(stderr, "Division test failed!\n"); fprintf(stderr, "Division test failed.\n");
return false; return false;
} }
@ -1164,7 +1164,27 @@ static bool TestNegativeZero(BN_CTX *ctx) {
return false; return false;
} }
if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) { if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
fprintf(stderr, "Division test failed!\n"); fprintf(stderr, "Division test failed.\n");
return false;
}
// Test that BN_set_negative will not produce a negative zero.
BN_zero(a.get());
BN_set_negative(a.get(), 1);
if (BN_is_negative(a.get())) {
fprintf(stderr, "BN_set_negative produced a negative zero.\n");
return false;
}
// Test that forcibly creating a negative zero does not break |BN_bn2hex| or
// |BN_bn2dec|.
a->neg = 1;
ScopedOpenSSLString dec(BN_bn2dec(a.get()));
ScopedOpenSSLString hex(BN_bn2hex(a.get()));
if (!dec || !hex ||
strcmp(dec.get(), "-0") != 0 ||
strcmp(hex.get(), "-0") != 0) {
fprintf(stderr, "BN_bn2dec or BN_bn2hex failed with negative zero.\n");
return false; return false;
} }
@ -1183,39 +1203,43 @@ static bool TestBadModulus(BN_CTX *ctx) {
BN_zero(zero.get()); BN_zero(zero.get());
if (BN_div(a.get(), b.get(), BN_value_one(), zero.get(), ctx)) { if (BN_div(a.get(), b.get(), BN_value_one(), zero.get(), ctx)) {
fprintf(stderr, "Division by zero succeeded!\n"); fprintf(stderr, "Division by zero unexpectedly succeeded.\n");
return false; return false;
} }
ERR_clear_error(); ERR_clear_error();
if (BN_mod_mul(a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx)) { if (BN_mod_mul(a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx)) {
fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n"); fprintf(stderr, "BN_mod_mul with zero modulus unexpectedly succeeded.\n");
return false; return false;
} }
ERR_clear_error(); ERR_clear_error();
if (BN_mod_exp(a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx)) { if (BN_mod_exp(a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx)) {
fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n"); fprintf(stderr, "BN_mod_exp with zero modulus unexpectedly succeeded.\n");
return 0; return 0;
} }
ERR_clear_error(); ERR_clear_error();
if (BN_mod_exp_mont(a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx, if (BN_mod_exp_mont(a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx,
NULL)) { NULL)) {
fprintf(stderr, "BN_mod_exp_mont with zero modulus succeeded!\n"); fprintf(stderr,
"BN_mod_exp_mont with zero modulus unexpectedly succeeded.\n");
return 0; return 0;
} }
ERR_clear_error(); ERR_clear_error();
if (BN_mod_exp_mont_consttime(a.get(), BN_value_one(), BN_value_one(), if (BN_mod_exp_mont_consttime(a.get(), BN_value_one(), BN_value_one(),
zero.get(), ctx, nullptr)) { zero.get(), ctx, nullptr)) {
fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus succeeded!\n"); fprintf(stderr,
"BN_mod_exp_mont_consttime with zero modulus unexpectedly "
"succeeded.\n");
return 0; return 0;
} }
ERR_clear_error(); ERR_clear_error();
if (BN_MONT_CTX_set(mont.get(), zero.get(), ctx)) { if (BN_MONT_CTX_set(mont.get(), zero.get(), ctx)) {
fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n"); fprintf(stderr,
"BN_MONT_CTX_set unexpectedly succeeded for zero modulus.\n");
return false; return false;
} }
ERR_clear_error(); ERR_clear_error();
@ -1227,21 +1251,25 @@ static bool TestBadModulus(BN_CTX *ctx) {
} }
if (BN_MONT_CTX_set(mont.get(), b.get(), ctx)) { if (BN_MONT_CTX_set(mont.get(), b.get(), ctx)) {
fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n"); fprintf(stderr,
"BN_MONT_CTX_set unexpectedly succeeded for even modulus.\n");
return false; return false;
} }
ERR_clear_error(); ERR_clear_error();
if (BN_mod_exp_mont(a.get(), BN_value_one(), BN_value_one(), b.get(), ctx, if (BN_mod_exp_mont(a.get(), BN_value_one(), BN_value_one(), b.get(), ctx,
NULL)) { NULL)) {
fprintf(stderr, "BN_mod_exp_mont with even modulus succeeded!\n"); fprintf(stderr,
"BN_mod_exp_mont with even modulus unexpectedly succeeded.\n");
return 0; return 0;
} }
ERR_clear_error(); ERR_clear_error();
if (BN_mod_exp_mont_consttime(a.get(), BN_value_one(), BN_value_one(), if (BN_mod_exp_mont_consttime(a.get(), BN_value_one(), BN_value_one(),
b.get(), ctx, nullptr)) { b.get(), ctx, nullptr)) {
fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus succeeded!\n"); fprintf(stderr,
"BN_mod_exp_mont_consttime with even modulus unexpectedly "
"succeeded.\n");
return 0; return 0;
} }
ERR_clear_error(); ERR_clear_error();

View File

@ -204,17 +204,14 @@ int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
static const char hextable[] = "0123456789abcdef"; static const char hextable[] = "0123456789abcdef";
char *BN_bn2hex(const BIGNUM *bn) { char *BN_bn2hex(const BIGNUM *bn) {
int i, j, v, z = 0; char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
char *buf; bn->top * BN_BYTES * 2 + 1 /* trailing NUL */);
char *p;
buf = OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2);
if (buf == NULL) { if (buf == NULL) {
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
return NULL; return NULL;
} }
p = buf; char *p = buf;
if (bn->neg) { if (bn->neg) {
*(p++) = '-'; *(p++) = '-';
} }
@ -223,10 +220,11 @@ char *BN_bn2hex(const BIGNUM *bn) {
*(p++) = '0'; *(p++) = '0';
} }
for (i = bn->top - 1; i >= 0; i--) { int z = 0;
for (j = BN_BITS2 - 8; j >= 0; j -= 8) { for (int i = bn->top - 1; i >= 0; i--) {
for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
/* strip leading zeros */ /* strip leading zeros */
v = ((int)(bn->d[i] >> (long)j)) & 0xff; int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
if (z || v != 0) { if (z || v != 0) {
*(p++) = hextable[v >> 4]; *(p++) = hextable[v >> 4];
*(p++) = hextable[v & 0x0f]; *(p++) = hextable[v & 0x0f];
@ -399,14 +397,15 @@ char *BN_bn2dec(const BIGNUM *a) {
#define BUF_REMAIN (num + 3 - (size_t)(p - buf)) #define BUF_REMAIN (num + 3 - (size_t)(p - buf))
p = buf; p = buf;
lp = bn_data; lp = bn_data;
if (BN_is_negative(t)) {
*p++ = '-';
}
if (BN_is_zero(t)) { if (BN_is_zero(t)) {
*(p++) = '0'; *(p++) = '0';
*(p++) = '\0'; *(p++) = '\0';
} else { } else {
if (BN_is_negative(t)) {
*p++ = '-';
}
while (!BN_is_zero(t)) { while (!BN_is_zero(t)) {
*lp = BN_div_word(t, BN_DEC_CONV); *lp = BN_div_word(t, BN_DEC_CONV);
lp++; lp++;