diff options
Diffstat (limited to 'src/tests/test_bigint.cpp')
-rw-r--r-- | src/tests/test_bigint.cpp | 152 |
1 files changed, 148 insertions, 4 deletions
diff --git a/src/tests/test_bigint.cpp b/src/tests/test_bigint.cpp index 82fc49861..e6aa4a434 100644 --- a/src/tests/test_bigint.cpp +++ b/src/tests/test_bigint.cpp @@ -6,6 +6,10 @@ #include "tests.h" +#if defined(BOTAN_HAS_BIGINT) + +#if defined(BOTAN_HAS_NUMBERTHEORY) + #include <vector> #include <string> #include <fstream> @@ -13,15 +17,132 @@ #include <cstdlib> #include <iterator> - +#include <sstream> #include <botan/bigint.h> #include <botan/exceptn.h> #include <botan/numthry.h> +#include <botan/reducer.h> + +#if defined(BOTAN_HAS_EC_CURVE_GFP) +#include <botan/curve_nistp.h> +#endif using namespace Botan; namespace { +BOTAN_TEST_CASE(bigint_to_u32bit, "BigInt to_u32bit", { + for(size_t i = 0; i != 32; ++i) + { + const u32bit in = 1 << i; + BOTAN_TEST(in, BigInt(in).to_u32bit(), "in range round trips"); + } + }); + +BigInt test_integer(RandomNumberGenerator& rng, size_t bits, BigInt max) + { + /* + Produces integers with long runs of ones and zeros, for testing for + carry handling problems. + */ + BigInt x = 0; + + auto flip_prob = [](size_t i) { + if(i % 64 == 0) + return .5; + if(i % 32 == 0) + return .4; + if(i % 8 == 0) + return .05; + return .01; + }; + + bool active = rng.next_byte() % 2; + for(size_t i = 0; i != bits; ++i) + { + x <<= 1; + x += static_cast<int>(active); + + const double prob = flip_prob(i); + const double sample = double(rng.next_byte() % 100) / 100.0; // biased + + if(sample < prob) + active = !active; + } + + if(max > 0) + { + while(x >= max) + { + const size_t b = x.bits() - 1; + BOTAN_ASSERT(x.get_bit(b) == true, "Set"); + x.clear_bit(b); + } + } + + return x; + } + +#if defined(BOTAN_HAS_EC_CURVE_GFP) + +void nist_redc_test(Test_State& _test, + const std::string& prime_name, + const BigInt& p, + std::function<void (BigInt&, secure_vector<word>&)> redc_fn) + { + auto& rng = test_rng(); + const BigInt p2 = p*p; + const size_t trials = 100; + const size_t p_bits = p.bits(); + + Modular_Reducer p_redc(p); + secure_vector<word> ws; + + for(size_t i = 0; i != trials; ++i) + { + const BigInt x = test_integer(rng, 2*p_bits, p2); + + // TODO: time and report all three approaches + const BigInt v1 = x % p; + const BigInt v2 = p_redc.reduce(x); + + BigInt v3 = x; + redc_fn(v3, ws); + + BOTAN_TEST(v1, v2, "reference"); + BOTAN_TEST(v2, v3, "specialized"); + + if(v1 != v2 || v2 != v3) + std::cout << "Prime " << prime_name << " input " << x << "\n"; + } + } + +#if defined(BOTAN_HAS_NIST_PRIME_REDUCERS_W32) + +BOTAN_TEST_CASE(bigint_redc_p192, "P-192 reduction", { + nist_redc_test(_test, "P-192", prime_p192(), redc_p192); + }); + +BOTAN_TEST_CASE(bigint_redc_p224, "P-224 reduction", { + nist_redc_test(_test, "P-224", prime_p224(), redc_p224); + }); + +BOTAN_TEST_CASE(bigint_redc_p256, "P-256 reduction", { + nist_redc_test(_test, "P-256", prime_p256(), redc_p256); + }); + +BOTAN_TEST_CASE(bigint_redc_p384, "P-384 reduction", { + nist_redc_test(_test, "P-384", prime_p384(), redc_p384); + }); + +#endif + +BOTAN_TEST_CASE(bigint_redc_p521, "P-521 reduction", { + nist_redc_test(_test, "P-521", prime_p521(), redc_p521); + }); + +#endif + void strip_comments(std::string& line) { if(line.find('#') != std::string::npos) @@ -342,9 +463,7 @@ size_t test_bigint() std::vector<std::string> substr = parse(line); -#if DEBUG - std::cout << "Testing: " << algorithm << std::endl; -#endif + // std::cout << "Testing: " << algorithm << std::endl; size_t new_errors = 0; if(algorithm.find("Addition") != std::string::npos) @@ -379,6 +498,31 @@ size_t test_bigint() << std::dec << alg_count << std::endl; } + total_errors += test_bigint_to_u32bit(); + +#if defined(BOTAN_HAS_EC_CURVE_GFP) + +#if defined(BOTAN_HAS_NIST_PRIME_REDUCERS_W32) + total_errors += test_bigint_redc_p192(); + total_errors += test_bigint_redc_p224(); + total_errors += test_bigint_redc_p256(); + total_errors += test_bigint_redc_p384(); + #endif + + total_errors += test_bigint_redc_p521(); +#endif + return total_errors; } +#else + +UNTESTED_WARNING(bigint); + +#endif // BOTAN_HAS_NUMBERTHEORY + +#else + +SKIP_TEST(bigint); + +#endif // BOTAN_HAS_BIGINT |