diff options
author | Jack Lloyd <[email protected]> | 2015-11-24 17:51:59 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2015-11-24 17:51:59 -0500 |
commit | 5f208fab1890e2ad64b52306eccd82f031425c7a (patch) | |
tree | 6bbbf1408e10538e441e3d603d80ebb2cabc6a78 /src/lib/rng | |
parent | bf59ffc4de374d7b27b7ab400789ab2723131b7a (diff) |
New reseed_with_sources call on RNGs
Provides an easier way for an application to configure a list of
entropy sources they'd like to use, or add a custom entropy source to
their seeding.
Exposes some toggles for the global/default entropy sources to build.h
Adds basic entropy tests which runs the polls and does sanity checking
on the results, including compression tests if available. These are
less useful for the CSPRNG outputs but a good check for the ones
producing plain ASCII like the /proc reader.
Diffstat (limited to 'src/lib/rng')
-rw-r--r-- | src/lib/rng/auto_rng/auto_rng.h | 7 | ||||
-rw-r--r-- | src/lib/rng/hmac_drbg/hmac_drbg.cpp | 10 | ||||
-rw-r--r-- | src/lib/rng/hmac_drbg/hmac_drbg.h | 4 | ||||
-rw-r--r-- | src/lib/rng/hmac_rng/hmac_rng.cpp | 40 | ||||
-rw-r--r-- | src/lib/rng/hmac_rng/hmac_rng.h | 6 | ||||
-rw-r--r-- | src/lib/rng/rng.cpp | 15 | ||||
-rw-r--r-- | src/lib/rng/rng.h | 40 | ||||
-rw-r--r-- | src/lib/rng/system_rng/system_rng.cpp | 24 | ||||
-rw-r--r-- | src/lib/rng/system_rng/system_rng.h | 7 | ||||
-rw-r--r-- | src/lib/rng/x931_rng/x931_rng.cpp | 7 | ||||
-rw-r--r-- | src/lib/rng/x931_rng/x931_rng.h | 5 |
11 files changed, 124 insertions, 41 deletions
diff --git a/src/lib/rng/auto_rng/auto_rng.h b/src/lib/rng/auto_rng/auto_rng.h index a7b28af92..ce0c5a7d2 100644 --- a/src/lib/rng/auto_rng/auto_rng.h +++ b/src/lib/rng/auto_rng/auto_rng.h @@ -25,7 +25,12 @@ class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator std::string name() const override { return m_rng->name(); } - void reseed(size_t poll_bits = 256) override { m_rng->reseed(poll_bits); } + size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override + { + return m_rng->reseed_with_sources(srcs, poll_bits, poll_timeout); + } void add_entropy(const byte in[], size_t len) override { m_rng->add_entropy(in, len); } diff --git a/src/lib/rng/hmac_drbg/hmac_drbg.cpp b/src/lib/rng/hmac_drbg/hmac_drbg.cpp index ad731b6b3..67325ee1b 100644 --- a/src/lib/rng/hmac_drbg/hmac_drbg.cpp +++ b/src/lib/rng/hmac_drbg/hmac_drbg.cpp @@ -78,11 +78,13 @@ void HMAC_DRBG::update(const byte input[], size_t input_len) } } -void HMAC_DRBG::reseed(size_t poll_bits) +size_t HMAC_DRBG::reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) { if(m_prng) { - m_prng->reseed(poll_bits); + size_t bits = m_prng->reseed_with_sources(srcs, poll_bits, poll_timeout); if(m_prng->is_seeded()) { @@ -90,7 +92,11 @@ void HMAC_DRBG::reseed(size_t poll_bits) update(input.data(), input.size()); m_reseed_counter = 1; } + + return bits; } + + return 0; } void HMAC_DRBG::add_entropy(const byte input[], size_t length) diff --git a/src/lib/rng/hmac_drbg/hmac_drbg.h b/src/lib/rng/hmac_drbg/hmac_drbg.h index c9d0e3d20..bd2d18d47 100644 --- a/src/lib/rng/hmac_drbg/hmac_drbg.h +++ b/src/lib/rng/hmac_drbg/hmac_drbg.h @@ -24,7 +24,9 @@ class BOTAN_DLL HMAC_DRBG : public RandomNumberGenerator void clear() override; std::string name() const override; - void reseed(size_t poll_bits) override; + size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override; void add_entropy(const byte input[], size_t input_len) override; diff --git a/src/lib/rng/hmac_rng/hmac_rng.cpp b/src/lib/rng/hmac_rng/hmac_rng.cpp index 5456b3bac..f5a782526 100644 --- a/src/lib/rng/hmac_rng/hmac_rng.cpp +++ b/src/lib/rng/hmac_rng/hmac_rng.cpp @@ -95,7 +95,11 @@ void HMAC_RNG::randomize(byte out[], size_t length) m_output_since_reseed += length; if(m_output_since_reseed >= BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED) - reseed_with_timeout(BOTAN_RNG_RESEED_POLL_BITS, BOTAN_RNG_AUTO_RESEED_TIMEOUT); + { + reseed_with_sources(Entropy_Sources::global_sources(), + BOTAN_RNG_RESEED_POLL_BITS, + BOTAN_RNG_AUTO_RESEED_TIMEOUT); + } /* HMAC KDF as described in E-t-E, using a CTXinfo of "rng" @@ -112,15 +116,9 @@ void HMAC_RNG::randomize(byte out[], size_t length) } } -/* -* Poll for entropy and reset the internal keys -*/ -void HMAC_RNG::reseed(size_t poll_bits) - { - reseed_with_timeout(poll_bits, BOTAN_RNG_RESEED_DEFAULT_TIMEOUT); - } - -void HMAC_RNG::reseed_with_timeout(size_t poll_bits, std::chrono::milliseconds timeout) +size_t HMAC_RNG::reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds timeout) { /* Using the terminology of E-t-E, XTR is the MAC function (normally @@ -130,20 +128,18 @@ void HMAC_RNG::reseed_with_timeout(size_t poll_bits, std::chrono::milliseconds t a bad poll doesn't wipe us out. */ - double bits_collected = 0; - - typedef std::chrono::high_resolution_clock clock; + typedef std::chrono::system_clock clock; auto deadline = clock::now() + timeout; - Entropy_Accumulator accum( - [&](const byte in[], size_t in_len, double entropy_estimate) - { + double bits_collected = 0; + + Entropy_Accumulator accum([&](const byte in[], size_t in_len, double entropy_estimate) { m_extractor->update(in, in_len); bits_collected += entropy_estimate; return (bits_collected >= poll_bits || clock::now() > deadline); }); - EntropySource::poll_available_sources(accum); + srcs.poll(accum); /* * It is necessary to feed forward poll data. Otherwise, a good poll @@ -172,6 +168,8 @@ void HMAC_RNG::reseed_with_timeout(size_t poll_bits, std::chrono::milliseconds t m_extractor->output_length() * 8); m_output_since_reseed = 0; + + return static_cast<size_t>(bits_collected); } bool HMAC_RNG::is_seeded() const @@ -180,12 +178,16 @@ bool HMAC_RNG::is_seeded() const } /* -* Add user-supplied entropy to the extractor input +* Add user-supplied entropy to the extractor input then reseed +* to incorporate it into the state */ void HMAC_RNG::add_entropy(const byte input[], size_t length) { m_extractor->update(input, length); - reseed_with_timeout(BOTAN_RNG_RESEED_POLL_BITS, BOTAN_RNG_AUTO_RESEED_TIMEOUT); + + reseed_with_sources(Entropy_Sources::global_sources(), + BOTAN_RNG_RESEED_POLL_BITS, + BOTAN_RNG_RESEED_DEFAULT_TIMEOUT); } /* diff --git a/src/lib/rng/hmac_rng/hmac_rng.h b/src/lib/rng/hmac_rng/hmac_rng.h index ba12e665d..1e38daa08 100644 --- a/src/lib/rng/hmac_rng/hmac_rng.h +++ b/src/lib/rng/hmac_rng/hmac_rng.h @@ -32,9 +32,9 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator void clear() override; std::string name() const override; - void reseed(size_t poll_bits) override; - - void reseed_with_timeout(size_t poll_bits, std::chrono::milliseconds ms); + size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override; void add_entropy(const byte[], size_t) override; diff --git a/src/lib/rng/rng.cpp b/src/lib/rng/rng.cpp index d4fd5fb10..c17f23dd0 100644 --- a/src/lib/rng/rng.cpp +++ b/src/lib/rng/rng.cpp @@ -7,9 +7,24 @@ #include <botan/rng.h> #include <botan/hmac_rng.h> +#include <botan/entropy_src.h> namespace Botan { +size_t RandomNumberGenerator::reseed(size_t bits_to_collect) + { + return this->reseed_with_timeout(bits_to_collect, + BOTAN_RNG_RESEED_DEFAULT_TIMEOUT); + } + +size_t RandomNumberGenerator::reseed_with_timeout(size_t bits_to_collect, + std::chrono::milliseconds timeout) + { + return this->reseed_with_sources(Entropy_Sources::global_sources(), + bits_to_collect, + timeout); + } + RandomNumberGenerator* RandomNumberGenerator::make_rng() { std::unique_ptr<MessageAuthenticationCode> h1(MessageAuthenticationCode::create("HMAC(SHA-512)")); diff --git a/src/lib/rng/rng.h b/src/lib/rng/rng.h index a28a676a6..1ce0d5153 100644 --- a/src/lib/rng/rng.h +++ b/src/lib/rng/rng.h @@ -8,13 +8,16 @@ #ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H__ #define BOTAN_RANDOM_NUMBER_GENERATOR_H__ -#include <botan/entropy_src.h> +#include <botan/secmem.h> #include <botan/exceptn.h> +#include <chrono> #include <string> #include <mutex> namespace Botan { +class Entropy_Sources; + /** * This class represents a random number (RNG) generator object. */ @@ -100,11 +103,29 @@ class BOTAN_DLL RandomNumberGenerator virtual std::string name() const = 0; /** - * Seed this RNG using the entropy sources it contains. + * Seed this RNG using the global entropy sources and default timeout + * @param bits_to_collect is the number of bits of entropy to + attempt to gather from the entropy sources + */ + size_t reseed(size_t bits_to_collect); + + /** + * Seed this RNG using the global entropy sources * @param bits_to_collect is the number of bits of entropy to attempt to gather from the entropy sources + * @param poll_timeout try not to run longer than this, no matter what */ - virtual void reseed(size_t bits_to_collect) = 0; + size_t reseed_with_timeout(size_t bits_to_collect, + std::chrono::milliseconds poll_timeout); + + /** + * Poll provided sources for up to poll_bits bits of entropy + * or until the timeout expires. Returns estimate of the number + * of bits collected. + */ + virtual size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) = 0; /** * Add entropy to this RNG. @@ -135,7 +156,12 @@ class BOTAN_DLL Null_RNG : public RandomNumberGenerator std::string name() const override { return "Null_RNG"; } - void reseed(size_t) override {} + size_t reseed_with_sources(Entropy_Sources&, size_t, + std::chrono::milliseconds) override + { + return 0; + } + bool is_seeded() const override { return false; } void add_entropy(const byte[], size_t) override {} }; @@ -170,10 +196,12 @@ class BOTAN_DLL Serialized_RNG : public RandomNumberGenerator return m_rng->name(); } - void reseed(size_t poll_bits) override + size_t reseed_with_sources(Entropy_Sources& src, + size_t bits, + std::chrono::milliseconds msec) override { std::lock_guard<std::mutex> lock(m_mutex); - m_rng->reseed(poll_bits); + return m_rng->reseed_with_sources(src, bits, msec); } void add_entropy(const byte in[], size_t len) override diff --git a/src/lib/rng/system_rng/system_rng.cpp b/src/lib/rng/system_rng/system_rng.cpp index 8b949d071..02ad07736 100644 --- a/src/lib/rng/system_rng/system_rng.cpp +++ b/src/lib/rng/system_rng/system_rng.cpp @@ -40,8 +40,18 @@ class System_RNG_Impl : public RandomNumberGenerator void clear() override {} std::string name() const override { return "system"; } - void reseed(size_t) override {} - void add_entropy(const byte[], size_t) override {} + size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override + { + return 0; + } + + void add_entropy(const byte[], size_t) override + { + // We could write this back to /dev/urandom to help seed the PRNG + // Unclear if this is valuable on current systems + } private: #if defined(BOTAN_TARGET_OS_HAS_CRYPTGENRANDOM) @@ -55,14 +65,18 @@ System_RNG_Impl::System_RNG_Impl() { #if defined(BOTAN_TARGET_OS_HAS_CRYPTGENRANDOM) - if(!CryptAcquireContext(&m_prov, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + if(!CryptAcquireContext(&m_prov, 0, 0, BOTAN_SYSTEM_RNG_CRYPTOAPI_PROV_TYPE, CRYPT_VERIFYCONTEXT)) throw std::runtime_error("System_RNG failed to acquire crypto provider"); #else - m_fd = ::open("/dev/urandom", O_RDONLY); +#ifndef O_NOCTTY + #define O_NOCTTY 0 +#endif + + m_fd = ::open(BOTAN_SYSTEM_RNG_DEVICE, O_RDONLY | O_NOCTTY); if(m_fd < 0) - throw std::runtime_error("System_RNG failed to open /dev/urandom"); + throw std::runtime_error("System_RNG failed to open RNG device"); #endif } diff --git a/src/lib/rng/system_rng/system_rng.h b/src/lib/rng/system_rng/system_rng.h index 0f4b94725..6290b8769 100644 --- a/src/lib/rng/system_rng/system_rng.h +++ b/src/lib/rng/system_rng/system_rng.h @@ -35,7 +35,12 @@ class BOTAN_DLL System_RNG : public RandomNumberGenerator std::string name() const override { return m_rng.name(); } - void reseed(size_t poll_bits = 256) override { m_rng.reseed(poll_bits); } + size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override + { + return m_rng.reseed_with_sources(srcs, poll_bits, poll_timeout); + } void add_entropy(const byte in[], size_t len) override { m_rng.add_entropy(in, len); } private: diff --git a/src/lib/rng/x931_rng/x931_rng.cpp b/src/lib/rng/x931_rng/x931_rng.cpp index d531cf4a9..020d9a5a5 100644 --- a/src/lib/rng/x931_rng/x931_rng.cpp +++ b/src/lib/rng/x931_rng/x931_rng.cpp @@ -72,10 +72,13 @@ void ANSI_X931_RNG::rekey() } } -void ANSI_X931_RNG::reseed(size_t poll_bits) +size_t ANSI_X931_RNG::reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) { - m_prng->reseed(poll_bits); + size_t bits = m_prng->reseed_with_sources(srcs, poll_bits, poll_timeout); rekey(); + return bits; } void ANSI_X931_RNG::add_entropy(const byte input[], size_t length) diff --git a/src/lib/rng/x931_rng/x931_rng.h b/src/lib/rng/x931_rng/x931_rng.h index 899fed956..ed7124a08 100644 --- a/src/lib/rng/x931_rng/x931_rng.h +++ b/src/lib/rng/x931_rng/x931_rng.h @@ -24,7 +24,10 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator void clear() override; std::string name() const override; - void reseed(size_t poll_bits) override; + size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override; + void add_entropy(const byte[], size_t) override; /** |