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