ssl_bn: skip truncation shift for byte-aligned BN_rand requests

- wolfSSL_BN_rand() calls mp_rshb() only when bits is not a
  multiple of 8.
- test_wolfSSL_BN_rand() declares i and seen, and samples 8-bit
  TOP_ANY, 16-bit TOP_ANY, and 8-bit TOP_ONE requests to assert
  the results are not confined to the low byte.

Issue: F-12559
pull/11316/head
Yosuke Shimizu 2026-08-31 10:28:42 +09:00
parent d80b4776a9
commit 900bcf745f
2 changed files with 40 additions and 2 deletions

View File

@ -2167,8 +2167,8 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
/* Dispose of buffer - no longer needed. */
XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (ret == 1) {
/* Truncate to requested bit length. */
/* Truncate to requested bit length when not a whole number of bytes. */
if ((ret == 1) && ((bits % 8) != 0)) {
mp_rshb((mp_int*)bn->internal, 8 - (bits % 8));
}

View File

@ -921,6 +921,8 @@ int test_wolfSSL_BN_rand(void)
BIGNUM* bn = NULL;
BIGNUM* range = NULL;
BIGNUM emptyBN;
int i;
int seen;
XMEMSET(&emptyBN, 0, sizeof(emptyBN));
ExpectNotNull(bn = BN_new());
@ -1045,6 +1047,42 @@ int test_wolfSSL_BN_rand(void)
WOLFSSL_BN_RAND_BOTTOM_ANY), 1);
ExpectIntEQ(BN_num_bits(bn), 13);
/* A request for a multiple of 8 bits keeps every generated bit. Shifting
* out a whole byte would make the 8-bit values zero, hold the 16-bit
* values in the low byte, and fix the 8-bit top bit results at 0x80. */
seen = 0;
for (i = 0; (i < 64) && EXPECT_SUCCESS(); i++) {
ExpectIntEQ(BN_rand(bn, 8, WOLFSSL_BN_RAND_TOP_ANY,
WOLFSSL_BN_RAND_BOTTOM_ANY), 1);
if (EXPECT_SUCCESS() && (BN_is_zero(bn) == 0)) {
seen = 1;
break;
}
}
ExpectIntEQ(seen, 1);
seen = 0;
for (i = 0; (i < 64) && EXPECT_SUCCESS(); i++) {
ExpectIntEQ(BN_rand(bn, 16, WOLFSSL_BN_RAND_TOP_ANY,
WOLFSSL_BN_RAND_BOTTOM_ANY), 1);
if (EXPECT_SUCCESS() && (BN_num_bits(bn) > 8)) {
seen = 1;
break;
}
}
ExpectIntEQ(seen, 1);
seen = 0;
for (i = 0; (i < 64) && EXPECT_SUCCESS(); i++) {
ExpectIntEQ(BN_pseudo_rand(bn, 8, WOLFSSL_BN_RAND_TOP_ONE,
WOLFSSL_BN_RAND_BOTTOM_ANY), 1);
if (EXPECT_SUCCESS() && (BN_get_word(bn) != 0x80)) {
seen = 1;
break;
}
}
ExpectIntEQ(seen, 1);
ExpectIntEQ(BN_rand(range, 64, WOLFSSL_BN_RAND_TOP_ONE,
WOLFSSL_BN_RAND_BOTTOM_ANY), 1);
ExpectIntEQ(BN_rand_range(bn, range), 1);