aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/rng/rng.h
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-08-19 07:51:47 -0400
committerJack Lloyd <[email protected]>2016-08-24 11:31:54 -0400
commit80c160f08f2a69eb4e41a68380796bf31fd2f924 (patch)
tree83259da316524ed3b96b0913e5b023bc40f26a28 /src/lib/rng/rng.h
parent91474f60d72937ad3c21d8aa53c14f7a0cceb9ca (diff)
RNG changes (GH #593)
Change reseed interval logic to count calls to `randomize` rather than bytes, to match SP 800-90A Changes RNG reseeding API: there is no implicit reference to the global entropy sources within the RNGs anymore. The entropy sources must be supplied with the API call. Adds support for reseding directly from another RNG (such as a system or hardware RNG). Stateful_RNG keeps optional references to both an RNG and a set of entropy sources. During a reseed, both sources are used if set. These can be provided to HMAC_DRBG constructor. For HMAC_DRBG, SP800-90A requires we output no more than 2**16 bytes per DRBG request. We treat requests longer than that as if the caller had instead made several sequential maximum-length requests. This means it is possible for one or more reseeds to trigger even in the course of generating a single (long) output (generate a 256-bit key and use ChaCha or HKDF if this is a problem). Adds RNG::randomize_with_ts_input which takes timestamps and uses them as the additional_data DRBG field. Stateful_RNG overrides this to also include the process ID and the reseed counter. AutoSeeded_RNG's `randomize` uses this. Officially deprecates RNG::make_rng and the Serialized_RNG construtor which creates an AutoSeeded_RNG. With these removed, it would be possible to perform a build with no AutoSeeded_RNG/HMAC_DRBG at all (eg, for applications which only use the system RNG). Tests courtesy @cordney in GH PRs #598 and #600
Diffstat (limited to 'src/lib/rng/rng.h')
-rw-r--r--src/lib/rng/rng.h137
1 files changed, 45 insertions, 92 deletions
diff --git a/src/lib/rng/rng.h b/src/lib/rng/rng.h
index 7da560b85..d1cdcfff2 100644
--- a/src/lib/rng/rng.h
+++ b/src/lib/rng/rng.h
@@ -8,6 +8,7 @@
#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>
@@ -19,7 +20,7 @@ namespace Botan {
class Entropy_Sources;
/**
-* An interface to a generic RNG
+* An interface to a cryptographic random number generator
*/
class BOTAN_DLL RandomNumberGenerator
{
@@ -45,6 +46,8 @@ class BOTAN_DLL RandomNumberGenerator
* Incorporate some additional data into the RNG state. For
* example adding nonces or timestamps from a peer's protocol
* message can help hedge against VM state rollback attacks.
+ * A few RNG types do not accept any externally provided input,
+ * in which case this function is a no-op.
*
* @param inputs a byte array containg the entropy to be added
* @param length the length of the byte array in
@@ -56,27 +59,41 @@ class BOTAN_DLL RandomNumberGenerator
*/
template<typename T> void add_entropy_T(const T& t)
{
- add_entropy(reinterpret_cast<const uint8_t*>(&t), sizeof(T));
+ this->add_entropy(reinterpret_cast<const uint8_t*>(&t), sizeof(T));
}
/**
- * Incorporate entropy into the RNG state then produce output
- * Some RNG types implement this using a single operation.
+ * Incorporate entropy into the RNG state then produce output.
+ * Some RNG types implement this using a single operation, default
+ * calls add_entropy + randomize in sequence.
+ *
+ * Use this to further bind the outputs to your current
+ * process/protocol state. For instance if generating a new key
+ * for use in a session, include a session ID or other such
+ * value. See NIST SP 800-90 A, B, C series for more ideas.
*/
virtual void randomize_with_input(byte output[], size_t output_len,
- const byte input[], size_t input_len)
- {
- this->add_entropy(input, input_len);
- this->randomize(output, output_len);
- }
+ const byte input[], size_t input_len);
+
+ /**
+ * This calls `randomize_with_input` using some timestamps as extra input.
+ *
+ * For a stateful RNG using non-random but potentially unique data as the
+ * additional_input can help protect against problems with fork, VM state
+ * rollback, or other cases where somehow an RNG state is duplicated. If
+ * both of the duplicated RNG states later incorporate a timestamp (and the
+ * timestamps don't themselves repeat), their outputs will diverge.
+ */
+ virtual void randomize_with_ts_input(byte output[], size_t output_len);
/**
- * Return the name of this object
+ * Return the name of this RNG type
*/
virtual std::string name() const = 0;
/**
- * Clear all internally held values of this RNG.
+ * Clear all internally held values of this RNG
+ * @post is_seeded() == false
*/
virtual void clear() = 0;
@@ -91,28 +108,17 @@ class BOTAN_DLL RandomNumberGenerator
* 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);
+ virtual size_t reseed(Entropy_Sources& srcs,
+ size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
+ std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_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
- * @param poll_timeout try not to run longer than this, even if
- * not enough entropy has been collected
+ * Reseed by reading specified bits from the RNG
*/
- size_t reseed(size_t bits_to_collect = BOTAN_RNG_RESEED_POLL_BITS);
+ virtual void reseed_from_rng(RandomNumberGenerator& rng,
+ size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS);
- /**
- * 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, even if
- * not enough entropy has been collected
- */
- size_t reseed_with_timeout(size_t bits_to_collect,
- std::chrono::milliseconds poll_timeout);
+ // Some utility functions built on the interface above:
/**
* Return a random vector
@@ -122,7 +128,7 @@ class BOTAN_DLL RandomNumberGenerator
secure_vector<byte> random_vec(size_t bytes)
{
secure_vector<byte> output(bytes);
- randomize(output.data(), output.size());
+ this->randomize(output.data(), output.size());
return output;
}
@@ -139,9 +145,9 @@ class BOTAN_DLL RandomNumberGenerator
byte next_nonzero_byte()
{
- byte b = next_byte();
+ byte b = this->next_byte();
while(b == 0)
- b = next_byte();
+ b = this->next_byte();
return b;
}
@@ -150,65 +156,11 @@ class BOTAN_DLL RandomNumberGenerator
* Added in 1.8.0
* Use AutoSeeded_RNG instead
*/
+ BOTAN_DEPRECATED("Use AutoSeeded_RNG")
static RandomNumberGenerator* make_rng();
};
/**
-* 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 a 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);
-
- void clear() override;
-
- /**
- * Mark state as requiring a reseed on next use
- */
- void force_reseed() { m_bytes_since_reseed = m_max_output_before_reseed; }
-
- uint32_t last_pid() const { return m_last_pid; }
-
- mutable std::mutex m_mutex;
-
- private:
- const size_t m_max_output_before_reseed;
- size_t m_bytes_since_reseed = 0;
- uint32_t m_last_pid = 0;
- bool m_successful_initialization = false;
- };
-
-/**
* Convenience typedef
*/
typedef RandomNumberGenerator RNG;
@@ -271,12 +223,12 @@ class BOTAN_DLL Serialized_RNG final : public RandomNumberGenerator
return m_rng->name();
}
- size_t reseed_with_sources(Entropy_Sources& src,
- size_t bits,
- std::chrono::milliseconds msec) override
+ size_t reseed(Entropy_Sources& src,
+ size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
+ std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override
{
std::lock_guard<std::mutex> lock(m_mutex);
- return m_rng->reseed_with_sources(src, bits, msec);
+ return m_rng->reseed(src, poll_bits, poll_timeout);
}
void add_entropy(const byte in[], size_t len) override
@@ -285,7 +237,8 @@ class BOTAN_DLL Serialized_RNG final : public RandomNumberGenerator
m_rng->add_entropy(in, len);
}
- Serialized_RNG() : m_rng(RandomNumberGenerator::make_rng()) {}
+ BOTAN_DEPRECATED("Create an AutoSeeded_RNG for other constructor") Serialized_RNG();
+
explicit Serialized_RNG(RandomNumberGenerator* rng) : m_rng(rng) {}
private:
mutable std::mutex m_mutex;