diff options
author | Jack Lloyd <[email protected]> | 2017-10-30 09:39:36 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-10-30 09:39:36 -0400 |
commit | 867aed15b71926b6f9ec5815d137502c12772d88 (patch) | |
tree | 8b0a0286bdb7cde17a5879f531def6eefd261791 | |
parent | 1007ab45750e4ebfd7c9bfe96efb39b7a1323226 (diff) | |
parent | 44d5d6a7e74a45f717cfedddc0d6186f182066de (diff) |
Merge GH #1282 Use simple non-cryptographic PRNG for tests
-rw-r--r-- | src/tests/test_runner.cpp | 189 | ||||
-rw-r--r-- | src/tests/test_runner.h | 4 | ||||
-rw-r--r-- | src/tests/tests.cpp | 24 | ||||
-rw-r--r-- | src/tests/tests.h | 20 |
4 files changed, 114 insertions, 123 deletions
diff --git a/src/tests/test_runner.cpp b/src/tests/test_runner.cpp index 6900a32ed..d6b612ded 100644 --- a/src/tests/test_runner.cpp +++ b/src/tests/test_runner.cpp @@ -8,20 +8,8 @@ #include "tests.h" #include <botan/version.h> +#include <botan/rotate.h> #include <botan/loadstor.h> -#include <botan/mac.h> - -#if defined(BOTAN_HAS_HMAC_DRBG) - #include <botan/hmac_drbg.h> -#endif - -#if defined(BOTAN_HAS_SYSTEM_RNG) - #include <botan/system_rng.h> -#endif - -#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - #include <botan/auto_rng.h> -#endif namespace Botan_Tests { @@ -29,98 +17,72 @@ Test_Runner::Test_Runner(std::ostream& out) : m_output(out) {} namespace { -std::unique_ptr<Botan::RandomNumberGenerator> -create_test_rng(const std::string& drbg_seed, std::ostream& output) +/* +* This is a fast, simple, deterministic PRNG that's used for running +* the tests. It is not intended to be cryptographically secure. +*/ +class Testsuite_RNG final : public Botan::RandomNumberGenerator { - std::unique_ptr<Botan::RandomNumberGenerator> rng; - -#if defined(BOTAN_HAS_HMAC_DRBG) && defined(BOTAN_AUTO_RNG_HMAC) - - std::vector<uint8_t> seed = Botan::hex_decode(drbg_seed); - if(seed.empty()) - { - const uint64_t ts = Botan_Tests::Test::timestamp(); - seed.resize(8); - Botan::store_be(ts, seed.data()); - } - - output << " rng:HMAC_DRBG(" << BOTAN_AUTO_RNG_HMAC << ") with seed '" << Botan::hex_encode(seed) << "'\n"; + public: + std::string name() const override { return "Testsuite_RNG"; } - // Expand out the seed with a hash to make the DRBG happy - std::unique_ptr<Botan::MessageAuthenticationCode> mac = - Botan::MessageAuthenticationCode::create(BOTAN_AUTO_RNG_HMAC); - - mac->set_key(seed); - seed.resize(mac->output_length()); - mac->final(seed.data()); - - std::unique_ptr<Botan::HMAC_DRBG> drbg(new Botan::HMAC_DRBG(std::move(mac))); - drbg->initialize_with(seed.data(), seed.size()); - -#if defined(BOTAN_TARGET_OS_HAS_THREADS) - rng.reset(new Botan::Serialized_RNG(drbg.release())); -#else - rng = std::move(drbg); -#endif - -#endif - - if(!rng && drbg_seed != "") - throw Botan_Tests::Test_Error("HMAC_DRBG disabled in build, cannot specify DRBG seed"); + void clear() override + { + m_a = m_b = m_c = m_d = 0; + } -#if defined(BOTAN_HAS_SYSTEM_RNG) - if(!rng) - { - output << " rng:system\n"; - rng.reset(new Botan::System_RNG); - } -#endif + void add_entropy(const uint8_t data[], size_t len) override + { + for(size_t i = 0; i != len; ++i) + { + m_a ^= data[i]; + m_b ^= i; + mix(); + } + } -#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - if(!rng) - { - output << " rng:autoseeded\n"; -#if defined(BOTAN_TARGET_OS_HAS_THREADS) - rng.reset(new Botan::Serialized_RNG(new Botan::AutoSeeded_RNG)); -#else - rng.reset(new Botan::AutoSeeded_RNG); -#endif + bool is_seeded() const override + { + return true; + } - } -#endif + void randomize(uint8_t out[], size_t len) override + { + for(size_t i = 0; i != len; ++i) + { + out[i] = static_cast<uint8_t>(m_a); + mix(); + } + } - if(!rng) - { - // last ditch fallback for RNG-less build - class Bogus_Fallback_RNG final : public Botan::RandomNumberGenerator + Testsuite_RNG(const std::string& drbg_seed, size_t test_counter = 0) { - public: - std::string name() const override { return "Bogus_Fallback_RNG"; } + m_d = static_cast<uint32_t>(test_counter); - void clear() override { /* ignored */ } - void add_entropy(const uint8_t[], size_t) override { /* ignored */ } - bool is_seeded() const override { return true; } + add_entropy(reinterpret_cast<const uint8_t*>(drbg_seed.data()), + drbg_seed.size()); + } + private: + void mix() + { + const size_t ROUNDS = 3; - void randomize(uint8_t out[], size_t len) override - { - for(size_t i = 0; i != len; ++i) - { - m_x = (m_x * 31337 + 42); - out[i] = static_cast<uint8_t>(m_x >> 7); - } - } + for(size_t i = 0; i != ROUNDS; ++i) + { + m_a += i; - Bogus_Fallback_RNG() : m_x(1) {} - private: - uint32_t m_x; - }; + m_a = Botan::rotl<9>(m_a); + m_b ^= m_a; + m_d ^= m_c; - output << " rng:bogus\n"; - rng.reset(new Bogus_Fallback_RNG); - } + m_a += m_d; + m_c += m_b; + m_c = Botan::rotl<23>(m_c); + } + } - return rng; - } + uint32_t m_a = 0, m_b = 0, m_c = 0, m_d = 0; + }; } @@ -205,20 +167,33 @@ int Test_Runner::run(const std::vector<std::string>& requested_tests, pf.set(provider); } - std::unique_ptr<Botan::RandomNumberGenerator> rng = create_test_rng(drbg_seed, output()); + std::vector<uint8_t> seed = Botan::hex_decode(drbg_seed); + if(seed.empty()) + { + const uint64_t ts = Botan_Tests::Test::timestamp(); + seed.resize(8); + Botan::store_be(ts, seed.data()); + } - Botan_Tests::Test::setup_tests(log_success, run_online_tests, run_long_tests, - data_dir, pkcs11_lib, pf, rng.get()); + output() << " drbg_seed:" << Botan::hex_encode(seed) << "\n"; + + Botan_Tests::Test::set_test_options(log_success, + run_online_tests, + run_long_tests, + data_dir, + pkcs11_lib, + pf); for(size_t i = 0; i != runs; ++i) { - const size_t failed = run_tests(req); + std::unique_ptr<Botan::RandomNumberGenerator> rng = + std::unique_ptr<Botan::RandomNumberGenerator>(new Testsuite_RNG(drbg_seed, i)); - // Throw so main returns an error - if(failed) - { + Botan_Tests::Test::set_test_rng(std::move(rng)); + + const size_t failed = run_tests(req, i, runs); + if(failed > 0) return failed; - } } return 0; @@ -259,7 +234,9 @@ std::string report_out(const std::vector<Botan_Tests::Test::Result>& results, } -size_t Test_Runner::run_tests(const std::vector<std::string>& tests_to_run) +size_t Test_Runner::run_tests(const std::vector<std::string>& tests_to_run, + size_t test_run, + size_t tot_test_runs) { size_t tests_ran = 0, tests_failed = 0; @@ -296,7 +273,13 @@ size_t Test_Runner::run_tests(const std::vector<std::string>& tests_to_run) } const uint64_t total_ns = Botan_Tests::Test::timestamp() - start_time; - output() << "Tests complete ran " << tests_ran << " tests in " + + if(test_run == 0 && tot_test_runs == 1) + output() << "Tests"; + else + output() << "Test run " << (1+test_run) << "/" << tot_test_runs; + + output() << " complete ran " << tests_ran << " tests in " << Botan_Tests::Test::format_time(total_ns) << " "; if(tests_failed > 0) diff --git a/src/tests/test_runner.h b/src/tests/test_runner.h index 96c562024..a314fdb6b 100644 --- a/src/tests/test_runner.h +++ b/src/tests/test_runner.h @@ -31,7 +31,9 @@ class Test_Runner final private: std::ostream& output() const { return m_output; } - size_t run_tests(const std::vector<std::string>& tests_to_run); + size_t run_tests(const std::vector<std::string>& tests_to_run, + size_t test_run, + const size_t tot_test_runs); std::ostream& m_output; }; diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp index 3d937b9de..bda3cd648 100644 --- a/src/tests/tests.cpp +++ b/src/tests/tests.cpp @@ -507,7 +507,7 @@ Test* Test::get_test(const std::string& test_name) } // static member variables of Test -Botan::RandomNumberGenerator* Test::m_test_rng = nullptr; +std::unique_ptr<Botan::RandomNumberGenerator> Test::m_test_rng; std::string Test::m_data_dir; bool Test::m_log_success = false; bool Test::m_run_online_tests = false; @@ -516,24 +516,28 @@ std::string Test::m_pkcs11_lib; Botan_Tests::Provider_Filter Test::m_provider_filter; //static -void Test::setup_tests(bool log_success, - bool run_online, - bool run_long, - const std::string& data_dir, - const std::string& pkcs11_lib, - const Botan_Tests::Provider_Filter& pf, - Botan::RandomNumberGenerator* rng) +void Test::set_test_options(bool log_success, + bool run_online, + bool run_long, + const std::string& data_dir, + const std::string& pkcs11_lib, + const Botan_Tests::Provider_Filter& pf) { m_data_dir = data_dir; m_log_success = log_success; m_run_online_tests = run_online; m_run_long_tests = run_long; - m_test_rng = rng; m_pkcs11_lib = pkcs11_lib; m_provider_filter = pf; } //static +void Test::set_test_rng(std::unique_ptr<Botan::RandomNumberGenerator> rng) + { + m_test_rng.reset(rng.release()); + } + +//static std::string Test::data_file(const std::string& what) { return Test::data_dir() + "/" + what; @@ -580,7 +584,7 @@ Botan::RandomNumberGenerator& Test::rng() { if(!m_test_rng) { - throw Test_Error("No usable RNG in build, and this test requires an RNG"); + throw Test_Error("Test requires RNG but no RNG set with Test::set_test_rng"); } return *m_test_rng; } diff --git a/src/tests/tests.h b/src/tests/tests.h index fdbd080f4..9ab8e43b8 100644 --- a/src/tests/tests.h +++ b/src/tests/tests.h @@ -353,8 +353,9 @@ class Test Registration(const std::string& name, Test* test); }; - virtual std::vector<Test::Result> run() = 0; virtual ~Test() = default; + virtual std::vector<Test::Result> run() = 0; + virtual std::vector<std::string> possible_providers(const std::string&); static std::map<std::string, std::unique_ptr<Test>>& global_registry(); @@ -395,13 +396,14 @@ class Test return r; } - static void setup_tests(bool log_success, - bool run_online_tests, - bool run_long_tests, - const std::string& data_dir, - const std::string& pkcs11_lib, - const Botan_Tests::Provider_Filter& pf, - Botan::RandomNumberGenerator* rng); + static void set_test_options(bool log_success, + bool run_online_tests, + bool run_long_tests, + const std::string& data_dir, + const std::string& pkcs11_lib, + const Botan_Tests::Provider_Filter& pf); + + static void set_test_rng(std::unique_ptr<Botan::RandomNumberGenerator> rng); static bool log_success(); static bool run_online_tests(); @@ -417,7 +419,7 @@ class Test private: static std::string m_data_dir; - static Botan::RandomNumberGenerator* m_test_rng; + static std::unique_ptr<Botan::RandomNumberGenerator> m_test_rng; static bool m_log_success, m_run_online_tests, m_run_long_tests; static std::string m_pkcs11_lib; static Botan_Tests::Provider_Filter m_provider_filter; |