Coverage Report

Created: 2025-12-14 07:05

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