Coverage Report

Created: 2020-02-14 15:38

/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 <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
*/
24
class BOTAN_PUBLIC_API(2,0) RandomNumberGenerator
25
   {
26
   public:
27
630
      virtual ~RandomNumberGenerator() = default;
28
29
630
      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
      */
141
      secure_vector<uint8_t> random_vec(size_t bytes)
142
486k
         {
143
486k
         secure_vector<uint8_t> output;
144
486k
         random_vec(output, bytes);
145
486k
         return output;
146
486k
         }
147
148
      template<typename Alloc>
149
         void random_vec(std::vector<uint8_t, Alloc>& v, size_t bytes)
150
488k
         {
151
488k
         v.resize(bytes);
152
488k
         this->randomize(v.data(), v.size());
153
488k
         }
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
150
488k
         {
151
488k
         v.resize(bytes);
152
488k
         this->randomize(v.data(), v.size());
153
488k
         }
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
150
492
         {
151
492
         v.resize(bytes);
152
492
         this->randomize(v.data(), v.size());
153
492
         }
154
155
      /**
156
      * Return a random byte
157
      * @return random byte
158
      */
159
      uint8_t next_byte()
160
22
         {
161
22
         uint8_t b;
162
22
         this->randomize(&b, 1);
163
22
         return b;
164
22
         }
165
166
      /**
167
      * @return a random byte that is greater than zero
168
      */
169
      uint8_t next_nonzero_byte()
170
21
         {
171
21
         uint8_t b = this->next_byte();
172
22
         while(b == 0)
173
1
            b = this->next_byte();
174
21
         return b;
175
21
         }
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
*/
189
typedef RandomNumberGenerator RNG;
190
191
/**
192
* Hardware_RNG exists to tag hardware RNG types (PKCS11_RNG, TPM_RNG, RDRAND_RNG)
193
*/
194
class BOTAN_PUBLIC_API(2,0) Hardware_RNG : public RandomNumberGenerator
195
   {
196
   public:
197
0
      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
*/
204
class BOTAN_PUBLIC_API(2,0) Null_RNG final : public RandomNumberGenerator
205
   {
206
   public:
207
0
      bool is_seeded() const override { return false; }
208
209
0
      bool accepts_input() const override { return false; }
210
211
0
      void clear() override {}
212
213
      void randomize(uint8_t[], size_t) override
214
0
         {
215
0
         throw PRNG_Unseeded("Null_RNG called");
216
0
         }
217
218
0
      void add_entropy(const uint8_t[], size_t) override {}
219
220
0
      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
0
         {
234
0
         lock_guard_type<mutex_type> lock(m_mutex);
235
0
         m_rng->randomize(out, len);
236
0
         }
237
238
      bool accepts_input() const override
239
0
         {
240
0
         lock_guard_type<mutex_type> lock(m_mutex);
241
0
         return m_rng->accepts_input();
242
0
         }
243
244
      bool is_seeded() const override
245
0
         {
246
0
         lock_guard_type<mutex_type> lock(m_mutex);
247
0
         return m_rng->is_seeded();
248
0
         }
249
250
      void clear() override
251
0
         {
252
0
         lock_guard_type<mutex_type> lock(m_mutex);
253
0
         m_rng->clear();
254
0
         }
255
256
      std::string name() const override
257
0
         {
258
0
         lock_guard_type<mutex_type> lock(m_mutex);
259
0
         return m_rng->name();
260
0
         }
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
0
         {
266
0
         lock_guard_type<mutex_type> lock(m_mutex);
267
0
         return m_rng->reseed(src, poll_bits, poll_timeout);
268
0
         }
269
270
      void add_entropy(const uint8_t in[], size_t len) override
271
0
         {
272
0
         lock_guard_type<mutex_type> lock(m_mutex);
273
0
         m_rng->add_entropy(in, len);
274
0
         }
275
276
      BOTAN_DEPRECATED("Use Serialized_RNG(new AutoSeeded_RNG)") Serialized_RNG();
277
278
0
      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