Coverage Report

Created: 2020-10-17 06:46

/src/botan/build/include/botan/rng.h
Line
Count
Source (jump to first uncovered line)
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
*/
25
class BOTAN_PUBLIC_API(2,0) RandomNumberGenerator
26
   {
27
   public:
28
429
      virtual ~RandomNumberGenerator() = default;
29
30
429
      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_pod<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
      */
143
      secure_vector<uint8_t> random_vec(size_t bytes)
144
502k
         {
145
502k
         secure_vector<uint8_t> output;
146
502k
         random_vec(output, bytes);
147
502k
         return output;
148
502k
         }
149
150
      template<typename Alloc>
151
         void random_vec(std::vector<uint8_t, Alloc>& v, size_t bytes)
152
504k
         {
153
504k
         v.resize(bytes);
154
504k
         this->randomize(v.data(), v.size());
155
504k
         }
void Botan::RandomNumberGenerator::random_vec<Botan::secure_allocator<unsigned char> >(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >&, unsigned long)
Line
Count
Source
152
503k
         {
153
503k
         v.resize(bytes);
154
503k
         this->randomize(v.data(), v.size());
155
503k
         }
void Botan::RandomNumberGenerator::random_vec<std::__1::allocator<unsigned char> >(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, unsigned long)
Line
Count
Source
152
624
         {
153
624
         v.resize(bytes);
154
624
         this->randomize(v.data(), v.size());
155
624
         }
156
157
      /**
158
      * Return a random byte
159
      * @return random byte
160
      */
161
      uint8_t next_byte()
162
25
         {
163
25
         uint8_t b;
164
25
         this->randomize(&b, 1);
165
25
         return b;
166
25
         }
167
168
      /**
169
      * @return a random byte that is greater than zero
170
      */
171
      uint8_t next_nonzero_byte()
172
24
         {
173
24
         uint8_t b = this->next_byte();
174
25
         while(b == 0)
175
1
            b = this->next_byte();
176
24
         return b;
177
24
         }
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
*/
191
typedef RandomNumberGenerator RNG;
192
193
/**
194
* Hardware_RNG exists to tag hardware RNG types (PKCS11_RNG, TPM_RNG, Processor_RNG)
195
*/
196
class BOTAN_PUBLIC_API(2,0) Hardware_RNG : public RandomNumberGenerator
197
   {
198
   public:
199
0
      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
*/
206
class BOTAN_PUBLIC_API(2,0) Null_RNG final : public RandomNumberGenerator
207
   {
208
   public:
209
0
      bool is_seeded() const override { return false; }
210
211
0
      bool accepts_input() const override { return false; }
212
213
0
      void clear() override {}
214
215
      void randomize(uint8_t[], size_t) override
216
0
         {
217
0
         throw PRNG_Unseeded("Null_RNG called");
218
0
         }
219
220
0
      void add_entropy(const uint8_t[], size_t) override {}
221
222
0
      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
0
         {
240
0
         lock_guard_type<mutex_type> lock(m_mutex);
241
0
         m_rng->randomize(out, len);
242
0
         }
243
244
      bool accepts_input() const override
245
0
         {
246
0
         lock_guard_type<mutex_type> lock(m_mutex);
247
0
         return m_rng->accepts_input();
248
0
         }
249
250
      bool is_seeded() const override
251
0
         {
252
0
         lock_guard_type<mutex_type> lock(m_mutex);
253
0
         return m_rng->is_seeded();
254
0
         }
255
256
      void clear() override
257
0
         {
258
0
         lock_guard_type<mutex_type> lock(m_mutex);
259
0
         m_rng->clear();
260
0
         }
261
262
      std::string name() const override
263
0
         {
264
0
         lock_guard_type<mutex_type> lock(m_mutex);
265
0
         return m_rng->name();
266
0
         }
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
0
         {
272
0
         lock_guard_type<mutex_type> lock(m_mutex);
273
0
         return m_rng->reseed(src, poll_bits, poll_timeout);
274
0
         }
275
276
      void add_entropy(const uint8_t in[], size_t len) override
277
0
         {
278
0
         lock_guard_type<mutex_type> lock(m_mutex);
279
0
         m_rng->add_entropy(in, len);
280
0
         }
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
0
      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