This allows a BIGNUM consumer to avoid messing around with bn->d and bn->top/width. Bug: 232 Change-Id: I134cf412fef24eb404ff66c84831b4591d921a17 Reviewed-on: https://boringssl-review.googlesource.com/25484 Commit-Queue: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org> Reviewed-by: Adam Langley <agl@google.com>kris/onging/CECPQ3_patch15
@@ -2064,3 +2064,44 @@ TEST_F(BNTest, NonMinimal) { | |||||
EXPECT_EQ(mont->N.width, mont2->N.width); | EXPECT_EQ(mont->N.width, mont2->N.width); | ||||
EXPECT_EQ(0, BN_cmp(&mont->RR, &mont2->RR)); | EXPECT_EQ(0, BN_cmp(&mont->RR, &mont2->RR)); | ||||
} | } | ||||
TEST_F(BNTest, CountLowZeroBits) { | |||||
bssl::UniquePtr<BIGNUM> ten(BN_new()); | |||||
ASSERT_TRUE(ten); | |||||
ASSERT_TRUE(BN_set_word(ten.get(), 10)); | |||||
bssl::UniquePtr<BIGNUM> eight(BN_new()); | |||||
ASSERT_TRUE(eight); | |||||
ASSERT_TRUE(BN_set_word(eight.get(), 8)); | |||||
bssl::UniquePtr<BIGNUM> two_exp_256(BN_new()); | |||||
ASSERT_TRUE(two_exp_256); | |||||
ASSERT_TRUE(BN_lshift(two_exp_256.get(), BN_value_one(), 256)); | |||||
bssl::UniquePtr<BIGNUM> two_exp_256_plus_4(BN_new()); | |||||
ASSERT_TRUE(two_exp_256_plus_4); | |||||
ASSERT_TRUE(BN_lshift(two_exp_256_plus_4.get(), BN_value_one(), 256)); | |||||
ASSERT_TRUE(BN_add_word(two_exp_256_plus_4.get(), 4)); | |||||
bssl::UniquePtr<BIGNUM> zero(BN_new()); | |||||
ASSERT_TRUE(zero); | |||||
BN_zero(zero.get()); | |||||
EXPECT_EQ(1, BN_count_low_zero_bits(ten.get())); | |||||
EXPECT_EQ(3, BN_count_low_zero_bits(eight.get())); | |||||
EXPECT_EQ(256, BN_count_low_zero_bits(two_exp_256.get())); | |||||
EXPECT_EQ(2, BN_count_low_zero_bits(two_exp_256_plus_4.get())); | |||||
EXPECT_EQ(0, BN_count_low_zero_bits(zero.get())); | |||||
ASSERT_TRUE(bn_resize_words(ten.get(), 16)); | |||||
ASSERT_TRUE(bn_resize_words(eight.get(), 16)); | |||||
ASSERT_TRUE(bn_resize_words(two_exp_256.get(), 16)); | |||||
ASSERT_TRUE(bn_resize_words(two_exp_256_plus_4.get(), 16)); | |||||
ASSERT_TRUE(bn_resize_words(zero.get(), 16)); | |||||
EXPECT_EQ(1, BN_count_low_zero_bits(ten.get())); | |||||
EXPECT_EQ(3, BN_count_low_zero_bits(eight.get())); | |||||
EXPECT_EQ(256, BN_count_low_zero_bits(two_exp_256.get())); | |||||
EXPECT_EQ(2, BN_count_low_zero_bits(two_exp_256_plus_4.get())); | |||||
EXPECT_EQ(0, BN_count_low_zero_bits(zero.get())); | |||||
} |
@@ -304,3 +304,19 @@ int BN_mask_bits(BIGNUM *a, int n) { | |||||
bn_set_minimal_width(a); | bn_set_minimal_width(a); | ||||
return 1; | return 1; | ||||
} | } | ||||
int BN_count_low_zero_bits(const BIGNUM *bn) { | |||||
for (int i = 0; i < bn->width; i++) { | |||||
if (bn->d[i] != 0) { | |||||
int bits = 0; | |||||
for (BN_ULONG w = bn->d[i]; (w & 1) == 0; w >>= 1) { | |||||
bits++; | |||||
} | |||||
return i * BN_BITS2 + bits; | |||||
} | |||||
} | |||||
// We got to the end of |bn| and saw no non-zero words. |bn| is zero, so | |||||
// return zero. | |||||
return 0; | |||||
} |
@@ -459,6 +459,7 @@ OPENSSL_EXPORT int BN_is_odd(const BIGNUM *bn); | |||||
// BN_is_pow2 returns 1 if |a| is a power of two, and 0 otherwise. | // BN_is_pow2 returns 1 if |a| is a power of two, and 0 otherwise. | ||||
OPENSSL_EXPORT int BN_is_pow2(const BIGNUM *a); | OPENSSL_EXPORT int BN_is_pow2(const BIGNUM *a); | ||||
// Bitwise operations. | // Bitwise operations. | ||||
// BN_lshift sets |r| equal to |a| << n. The |a| and |r| arguments may be the | // BN_lshift sets |r| equal to |a| << n. The |a| and |r| arguments may be the | ||||
@@ -495,6 +496,11 @@ OPENSSL_EXPORT int BN_is_bit_set(const BIGNUM *a, int n); | |||||
// on success or zero if |n| is greater than the length of |a| already. | // on success or zero if |n| is greater than the length of |a| already. | ||||
OPENSSL_EXPORT int BN_mask_bits(BIGNUM *a, int n); | OPENSSL_EXPORT int BN_mask_bits(BIGNUM *a, int n); | ||||
// BN_count_low_zero_bits returns the number of low-order zero bits in |bn|, or | |||||
// the number of factors of two which divide it. It returns zero if |bn| is | |||||
// zero. | |||||
OPENSSL_EXPORT int BN_count_low_zero_bits(const BIGNUM *bn); | |||||
// Modulo arithmetic. | // Modulo arithmetic. | ||||