diff options
Diffstat (limited to 'src/lib/rng/rng.h')
-rw-r--r-- | src/lib/rng/rng.h | 217 |
1 files changed, 141 insertions, 76 deletions
diff --git a/src/lib/rng/rng.h b/src/lib/rng/rng.h index 3fd3dcec8..2e08ce553 100644 --- a/src/lib/rng/rng.h +++ b/src/lib/rng/rng.h @@ -1,6 +1,6 @@ /* -* RandomNumberGenerator -* (C) 1999-2009 Jack Lloyd +* Random Number Generator base classes +* (C) 1999-2009,2015,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -19,16 +19,20 @@ namespace Botan { class Entropy_Sources; /** -* This class represents a random number (RNG) generator object. +* An interface to a generic RNG */ class BOTAN_DLL RandomNumberGenerator { public: - /** - * Create a seeded and active RNG object for general application use - * Added in 1.8.0 + virtual ~RandomNumberGenerator() = default; + + RandomNumberGenerator() = default; + + /* + * Never copy a RNG, create a new one */ - static RandomNumberGenerator* make_rng(); + RandomNumberGenerator(const RandomNumberGenerator& rng) = delete; + RandomNumberGenerator& operator=(const RandomNumberGenerator& rng) = delete; /** * Randomize a byte array. @@ -38,41 +42,35 @@ class BOTAN_DLL RandomNumberGenerator virtual void randomize(byte output[], size_t length) = 0; /** - * Return a random vector - * @param bytes number of bytes in the result - * @return randomized vector of length bytes + * Incorporate some entropy into the RNG state. For example + * adding nonces or timestamps from a peer's protocol message + * can help hedge against VM state rollback attacks. + * + * @param inputs a byte array containg the entropy to be added + * @param length the length of the byte array in */ - virtual secure_vector<byte> random_vec(size_t bytes) - { - secure_vector<byte> output(bytes); - randomize(output.data(), output.size()); - return output; - } + virtual void add_entropy(const byte input[], size_t length) = 0; /** - * Only usable with POD types, only useful with integers - * get_random<u64bit>() + * Incorporate entropy into the RNG state then produce output + * Some RNG types implement this using a single operation. */ - template<typename T> T get_random() + virtual void randomize_with_input(byte output[], size_t output_len, + const byte input[], size_t input_len) { - T r; - this->randomize(reinterpret_cast<byte*>(&r), sizeof(r)); - return r; + this->add_entropy(input, input_len); + this->randomize(output, output_len); } /** - * Return a random byte - * @return random byte + * Return the name of this object */ - byte next_byte() { return get_random<byte>(); } + virtual std::string name() const = 0; - byte next_nonzero_byte() - { - byte b = next_byte(); - while(b == 0) - b = next_byte(); - return b; - } + /** + * Clear all internally held values of this RNG. + */ + virtual void clear() = 0; /** * Check whether this RNG is seeded. @@ -81,85 +79,144 @@ class BOTAN_DLL RandomNumberGenerator virtual bool is_seeded() const = 0; /** - * Clear all internally held values of this RNG. - */ - virtual void clear() = 0; - - /** - * Return the name of this object + * 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 std::string name() const = 0; + virtual size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout); /** - * Seed this RNG using the global entropy sources and default timeout + * Reseed this RNG from the default entropy sources and a default timeout * @param bits_to_collect is the number of bits of entropy to - attempt to gather from the entropy sources + * attempt to gather from the entropy sources + * @param poll_timeout try not to run longer than this, even if + * not enough entropy has been collected */ - size_t reseed(size_t bits_to_collect); + size_t reseed(size_t bits_to_collect = BOTAN_RNG_RESEED_POLL_BITS); /** - * Seed this RNG using the global entropy sources + * Reseed this RNG from the default 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 + * attempt to gather from the entropy sources + * @param poll_timeout try not to run longer than this, even if + * not enough entropy has been collected */ 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. + * Return a random vector + * @param bytes number of bytes in the result + * @return randomized vector of length bytes */ - virtual size_t reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout) = 0; + secure_vector<byte> random_vec(size_t bytes) + { + secure_vector<byte> output(bytes); + randomize(output.data(), output.size()); + return output; + } /** - * Add entropy to this RNG. - * @param in a byte array containg the entropy to be added - * @param length the length of the byte array in + * Return a random byte + * @return random byte */ - virtual void add_entropy(const byte in[], size_t length) = 0; + byte next_byte() + { + byte b; + this->randomize(&b, 1); + return b; + } - /* - * Never copy a RNG, create a new one + byte next_nonzero_byte() + { + byte b = next_byte(); + while(b == 0) + b = next_byte(); + return b; + } + + /** + * Create a seeded and active RNG object for general application use + * Added in 1.8.0 + * Use AutoSeeded_RNG instead */ - RandomNumberGenerator(const RandomNumberGenerator& rng) = delete; - RandomNumberGenerator& operator=(const RandomNumberGenerator& rng) = delete; + static RandomNumberGenerator* make_rng(); + }; - RandomNumberGenerator() {} - virtual ~RandomNumberGenerator() {} +/** +* Inherited by RNGs which maintain in-process state, like HMAC_DRBG. +* On Unix these RNGs are vulnerable to problems with fork, where the +* RNG state is duplicated, and the parent and child process RNGs will +* produce identical output until one of them reseeds. Stateful_RNG +* reseeds itself whenever a fork is detected, or after a set number of +* bytes have been output. +* +* Not implemented by RNGs which access an external RNG, such as the +* system PRNG or an hardware RNG. +*/ +class BOTAN_DLL Stateful_RNG : public RandomNumberGenerator + { + public: + Stateful_RNG(size_t max_output_before_reseed); + + virtual bool is_seeded() const override final; + + /** + * Consume this input and mark the RNG as initialized regardless + * of the length of the input or the current seeded state of + * the RNG. + */ + void initialize_with(const byte input[], size_t length); + + /** + * Poll provided sources for up to poll_bits bits of entropy + * or until the timeout expires. Returns estimate of the number + * of bits collected. + */ + size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override; + + protected: + void reseed_check(size_t bytes_requested); + + private: + const size_t m_max_bytes_before_reseed_required; + size_t m_bytes_since_reseed = 0; + uint32_t m_last_pid = 0; + bool m_successful_initialization = false; }; typedef RandomNumberGenerator RNG; /** * Null/stub RNG - fails if you try to use it for anything +* This is not generally useful except for in certain tests */ -class BOTAN_DLL Null_RNG : public RandomNumberGenerator +class BOTAN_DLL Null_RNG final : public RandomNumberGenerator { public: - void randomize(byte[], size_t) override { throw PRNG_Unseeded("Null_RNG"); } + bool is_seeded() const override { return false; } void clear() override {} - std::string name() const override { return "Null_RNG"; } - - size_t reseed_with_sources(Entropy_Sources&, size_t, - std::chrono::milliseconds) override + void randomize(byte[], size_t) override { - return 0; + throw Exception("Null_RNG called"); } - bool is_seeded() const override { return false; } void add_entropy(const byte[], size_t) override {} + + std::string name() const override { return "Null_RNG"; } }; + /** * Wraps access to a RNG in a mutex */ -class BOTAN_DLL Serialized_RNG : public RandomNumberGenerator +class BOTAN_DLL Serialized_RNG final : public RandomNumberGenerator { public: void randomize(byte out[], size_t len) override @@ -168,6 +225,20 @@ class BOTAN_DLL Serialized_RNG : public RandomNumberGenerator m_rng->randomize(out, len); } + void randomize_with_input(byte output[], size_t output_length, + const byte input[], size_t input_length) override + { + std::lock_guard<std::mutex> lock(m_mutex); + m_rng->randomize_with_input(output, output_length, + input, input_length); + } + + void add_entropy(const byte in[], size_t len) override + { + std::lock_guard<std::mutex> lock(m_mutex); + m_rng->add_entropy(in, len); + } + bool is_seeded() const override { std::lock_guard<std::mutex> lock(m_mutex); @@ -194,12 +265,6 @@ class BOTAN_DLL Serialized_RNG : public RandomNumberGenerator return m_rng->reseed_with_sources(src, bits, msec); } - void add_entropy(const byte in[], size_t len) override - { - std::lock_guard<std::mutex> lock(m_mutex); - m_rng->add_entropy(in, len); - } - Serialized_RNG() : m_rng(RandomNumberGenerator::make_rng()) {} explicit Serialized_RNG(RandomNumberGenerator* rng) : m_rng(rng) {} private: |