aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-10-30 09:39:36 -0400
committerJack Lloyd <[email protected]>2017-10-30 09:39:36 -0400
commit867aed15b71926b6f9ec5815d137502c12772d88 (patch)
tree8b0a0286bdb7cde17a5879f531def6eefd261791
parent1007ab45750e4ebfd7c9bfe96efb39b7a1323226 (diff)
parent44d5d6a7e74a45f717cfedddc0d6186f182066de (diff)
Merge GH #1282 Use simple non-cryptographic PRNG for tests
-rw-r--r--src/tests/test_runner.cpp189
-rw-r--r--src/tests/test_runner.h4
-rw-r--r--src/tests/tests.cpp24
-rw-r--r--src/tests/tests.h20
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;