Botan  2.18.1
Crypto and TLS for C++11
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 
18 namespace Botan {
19 
20 class Entropy_Sources;
21 
22 /**
23 * An interface to a cryptographic random number generator
24 */
26  {
27  public:
28  virtual ~RandomNumberGenerator() = default;
29 
30  RandomNumberGenerator() = default;
31 
32  /*
33  * Never copy a RNG, create a new one
34  */
35  RandomNumberGenerator(const RandomNumberGenerator& rng) = delete;
36  RandomNumberGenerator& operator=(const RandomNumberGenerator& rng) = delete;
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  {
145  secure_vector<uint8_t> output;
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 */
235 class 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
void add_entropy(const uint8_t[], size_t) override
Definition: rng.h:220
secure_vector< uint8_t > random_vec(size_t bytes)
Definition: rng.h:143
noop_mutex mutex_type
Definition: mutex.h:52
int(* final)(unsigned char *, CTX *)
#define BOTAN_PUBLIC_API(maj, min)
Definition: compiler.h:31
std::string name() const override
Definition: rng.h:222
void randomize(uint8_t[], size_t) override
Definition: rng.h:215
virtual void clear() final override
Definition: rng.h:199
std::string name
uint8_t next_nonzero_byte()
Definition: rng.h:171
void add_entropy_T(const T &t)
Definition: rng.h:69
bool is_seeded() const override
Definition: rng.h:209
Definition: alg_id.cpp:13
void clear() override
Definition: rng.h:213
void random_vec(std::vector< uint8_t, Alloc > &v, size_t bytes)
Definition: rng.h:151
fe T
Definition: ge.cpp:37
bool accepts_input() const override
Definition: rng.h:211
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65