2
* Random Number Generator base classes
3
* (C) 1999-2009,2015,2016 Jack Lloyd
5
* Botan is released under the Simplified BSD License (see license.txt)
8
#ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H_
9
#define BOTAN_RANDOM_NUMBER_GENERATOR_H_
11
#include <botan/secmem.h>
12
#include <botan/exceptn.h>
13
#include <botan/mutex.h>
19
class Entropy_Sources;
22
* An interface to a cryptographic random number generator
24
class BOTAN_PUBLIC_API(2,0) RandomNumberGenerator
27
virtual ~RandomNumberGenerator() = default;
29
RandomNumberGenerator() = default;
32
* Never copy a RNG, create a new one
34
RandomNumberGenerator(const RandomNumberGenerator& rng) = delete;
35
RandomNumberGenerator& operator=(const RandomNumberGenerator& rng) = delete;
38
* Randomize a byte array.
39
* @param output the byte array to hold the random output.
40
* @param length the length of the byte array output in bytes.
42
virtual void randomize(uint8_t output[], size_t length) = 0;
45
* Incorporate some additional data into the RNG state. For
46
* example adding nonces or timestamps from a peer's protocol
47
* message can help hedge against VM state rollback attacks.
48
* A few RNG types do not accept any externally provided input,
49
* in which case this function is a no-op.
51
* @param input a byte array containg the entropy to be added
52
* @param length the length of the byte array in
54
virtual void add_entropy(const uint8_t input[], size_t length) = 0;
57
* Incorporate some additional data into the RNG state.
59
template<typename T> void add_entropy_T(const T& t)
61
this->add_entropy(reinterpret_cast<const uint8_t*>(&t), sizeof(T));
65
* Incorporate entropy into the RNG state then produce output.
66
* Some RNG types implement this using a single operation, default
67
* calls add_entropy + randomize in sequence.
69
* Use this to further bind the outputs to your current
70
* process/protocol state. For instance if generating a new key
71
* for use in a session, include a session ID or other such
72
* value. See NIST SP 800-90 A, B, C series for more ideas.
74
* @param output buffer to hold the random output
75
* @param output_len size of the output buffer in bytes
76
* @param input entropy buffer to incorporate
77
* @param input_len size of the input buffer in bytes
79
virtual void randomize_with_input(uint8_t output[], size_t output_len,
80
const uint8_t input[], size_t input_len);
83
* This calls `randomize_with_input` using some timestamps as extra input.
85
* For a stateful RNG using non-random but potentially unique data the
86
* extra input can help protect against problems with fork, VM state
87
* rollback, or other cases where somehow an RNG state is duplicated. If
88
* both of the duplicated RNG states later incorporate a timestamp (and the
89
* timestamps don't themselves repeat), their outputs will diverge.
91
virtual void randomize_with_ts_input(uint8_t output[], size_t output_len);
94
* @return the name of this RNG type
96
virtual std::string name() const = 0;
99
* Clear all internally held values of this RNG
100
* @post is_seeded() == false
102
virtual void clear() = 0;
105
* Check whether this RNG is seeded.
106
* @return true if this RNG was already seeded, false otherwise.
108
virtual bool is_seeded() const = 0;
111
* Poll provided sources for up to poll_bits bits of entropy
112
* or until the timeout expires. Returns estimate of the number
115
virtual size_t reseed(Entropy_Sources& srcs,
116
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
117
std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT);
120
* Reseed by reading specified bits from the RNG
122
virtual void reseed_from_rng(RandomNumberGenerator& rng,
123
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS);
125
// Some utility functions built on the interface above:
128
* Return a random vector
129
* @param bytes number of bytes in the result
130
* @return randomized vector of length bytes
132
secure_vector<uint8_t> random_vec(size_t bytes)
134
secure_vector<uint8_t> output(bytes);
135
this->randomize(output.data(), output.size());
140
* Return a random byte
141
* @return random byte
146
this->randomize(&b, 1);
151
* @return a random byte that is greater than zero
153
uint8_t next_nonzero_byte()
155
uint8_t b = this->next_byte();
157
b = this->next_byte();
162
* Create a seeded and active RNG object for general application use
164
* Use AutoSeeded_RNG instead
166
BOTAN_DEPRECATED("Use AutoSeeded_RNG")
167
static RandomNumberGenerator* make_rng();
171
* Convenience typedef
173
typedef RandomNumberGenerator RNG;
176
* Hardware_RNG has no members but exists to tag hardware RNG types
177
* (PKCS11_RNG, TPM_RNG, RDRAND_RNG)
179
class BOTAN_PUBLIC_API(2,0) Hardware_RNG : public RandomNumberGenerator
182
virtual void clear() final override { /* no way to clear state of hardware RNG */ }
186
* Null/stub RNG - fails if you try to use it for anything
187
* This is not generally useful except for in certain tests
189
class BOTAN_PUBLIC_API(2,0) Null_RNG final : public RandomNumberGenerator
192
bool is_seeded() const override { return false; }
194
void clear() override {}
196
void randomize(uint8_t[], size_t) override
198
throw PRNG_Unseeded("Null_RNG called");
201
void add_entropy(const uint8_t[], size_t) override {}
203
std::string name() const override { return "Null_RNG"; }
206
#if defined(BOTAN_TARGET_OS_HAS_THREADS)
208
* Wraps access to a RNG in a mutex
209
* Note that most of the time it's much better to use a RNG per thread
210
* otherwise the RNG will act as an unnecessary contention point
212
class BOTAN_PUBLIC_API(2,0) Serialized_RNG final : public RandomNumberGenerator
215
void randomize(uint8_t out[], size_t len) override
217
lock_guard_type<mutex_type> lock(m_mutex);
218
m_rng->randomize(out, len);
221
bool is_seeded() const override
223
lock_guard_type<mutex_type> lock(m_mutex);
224
return m_rng->is_seeded();
227
void clear() override
229
lock_guard_type<mutex_type> lock(m_mutex);
233
std::string name() const override
235
lock_guard_type<mutex_type> lock(m_mutex);
236
return m_rng->name();
239
size_t reseed(Entropy_Sources& src,
240
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
241
std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override
243
lock_guard_type<mutex_type> lock(m_mutex);
244
return m_rng->reseed(src, poll_bits, poll_timeout);
247
void add_entropy(const uint8_t in[], size_t len) override
249
lock_guard_type<mutex_type> lock(m_mutex);
250
m_rng->add_entropy(in, len);
253
BOTAN_DEPRECATED("Use Serialized_RNG(new AutoSeeded_RNG)") Serialized_RNG();
255
explicit Serialized_RNG(RandomNumberGenerator* rng) : m_rng(rng) {}
257
mutable mutex_type m_mutex;
258
std::unique_ptr<RandomNumberGenerator> m_rng;