Botan 3.13.0
Crypto and TLS for C&
stateful_rng.h
Go to the documentation of this file.
1/*
2* (C) 2016 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_STATEFUL_RNG_H_
8#define BOTAN_STATEFUL_RNG_H_
9
10#include <botan/mutex.h>
11#include <botan/rng.h>
12
13namespace Botan {
14
15/**
16* Inherited by RNGs which maintain in-process state, like HMAC_DRBG.
17* On Unix these RNGs are vulnerable to problems with fork, where the
18* RNG state is duplicated, and the parent and child process RNGs will
19* produce identical output until one of them reseeds. Stateful_RNG
20* reseeds itself whenever a fork is detected, or after a set number of
21* bytes have been output.
22*
23* Not implemented by RNGs which access an external RNG, such as the
24* system PRNG or a hardware RNG.
25*/
27 public:
28 /**
29 * Create a Stateful_RNG which reseeds from both an RNG and entropy sources
30 *
31 * @param rng is a reference to some RNG which will be used
32 * to perform the periodic reseeding
33 * @param entropy_sources will be polled to perform reseeding periodically
34 * @param reseed_interval specifies a limit of how many times
35 * the RNG will be called before automatic reseeding is performed
36 */
38 m_underlying_rng(&rng), m_entropy_sources(&entropy_sources), m_reseed_interval(reseed_interval) {}
39
40 /**
41 * Create a Stateful_RNG which reseeds from another RNG
42 *
43 * @param rng is a reference to some RNG which will be used
44 * to perform the periodic reseeding
45 * @param reseed_interval specifies a limit of how many times
46 * the RNG will be called before automatic reseeding is performed
47 */
49 m_underlying_rng(&rng), m_reseed_interval(reseed_interval) {}
50
51 /**
52 * Create a Stateful_RNG which reseeds from entropy sources
53 *
54 * @param entropy_sources will be polled to perform reseeding periodically
55 * @param reseed_interval specifies a limit of how many times
56 * the RNG will be called before automatic reseeding is performed
57 */
58 Stateful_RNG(Entropy_Sources& entropy_sources, size_t reseed_interval) :
59 m_entropy_sources(&entropy_sources), m_reseed_interval(reseed_interval) {}
60
61 /**
62 * In this case, automatic reseeding is impossible
63 */
64 Stateful_RNG() : m_reseed_interval(0) {}
65
66 /**
67 * Consume this input and mark the RNG as initialized regardless
68 * of the length of the input or the current seeded state of
69 * the RNG.
70 */
71 void initialize_with(std::span<const uint8_t> input);
72
73 /**
74 * Consume this input and mark the RNG as initialized regardless
75 * of the length of the input or the current seeded state of the RNG.
76 * @param input the seed material
77 * @param length the number of bytes in input
78 */
79 void initialize_with(const uint8_t input[], size_t length) { this->initialize_with(std::span(input, length)); }
80
81 /**
82 * Test whether this RNG has been seeded
83 * @return true if this RNG is seeded and ready for use
84 */
85 bool is_seeded() const final;
86
87 /**
88 * Test whether this RNG accepts externally provided input
89 * @return false if this RNG is known to ignore provided inputs
90 */
91 bool accepts_input() const final { return true; }
92
93 /**
94 * Mark state as requiring a reseed on next use
95 */
96 void force_reseed();
97
98 /**
99 * Reseed this RNG from another RNG
100 * @param rng the RNG to draw seed material from
101 * @param poll_bits the number of bits to collect
102 */
103 void reseed_from_rng(RandomNumberGenerator& rng, size_t poll_bits = RandomNumberGenerator::DefaultPollBits) final;
104
105 /**
106 * Poll provided sources for up to poll_bits bits of entropy.
107 * Returns estimate of the number of bits collected.
108 */
109 size_t reseed_from_sources(Entropy_Sources& srcs,
110 size_t poll_bits = RandomNumberGenerator::DefaultPollBits) final;
111
112 /**
113 * Return the security level of this DRBG
114 * @return intended security level of this DRBG
115 */
116 virtual size_t security_level() const = 0;
117
118 /**
119 * Return the largest number of bytes this DRBG will produce per request
120 * Some DRBGs have a notion of the maximum number of bytes per
121 * request. Longer requests (to randomize) will be treated as
122 * multiple requests, and may initiate reseeding multiple times,
123 * depending on the values of max_number_of_bytes_per_request and
124 * reseed_interval(). This function returns zero if the RNG in
125 * question does not have such a notion.
126 *
127 * @return max number of bytes per request (or zero)
128 */
129 virtual size_t max_number_of_bytes_per_request() const = 0;
130
131 /**
132 * Return how many requests may be made before automatic reseeding
133 * @return the reseed interval, or zero if automatic reseeding is disabled
134 */
135 size_t reseed_interval() const { return m_reseed_interval; }
136
137 /**
138 * Clear all internally held values of this RNG
139 */
140 void clear() final;
141
142 protected:
143 /**
144 * Reseed if the reseed interval has elapsed, or throw if unseeded
145 */
146 void reseed_check();
147
148 /**
149 * Generate output, incorporating the provided input
150 * @param output the buffer to fill
151 * @param input additional input to incorporate
152 */
153 virtual void generate_output(std::span<uint8_t> output, std::span<const uint8_t> input) = 0;
154
155 /**
156 * Incorporate the provided input into the RNG state
157 * @param input the seed material
158 */
159 virtual void update(std::span<const uint8_t> input) = 0;
160
161 /**
162 * Clear the subclass specific portion of the RNG state
163 */
164 virtual void clear_state() = 0;
165
166 private:
167 void generate_batched_output(std::span<uint8_t> output, std::span<const uint8_t> input);
168
169 void fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) final;
170
171 void reset_reseed_counter();
172
173 mutable recursive_mutex_type m_mutex;
174
175 // A non-owned and possibly null pointer to shared RNG
176 RandomNumberGenerator* m_underlying_rng = nullptr;
177
178 // A non-owned and possibly null pointer to a shared Entropy_Source
179 Entropy_Sources* m_entropy_sources = nullptr;
180
181 const size_t m_reseed_interval;
182 uint32_t m_last_pid = 0;
183
184 /*
185 * Set to 1 after a successful seeding, then incremented. Reset
186 * to 0 by clear() or a fork. This logic is used even if
187 * automatic reseeding is disabled (via m_reseed_interval = 0)
188 */
189 size_t m_reseed_counter = 0;
190};
191
192} // namespace Botan
193
194#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
static constexpr size_t DefaultPollBits
Definition rng.h:50
size_t reseed_interval() const
virtual size_t security_level() const =0
virtual void clear_state()=0
Stateful_RNG(RandomNumberGenerator &rng, size_t reseed_interval)
Stateful_RNG(RandomNumberGenerator &rng, Entropy_Sources &entropy_sources, size_t reseed_interval)
void initialize_with(const uint8_t input[], size_t length)
virtual void generate_output(std::span< uint8_t > output, std::span< const uint8_t > input)=0
Stateful_RNG(Entropy_Sources &entropy_sources, size_t reseed_interval)
bool accepts_input() const final
virtual size_t max_number_of_bytes_per_request() const =0
virtual void update(std::span< const uint8_t > input)=0
noop_mutex recursive_mutex_type
Definition mutex.h:41