Botan 2.19.3
Crypto and TLS for C&
rng.h
Go to the documentation of this file.
1/*
2* Random Number Generator base classes
3* (C) 1999-2009,2015,2016 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H_
9#define BOTAN_RANDOM_NUMBER_GENERATOR_H_
10
11#include <botan/secmem.h>
12#include <botan/exceptn.h>
13#include <botan/mutex.h>
14#include <type_traits>
15#include <chrono>
16#include <string>
17
18namespace Botan {
19
20class Entropy_Sources;
21
22/**
23* An interface to a cryptographic random number generator
24*/
26 {
27 public:
28 virtual ~RandomNumberGenerator() = default;
29
31
32 /*
33 * Never copy a RNG, create a new one
34 */
37
38 /**
39 * Randomize a byte array.
40 * @param output the byte array to hold the random output.
41 * @param length the length of the byte array output in bytes.
42 */
43 virtual void randomize(uint8_t output[], size_t length) = 0;
44
45 /**
46 * Returns false if it is known that this RNG object is not able to accept
47 * externally provided inputs (via add_entropy, randomize_with_input, etc).
48 * In this case, any such provided inputs are ignored.
49 *
50 * If this function returns true, then inputs may or may not be accepted.
51 */
52 virtual bool accepts_input() const = 0;
53
54 /**
55 * Incorporate some additional data into the RNG state. For
56 * example adding nonces or timestamps from a peer's protocol
57 * message can help hedge against VM state rollback attacks.
58 * A few RNG types do not accept any externally provided input,
59 * in which case this function is a no-op.
60 *
61 * @param input a byte array containg the entropy to be added
62 * @param length the length of the byte array in
63 */
64 virtual void add_entropy(const uint8_t input[], size_t length) = 0;
65
66 /**
67 * Incorporate some additional data into the RNG state.
68 */
69 template<typename T> void add_entropy_T(const T& t)
70 {
71 static_assert(std::is_standard_layout<T>::value && std::is_trivial<T>::value, "add_entropy_T data must be POD");
72 this->add_entropy(reinterpret_cast<const uint8_t*>(&t), sizeof(T));
73 }
74
75 /**
76 * Incorporate entropy into the RNG state then produce output.
77 * Some RNG types implement this using a single operation, default
78 * calls add_entropy + randomize in sequence.
79 *
80 * Use this to further bind the outputs to your current
81 * process/protocol state. For instance if generating a new key
82 * for use in a session, include a session ID or other such
83 * value. See NIST SP 800-90 A, B, C series for more ideas.
84 *
85 * @param output buffer to hold the random output
86 * @param output_len size of the output buffer in bytes
87 * @param input entropy buffer to incorporate
88 * @param input_len size of the input buffer in bytes
89 */
90 virtual void randomize_with_input(uint8_t output[], size_t output_len,
91 const uint8_t input[], size_t input_len);
92
93 /**
94 * This calls `randomize_with_input` using some timestamps as extra input.
95 *
96 * For a stateful RNG using non-random but potentially unique data the
97 * extra input can help protect against problems with fork, VM state
98 * rollback, or other cases where somehow an RNG state is duplicated. If
99 * both of the duplicated RNG states later incorporate a timestamp (and the
100 * timestamps don't themselves repeat), their outputs will diverge.
101 */
102 virtual void randomize_with_ts_input(uint8_t output[], size_t output_len);
103
104 /**
105 * @return the name of this RNG type
106 */
107 virtual std::string name() const = 0;
108
109 /**
110 * Clear all internally held values of this RNG
111 * @post is_seeded() == false
112 */
113 virtual void clear() = 0;
114
115 /**
116 * Check whether this RNG is seeded.
117 * @return true if this RNG was already seeded, false otherwise.
118 */
119 virtual bool is_seeded() const = 0;
120
121 /**
122 * Poll provided sources for up to poll_bits bits of entropy
123 * or until the timeout expires. Returns estimate of the number
124 * of bits collected.
125 */
126 virtual size_t reseed(Entropy_Sources& srcs,
127 size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
128 std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT);
129
130 /**
131 * Reseed by reading specified bits from the RNG
132 */
133 virtual void reseed_from_rng(RandomNumberGenerator& rng,
134 size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS);
135
136 // Some utility functions built on the interface above:
137
138 /**
139 * Return a random vector
140 * @param bytes number of bytes in the result
141 * @return randomized vector of length bytes
142 */
144 {
146 random_vec(output, bytes);
147 return output;
148 }
149
150 template<typename Alloc>
151 void random_vec(std::vector<uint8_t, Alloc>& v, size_t bytes)
152 {
153 v.resize(bytes);
154 this->randomize(v.data(), v.size());
155 }
156
157 /**
158 * Return a random byte
159 * @return random byte
160 */
161 uint8_t next_byte()
162 {
163 uint8_t b;
164 this->randomize(&b, 1);
165 return b;
166 }
167
168 /**
169 * @return a random byte that is greater than zero
170 */
172 {
173 uint8_t b = this->next_byte();
174 while(b == 0)
175 b = this->next_byte();
176 return b;
177 }
178
179 /**
180 * Create a seeded and active RNG object for general application use
181 * Added in 1.8.0
182 * Use AutoSeeded_RNG instead
183 */
184 BOTAN_DEPRECATED("Use AutoSeeded_RNG")
185 static RandomNumberGenerator* make_rng();
186 };
187
188/**
189* Convenience typedef
190*/
192
193/**
194* Hardware_RNG exists to tag hardware RNG types (PKCS11_RNG, TPM_RNG, Processor_RNG)
195*/
197 {
198 public:
199 virtual void clear() final override { /* no way to clear state of hardware RNG */ }
200 };
201
202/**
203* Null/stub RNG - fails if you try to use it for anything
204* This is not generally useful except for in certain tests
205*/
207 {
208 public:
209 bool is_seeded() const override { return false; }
210
211 bool accepts_input() const override { return false; }
212
213 void clear() override {}
214
215 void randomize(uint8_t[], size_t) override
216 {
217 throw PRNG_Unseeded("Null_RNG called");
218 }
219
220 void add_entropy(const uint8_t[], size_t) override {}
221
222 std::string name() const override { return "Null_RNG"; }
223 };
224
225#if defined(BOTAN_TARGET_OS_HAS_THREADS)
226/**
227* Wraps access to a RNG in a mutex
228* Note that most of the time it's much better to use a RNG per thread
229* otherwise the RNG will act as an unnecessary contention point
230*
231* Since 2.16.0 all Stateful_RNG instances have an internal lock, so
232* this class is no longer needed. It will be removed in a future major
233* release.
234*/
235class BOTAN_PUBLIC_API(2,0) Serialized_RNG final : public RandomNumberGenerator
236 {
237 public:
238 void randomize(uint8_t out[], size_t len) override
239 {
240 lock_guard_type<mutex_type> lock(m_mutex);
241 m_rng->randomize(out, len);
242 }
243
244 bool accepts_input() const override
245 {
246 lock_guard_type<mutex_type> lock(m_mutex);
247 return m_rng->accepts_input();
248 }
249
250 bool is_seeded() const override
251 {
252 lock_guard_type<mutex_type> lock(m_mutex);
253 return m_rng->is_seeded();
254 }
255
256 void clear() override
257 {
258 lock_guard_type<mutex_type> lock(m_mutex);
259 m_rng->clear();
260 }
261
262 std::string name() const override
263 {
264 lock_guard_type<mutex_type> lock(m_mutex);
265 return m_rng->name();
266 }
267
268 size_t reseed(Entropy_Sources& src,
269 size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
270 std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override
271 {
272 lock_guard_type<mutex_type> lock(m_mutex);
273 return m_rng->reseed(src, poll_bits, poll_timeout);
274 }
275
276 void add_entropy(const uint8_t in[], size_t len) override
277 {
278 lock_guard_type<mutex_type> lock(m_mutex);
279 m_rng->add_entropy(in, len);
280 }
281
282 BOTAN_DEPRECATED("Use Serialized_RNG(new AutoSeeded_RNG) instead") Serialized_RNG();
283
284 /*
285 * Since 2.16.0 this is no longer needed for any RNG type. This
286 * class will be removed in a future major release.
287 */
288 explicit Serialized_RNG(RandomNumberGenerator* rng) : m_rng(rng) {}
289 private:
290 mutable mutex_type m_mutex;
291 std::unique_ptr<RandomNumberGenerator> m_rng;
292 };
293#endif
294
295}
296
297#endif
virtual void clear() final override
Definition rng.h:199
bool accepts_input() const override
Definition rng.h:211
void add_entropy(const uint8_t[], size_t) override
Definition rng.h:220
void clear() override
Definition rng.h:213
void randomize(uint8_t[], size_t) override
Definition rng.h:215
std::string name() const override
Definition rng.h:222
bool is_seeded() const override
Definition rng.h:209
virtual bool accepts_input() const =0
virtual ~RandomNumberGenerator()=default
uint8_t next_nonzero_byte()
Definition rng.h:171
RandomNumberGenerator & operator=(const RandomNumberGenerator &rng)=delete
virtual bool is_seeded() const =0
void add_entropy_T(const T &t)
Definition rng.h:69
virtual void randomize(uint8_t output[], size_t length)=0
virtual std::string name() const =0
secure_vector< uint8_t > random_vec(size_t bytes)
Definition rng.h:143
RandomNumberGenerator(const RandomNumberGenerator &rng)=delete
void random_vec(std::vector< uint8_t, Alloc > &v, size_t bytes)
Definition rng.h:151
virtual void add_entropy(const uint8_t input[], size_t length)=0
std::string name
int(* final)(unsigned char *, CTX *)
#define BOTAN_PUBLIC_API(maj, min)
Definition compiler.h:31
fe T
Definition ge.cpp:37
noop_mutex mutex_type
Definition mutex.h:52
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:65