Coverage Report

Created: 2025-07-11 06:15

/src/Botan-3.4.0/build/include/public/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
*     2023                René Meusel - Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H_
10
#define BOTAN_RANDOM_NUMBER_GENERATOR_H_
11
12
#include <botan/concepts.h>
13
#include <botan/exceptn.h>
14
#include <botan/mutex.h>
15
#include <botan/secmem.h>
16
17
#include <chrono>
18
#include <concepts>
19
#include <span>
20
#include <string>
21
#include <type_traits>
22
23
namespace Botan {
24
25
class Entropy_Sources;
26
27
/**
28
* An interface to a cryptographic random number generator
29
*/
30
class BOTAN_PUBLIC_API(2, 0) RandomNumberGenerator {
31
   public:
32
358k
      virtual ~RandomNumberGenerator() = default;
33
34
358k
      RandomNumberGenerator() = default;
35
36
      /*
37
      * Never copy a RNG, create a new one
38
      */
39
      RandomNumberGenerator(const RandomNumberGenerator& rng) = delete;
40
      RandomNumberGenerator& operator=(const RandomNumberGenerator& rng) = delete;
41
42
      /**
43
      * Randomize a byte array.
44
      *
45
      * May block shortly if e.g. the RNG is not yet initialized
46
      * or a retry because of insufficient entropy is needed.
47
      *
48
      * @param output the byte array to hold the random output.
49
      * @throws PRNG_Unseeded if the RNG fails because it has not enough entropy
50
      * @throws Exception if the RNG fails
51
      */
52
179k
      void randomize(std::span<uint8_t> output) { this->fill_bytes_with_input(output, {}); }
53
54
0
      void randomize(uint8_t output[], size_t length) { this->randomize(std::span(output, length)); }
55
56
      /**
57
      * Returns false if it is known that this RNG object is not able to accept
58
      * externally provided inputs (via add_entropy, randomize_with_input, etc).
59
      * In this case, any such provided inputs are ignored.
60
      *
61
      * If this function returns true, then inputs may or may not be accepted.
62
      */
63
      virtual bool accepts_input() const = 0;
64
65
      /**
66
      * Incorporate some additional data into the RNG state. For
67
      * example adding nonces or timestamps from a peer's protocol
68
      * message can help hedge against VM state rollback attacks.
69
      * A few RNG types do not accept any externally provided input,
70
      * in which case this function is a no-op.
71
      *
72
      * @param input a byte array containing the entropy to be added
73
      * @throws Exception may throw if the RNG accepts input, but adding the entropy failed.
74
      */
75
179k
      void add_entropy(std::span<const uint8_t> input) { this->fill_bytes_with_input({}, input); }
76
77
0
      void add_entropy(const uint8_t input[], size_t length) { this->add_entropy(std::span(input, length)); }
78
79
      /**
80
      * Incorporate some additional data into the RNG state.
81
      */
82
      template <typename T>
83
         requires std::is_standard_layout<T>::value && std::is_trivial<T>::value
84
      void add_entropy_T(const T& t) {
85
         this->add_entropy(reinterpret_cast<const uint8_t*>(&t), sizeof(T));
86
      }
87
88
      /**
89
      * Incorporate entropy into the RNG state then produce output.
90
      * Some RNG types implement this using a single operation, default
91
      * calls add_entropy + randomize in sequence.
92
      *
93
      * Use this to further bind the outputs to your current
94
      * process/protocol state. For instance if generating a new key
95
      * for use in a session, include a session ID or other such
96
      * value. See NIST SP 800-90 A, B, C series for more ideas.
97
      *
98
      * @param output buffer to hold the random output
99
      * @param input entropy buffer to incorporate
100
      * @throws PRNG_Unseeded if the RNG fails because it has not enough entropy
101
      * @throws Exception if the RNG fails
102
      * @throws Exception may throw if the RNG accepts input, but adding the entropy failed.
103
      */
104
0
      void randomize_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) {
105
0
         this->fill_bytes_with_input(output, input);
106
0
      }
107
108
0
      void randomize_with_input(uint8_t output[], size_t output_len, const uint8_t input[], size_t input_len) {
109
0
         this->randomize_with_input(std::span(output, output_len), std::span(input, input_len));
110
0
      }
111
112
      /**
113
      * This calls `randomize_with_input` using some timestamps as extra input.
114
      *
115
      * For a stateful RNG using non-random but potentially unique data the
116
      * extra input can help protect against problems with fork, VM state
117
      * rollback, or other cases where somehow an RNG state is duplicated. If
118
      * both of the duplicated RNG states later incorporate a timestamp (and the
119
      * timestamps don't themselves repeat), their outputs will diverge.
120
      *
121
      * @param output buffer to hold the random output
122
      * @throws PRNG_Unseeded if the RNG fails because it has not enough entropy
123
      * @throws Exception if the RNG fails
124
      * @throws Exception may throw if the RNG accepts input, but adding the entropy failed.
125
      */
126
      void randomize_with_ts_input(std::span<uint8_t> output);
127
128
0
      void randomize_with_ts_input(uint8_t output[], size_t output_len) {
129
0
         this->randomize_with_ts_input(std::span(output, output_len));
130
0
      }
131
132
      /**
133
      * @return the name of this RNG type
134
      */
135
      virtual std::string name() const = 0;
136
137
      /**
138
      * Clear all internally held values of this RNG
139
      * @post is_seeded() == false if the RNG has an internal state that can be cleared.
140
      */
141
      virtual void clear() = 0;
142
143
      /**
144
      * Check whether this RNG is seeded.
145
      * @return true if this RNG was already seeded, false otherwise.
146
      */
147
      virtual bool is_seeded() const = 0;
148
149
      /**
150
      * Poll provided sources for up to poll_bits bits of entropy
151
      * or until the timeout expires. Returns estimate of the number
152
      * of bits collected.
153
      *
154
      * Sets the seeded state to true if enough entropy was added.
155
      */
156
      virtual size_t reseed(Entropy_Sources& srcs,
157
                            size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
158
                            std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT);
159
160
      /**
161
      * Reseed by reading specified bits from the RNG
162
      *
163
      * Sets the seeded state to true if enough entropy was added.
164
      *
165
      * @throws Exception if RNG accepts input but reseeding failed.
166
      */
167
      virtual void reseed_from_rng(RandomNumberGenerator& rng, size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS);
168
169
      // Some utility functions built on the interface above:
170
171
      /**
172
      * Fill a given byte container with @p bytes random bytes
173
      *
174
      * @todo deprecate this overload (in favor of randomize())
175
      *
176
      * @param  v     the container to be filled with @p bytes random bytes
177
      * @throws Exception if RNG fails
178
      */
179
179k
      void random_vec(std::span<uint8_t> v) { this->randomize(v); }
180
181
      /**
182
      * Resize a given byte container to @p bytes and fill it with random bytes
183
      *
184
      * @tparam T     the desired byte container type (e.g std::vector<uint8_t>)
185
      * @param  v     the container to be filled with @p bytes random bytes
186
      * @param  bytes number of random bytes to initialize the container with
187
      * @throws Exception if RNG or memory allocation fails
188
      */
189
      template <concepts::resizable_byte_buffer T>
190
179k
      void random_vec(T& v, size_t bytes) {
191
179k
         v.resize(bytes);
192
179k
         random_vec(v);
193
179k
      }
_ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS_16secure_allocatorIhEEEEEEvRT_m
Line
Count
Source
190
179k
      void random_vec(T& v, size_t bytes) {
191
179k
         v.resize(bytes);
192
179k
         random_vec(v);
193
179k
      }
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS3_9allocatorIhEEEEEEvRT_m
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENS_6StrongINSt3__16vectorIhNS_16secure_allocatorIhEEEENS_18SphincsSecretSeed_EJEEEEEvRT_m
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENS_6StrongINSt3__16vectorIhNS_16secure_allocatorIhEEEENS_17SphincsSecretPRF_EJEEEEEvRT_m
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENS_6StrongINSt3__16vectorIhNS4_9allocatorIhEEEENS_18SphincsPublicSeed_EJEEEEEvRT_m
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENS_6StrongINSt3__16vectorIhNS_16secure_allocatorIhEEEENS_26SphincsOptionalRandomness_EJEEEEEvRT_m
194
195
      /**
196
      * Create some byte container type and fill it with some random @p bytes.
197
      *
198
      * @tparam T     the desired byte container type (e.g std::vector<uint8_t>)
199
      * @param  bytes number of random bytes to initialize the container with
200
      * @return       a container of type T with @p bytes random bytes
201
      * @throws Exception if RNG or memory allocation fails
202
      */
203
      template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>>
204
         requires std::default_initializable<T>
205
179k
      T random_vec(size_t bytes) {
206
179k
         T result;
207
179k
         random_vec(result, bytes);
208
179k
         return result;
209
179k
      }
_ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS_16secure_allocatorIhEEEEQsr3stdE21default_initializableIT_EEES8_m
Line
Count
Source
205
179k
      T random_vec(size_t bytes) {
206
179k
         T result;
207
179k
         random_vec(result, bytes);
208
179k
         return result;
209
179k
      }
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS3_9allocatorIhEEEEQsr3stdE21default_initializableIT_EEES8_m
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENS_6StrongINSt3__16vectorIhNS_16secure_allocatorIhEEEENS_18SphincsSecretSeed_EJEEEQsr3stdE21default_initializableIT_EEESB_m
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENS_6StrongINSt3__16vectorIhNS_16secure_allocatorIhEEEENS_17SphincsSecretPRF_EJEEEQsr3stdE21default_initializableIT_EEESB_m
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENS_6StrongINSt3__16vectorIhNS4_9allocatorIhEEEENS_18SphincsPublicSeed_EJEEEQsr3stdE21default_initializableIT_EEESB_m
Unexecuted instantiation: _ZN5Botan21RandomNumberGenerator10random_vecITkNS_8concepts21resizable_byte_bufferENS_6StrongINSt3__16vectorIhNS_16secure_allocatorIhEEEENS_26SphincsOptionalRandomness_EJEEEQsr3stdE21default_initializableIT_EEESB_m
210
211
      /**
212
      * Return a random byte
213
      * @return random byte
214
      * @throws PRNG_Unseeded if the RNG fails because it has not enough entropy
215
      * @throws Exception if the RNG fails
216
      */
217
179k
      uint8_t next_byte() {
218
179k
         uint8_t b;
219
179k
         this->fill_bytes_with_input(std::span(&b, 1), {});
220
179k
         return b;
221
179k
      }
222
223
      /**
224
      * @return a random byte that is greater than zero
225
      * @throws PRNG_Unseeded if the RNG fails because it has not enough entropy
226
      * @throws Exception if the RNG fails
227
      */
228
0
      uint8_t next_nonzero_byte() {
229
0
         uint8_t b = this->next_byte();
230
0
         while(b == 0) {
231
0
            b = this->next_byte();
232
0
         }
233
0
         return b;
234
0
      }
235
236
   protected:
237
      /**
238
      * Generic interface to provide entropy to a concrete implementation and to
239
      * fill a given buffer with random output. Both @p output and @p input may
240
      * be empty and should be ignored in that case. If both buffers are
241
      * non-empty implementations should typically first apply the @p input data
242
      * and then generate random data into @p output.
243
      *
244
      * This method must be implemented by all RandomNumberGenerator sub-classes.
245
      *
246
      * @param output  Byte buffer to write random bytes into. Implementations
247
      *                should not read from this buffer.
248
      * @param input   Byte buffer that may contain bytes to be incorporated in
249
      *                the RNG's internal state. Implementations may choose to
250
      *                ignore the bytes in this buffer.
251
      */
252
      virtual void fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) = 0;
253
};
254
255
/**
256
* Convenience typedef
257
*/
258
typedef RandomNumberGenerator RNG;
259
260
/**
261
* Hardware_RNG exists to tag hardware RNG types (PKCS11_RNG, TPM_RNG, Processor_RNG)
262
*/
263
class BOTAN_PUBLIC_API(2, 0) Hardware_RNG : public RandomNumberGenerator {
264
   public:
265
0
      void clear() final { /* no way to clear state of hardware RNG */
266
0
      }
267
};
268
269
/**
270
* Null/stub RNG - fails if you try to use it for anything
271
* This is not generally useful except for in certain tests
272
*/
273
class BOTAN_PUBLIC_API(2, 0) Null_RNG final : public RandomNumberGenerator {
274
   public:
275
0
      bool is_seeded() const override { return false; }
276
277
0
      bool accepts_input() const override { return false; }
278
279
0
      void clear() override {}
280
281
0
      std::string name() const override { return "Null_RNG"; }
282
283
   private:
284
      void fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> /* ignored */) override;
285
};
286
287
}  // namespace Botan
288
289
#endif