diff options
author | Jack Lloyd <[email protected]> | 2016-07-18 15:36:27 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-07-18 15:36:27 -0400 |
commit | e33c989417b7ad9557b02936a1a814e37bf85fcd (patch) | |
tree | c36944002c46e7098d4ab33209c2deaca391b4c1 /src/tests/test_rng.cpp | |
parent | 7438e0b4c85403ba6f4c864a76cd8865f9659ed3 (diff) | |
parent | 8f2f800c7ea841fa5ab963349178ac3a9f56a513 (diff) |
Merge GH #520 RNG changes
Adds Stateful_RNG base class which handles reseeding after some
amount of output (configurable at instantiation time, defaults to
the build.h value) as well as detecting forks (just using pid
comparisons, so still vulnerable to pid wraparound). Implemented
by HMAC_RNG and HMAC_DRBG. I did not update X9.31 since its
underlying RNG should already be fork safe and handle reseeding
at the appropriate time, since a new block is taken from the
underlying RNG (for the datetime vector) for each block of
output.
Adds RNG::randomize_with_input which for most PRNGs is just a
call to add_entropy followed by randomize. However for HMAC_DRBG
it is used for additional input. Adds tests for HMAC_DRBG with AD
from the CAVS file.
RNG::add_entropy is implemented by System_RNG now, as both
CryptGenRandom and /dev/urandom support receiving application
provided data.
The AutoSeeded_RNG underlying type is currently selectable in
build.h and defaults to HMAC_DRBG(SHA-256). AutoSeeded_RNG
provides additional input with each output request, consisting of
the current pid, a counter, and timestamp (unless the application
explicitly calls randomize_with_input, in which case we just take
what they provided). This is the same hedge used in HMAC_RNGs
output PRF.
AutoSeeded_RNG is part of the base library now and cannot be
compiled out.
Removes Entropy_Accumulator type (which just served to bridge
between the RNG and the entropy source), instead the
Entropy_Source is passed a reference to the RNG being reseeded,
and it can call add_entropy on whatever it can come up with.
Diffstat (limited to 'src/tests/test_rng.cpp')
-rw-r--r-- | src/tests/test_rng.cpp | 94 |
1 files changed, 26 insertions, 68 deletions
diff --git a/src/tests/test_rng.cpp b/src/tests/test_rng.cpp index 7f1c1f123..2092f7545 100644 --- a/src/tests/test_rng.cpp +++ b/src/tests/test_rng.cpp @@ -19,82 +19,32 @@ namespace Botan_Tests { namespace { -Botan::RandomNumberGenerator* get_rng(const std::string& algo_str, const std::vector<byte>& ikm) - { - class AllOnce_RNG : public Fixed_Output_RNG - { - public: - explicit AllOnce_RNG(const std::vector<byte>& in) : Fixed_Output_RNG(in) {} - - Botan::secure_vector<byte> random_vec(size_t) override - { - Botan::secure_vector<byte> vec(this->remaining()); - this->randomize(vec.data(), vec.size()); - return vec; - } - }; - - const std::vector<std::string> algo_name = Botan::parse_algorithm_name(algo_str); - - const std::string rng_name = algo_name[0]; - -#if defined(BOTAN_HAS_HMAC_DRBG) - if(rng_name == "HMAC_DRBG") - { - auto mac = Botan::MessageAuthenticationCode::create("HMAC(" + algo_name[1] + ")"); - - if(!mac) - { - return nullptr; - } - - return new Botan::HMAC_DRBG(mac.release(), new AllOnce_RNG(ikm)); - } - -#endif - -#if defined(BOTAN_HAS_X931_RNG) - if(rng_name == "X9.31-RNG") - { - auto bc = Botan::BlockCipher::create(algo_name[1]); - - if(!bc) - { - return nullptr; - } - - return new Botan::ANSI_X931_RNG(bc.release(), new Fixed_Output_RNG(ikm)); - } -#endif - - return nullptr; - } - #if defined(BOTAN_HAS_X931_RNG) class X931_RNG_Tests : public Text_Based_Test { public: - X931_RNG_Tests() : Text_Based_Test("x931.vec", {"IKM", "L", "Out"}) {} + X931_RNG_Tests() : Text_Based_Test("x931.vec", {"IKM", "Out"}) {} Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { const std::vector<uint8_t> ikm = get_req_bin(vars, "IKM"); const std::vector<uint8_t> expected = get_req_bin(vars, "Out"); - const size_t L = get_req_sz(vars, "L"); + Test::Result result("X9.31-RNG(" + algo + ")"); - Test::Result result(algo); + std::unique_ptr<Botan::BlockCipher> bc = Botan::BlockCipher::create(algo); - result.test_eq("length", L, expected.size()); - - std::unique_ptr<Botan::RandomNumberGenerator> rng(get_rng(algo, ikm)); - if(!rng) + if(!bc) { - result.note_missing("RNG " + algo); + result.note_missing("X9.31 cipher " + algo); return result; } - result.test_eq("rng", rng->random_vec(L), expected); + Botan::ANSI_X931_RNG rng(bc.release(), new Fixed_Output_RNG(ikm)); + + std::vector<uint8_t> output(expected.size()); + rng.randomize(output.data(), output.size()); + result.test_eq("rng", output, expected); return result; } @@ -110,7 +60,8 @@ class HMAC_DRBG_Tests : public Text_Based_Test { public: HMAC_DRBG_Tests() : Text_Based_Test("hmac_drbg.vec", - {"EntropyInput", "EntropyInputReseed", "Out"}) {} + {"EntropyInput", "EntropyInputReseed", "Out"}, + {"AdditionalInput1", "AdditionalInput2"}) {} Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { @@ -118,23 +69,30 @@ class HMAC_DRBG_Tests : public Text_Based_Test const std::vector<byte> reseed_input = get_req_bin(vars, "EntropyInputReseed"); const std::vector<byte> expected = get_req_bin(vars, "Out"); - Test::Result result(algo); + const std::vector<byte> ad1 = get_opt_bin(vars, "AdditionalInput1"); + const std::vector<byte> ad2 = get_opt_bin(vars, "AdditionalInput2"); + + Test::Result result("HMAC_DRBG(" + algo + ")"); - std::unique_ptr<Botan::RandomNumberGenerator> rng(get_rng(algo, seed_input)); - if(!rng) + auto mac = Botan::MessageAuthenticationCode::create("HMAC(" + algo + ")"); + if(!mac) { - result.note_missing("RNG " + algo); + result.note_missing("HMAC(" + algo + ")"); return result; } - rng->reseed(0); // force initialization + std::unique_ptr<Botan::HMAC_DRBG> rng(new Botan::HMAC_DRBG(mac.release(), 0)); + rng->initialize_with(seed_input.data(), seed_input.size()); // now reseed rng->add_entropy(reseed_input.data(), reseed_input.size()); - rng->random_vec(expected.size()); // discard 1st block + std::vector<byte> out(expected.size()); + // first block is discarded + rng->randomize_with_input(out.data(), out.size(), ad1.data(), ad1.size()); + rng->randomize_with_input(out.data(), out.size(), ad2.data(), ad2.size()); - result.test_eq("rng", rng->random_vec(expected.size()), expected); + result.test_eq("rng", out, expected); return result; } |