Botan 2.19.5 Crypto and TLS for C&

stateful_rng.cpp
Go to the documentation of this file.
1/*
2* (C) 2016,2020 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#include <botan/stateful_rng.h>
8#include <botan/internal/os_utils.h>
9#include <botan/loadstor.h>
10
11#if defined(BOTAN_HAS_SYSTEM_RNG)
12 #include <botan/system_rng.h>
13#endif
14
15 namespace Botan {
16
17 void Stateful_RNG::clear()
18 {
19 lock_guard_type<recursive_mutex_type> lock(m_mutex);
20 m_reseed_counter = 0;
21 m_last_pid = 0;
22 clear_state();
23 }
24
25 void Stateful_RNG::force_reseed()
26 {
27 lock_guard_type<recursive_mutex_type> lock(m_mutex);
28 m_reseed_counter = 0;
29 }
30
31 bool Stateful_RNG::is_seeded() const
32 {
33 lock_guard_type<recursive_mutex_type> lock(m_mutex);
34 return m_reseed_counter > 0;
35 }
36
37 void Stateful_RNG::add_entropy(const uint8_t input[], size_t input_len)
38 {
39 lock_guard_type<recursive_mutex_type> lock(m_mutex);
40
41 update(input, input_len);
42
43 if(8*input_len >= security_level())
44 {
45 reset_reseed_counter();
46 }
47 }
48
49 void Stateful_RNG::initialize_with(const uint8_t input[], size_t len)
50 {
51 lock_guard_type<recursive_mutex_type> lock(m_mutex);
52
53 clear();
54 add_entropy(input, len);
55 }
56
57 void Stateful_RNG::randomize(uint8_t output[], size_t output_len)
58 {
59 randomize_with_input(output, output_len, nullptr, 0);
60 }
61
62 void Stateful_RNG::randomize_with_ts_input(uint8_t output[], size_t output_len)
63 {
64 uint8_t additional_input[20] = { 0 };
65
66 store_le(OS::get_high_resolution_clock(), additional_input);
67
68#if defined(BOTAN_HAS_SYSTEM_RNG)
69 System_RNG system_rng;
70 system_rng.randomize(additional_input + 8, sizeof(additional_input) - 8);
71#else
72 store_le(OS::get_system_timestamp_ns(), additional_input + 8);
73 store_le(OS::get_process_id(), additional_input + 16);
74#endif
75
76 randomize_with_input(output, output_len, additional_input, sizeof(additional_input));
77 }
78
79 void Stateful_RNG::randomize_with_input(uint8_t output[], size_t output_len,
80 const uint8_t input[], size_t input_len)
81 {
82 if(output_len == 0)
83 return;
84
85 lock_guard_type<recursive_mutex_type> lock(m_mutex);
86
87 const size_t max_per_request = max_number_of_bytes_per_request();
88
89 if(max_per_request == 0) // no limit
90 {
91 reseed_check();
92 this->generate_output(output, output_len, input, input_len);
93 }
94 else
95 {
96 while(output_len > 0)
97 {
98 const size_t this_req = std::min(max_per_request, output_len);
99
100 /*
101 * We split the request into several requests to the underlying DRBG but
102 * pass the input to each invocation. It might be more sensible to only
103 * provide it for the first invocation, however between 2.0 and 2.15
104 * HMAC_DRBG always provided it for all requests so retain that here.
105 */
106
107 reseed_check();
108 this->generate_output(output, this_req, input, input_len);
109
110 output += this_req;
111 output_len -= this_req;
112 }
113 }
114 }
115
116 size_t Stateful_RNG::reseed(Entropy_Sources& srcs,
117 size_t poll_bits,
118 std::chrono::milliseconds poll_timeout)
119 {
120 lock_guard_type<recursive_mutex_type> lock(m_mutex);
121
122 const size_t bits_collected = RandomNumberGenerator::reseed(srcs, poll_bits, poll_timeout);
123
124 if(bits_collected >= security_level())
125 {
126 reset_reseed_counter();
127 }
128
129 return bits_collected;
130 }
131
132 void Stateful_RNG::reseed_from_rng(RandomNumberGenerator& rng, size_t poll_bits)
133 {
134 lock_guard_type<recursive_mutex_type> lock(m_mutex);
135
136 RandomNumberGenerator::reseed_from_rng(rng, poll_bits);
137
138 if(poll_bits >= security_level())
139 {
140 reset_reseed_counter();
141 }
142 }
143
144 void Stateful_RNG::reset_reseed_counter()
145 {
146 // Lock is held whenever this function is called
147 m_reseed_counter = 1;
148 }
149
150 void Stateful_RNG::reseed_check()
151 {
152 // Lock is held whenever this function is called
153
154 const uint32_t cur_pid = OS::get_process_id();
155
156 const bool fork_detected = (m_last_pid > 0) && (cur_pid != m_last_pid);
157
158 if(is_seeded() == false ||
159 fork_detected ||
160 (m_reseed_interval > 0 && m_reseed_counter >= m_reseed_interval))
161 {
162 m_reseed_counter = 0;
163 m_last_pid = cur_pid;
164
165 if(m_underlying_rng)
166 {
167 reseed_from_rng(*m_underlying_rng, security_level());
168 }
169
170 if(m_entropy_sources)
171 {
172 reseed(*m_entropy_sources, security_level());
173 }
174
175 if(!is_seeded())
176 {
177 if(fork_detected)
178 throw Invalid_State("Detected use of fork but cannot reseed DRBG");
179 else
180 throw PRNG_Unseeded(name());
181 }
182 }
183 else
184 {
185 BOTAN_ASSERT(m_reseed_counter != 0, "RNG is seeded");
186 m_reseed_counter += 1;
187 }
188 }
189
190}
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
Botan::Entropy_Sources
Definition: entropy_src.h:57
Botan::Invalid_State
Definition: exceptn.h:216
Botan::PRNG_Unseeded
Definition: exceptn.h:227
Botan::RandomNumberGenerator
Definition: rng.h:26
Botan::RandomNumberGenerator::reseed_from_rng
virtual void reseed_from_rng(RandomNumberGenerator &rng, size_t poll_bits=BOTAN_RNG_RESEED_POLL_BITS)
Definition: rng.cpp:59
Botan::RandomNumberGenerator::randomize
virtual void randomize(uint8_t output[], size_t length)=0
Botan::RandomNumberGenerator::name
virtual std::string name() const =0
Botan::RandomNumberGenerator::reseed
virtual size_t reseed(Entropy_Sources &srcs, size_t poll_bits=BOTAN_RNG_RESEED_POLL_BITS, std::chrono::milliseconds poll_timeout=BOTAN_RNG_RESEED_DEFAULT_TIMEOUT)
Definition: rng.cpp:45
Botan::Stateful_RNG::randomize_with_ts_input
void randomize_with_ts_input(uint8_t output[], size_t output_len) override final
Definition: stateful_rng.cpp:62
Botan::Stateful_RNG::reseed_check
void reseed_check()
Definition: stateful_rng.cpp:150
Botan::Stateful_RNG::generate_output
virtual void generate_output(uint8_t output[], size_t output_len, const uint8_t input[], size_t input_len)=0
Botan::Stateful_RNG::force_reseed
void force_reseed()
Definition: stateful_rng.cpp:25
Botan::Stateful_RNG::security_level
virtual size_t security_level() const =0
Botan::Stateful_RNG::clear_state
virtual void clear_state()=0
Botan::Stateful_RNG::reseed
size_t reseed(Entropy_Sources &srcs, size_t poll_bits=BOTAN_RNG_RESEED_POLL_BITS, std::chrono::milliseconds poll_timeout=BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override
Definition: stateful_rng.cpp:116
Botan::Stateful_RNG::initialize_with
void initialize_with(const uint8_t input[], size_t length)
Definition: stateful_rng.cpp:49
Botan::Stateful_RNG::update
virtual void update(const uint8_t input[], size_t input_len)=0
Botan::Stateful_RNG::is_seeded
bool is_seeded() const override final
Definition: stateful_rng.cpp:31
Botan::Stateful_RNG::randomize_with_input
void randomize_with_input(uint8_t output[], size_t output_len, const uint8_t input[], size_t input_len) override final
Definition: stateful_rng.cpp:79
Botan::Stateful_RNG::max_number_of_bytes_per_request
virtual size_t max_number_of_bytes_per_request() const =0
Botan::Stateful_RNG::clear
void clear() override final
Definition: stateful_rng.cpp:17
Botan::Stateful_RNG::randomize
void randomize(uint8_t output[], size_t output_len) override final
Definition: stateful_rng.cpp:57
Botan::Stateful_RNG::reseed_from_rng
void reseed_from_rng(RandomNumberGenerator &rng, size_t poll_bits=BOTAN_RNG_RESEED_POLL_BITS) override final
Definition: stateful_rng.cpp:132
Botan::Stateful_RNG::add_entropy
void add_entropy(const uint8_t input[], size_t input_len) override final
Definition: stateful_rng.cpp:37
Botan::System_RNG
Definition: system_rng.h:26
Botan::lock_guard
Definition: mutex.h:32
Botan::OS::get_high_resolution_clock
uint64_t BOTAN_TEST_API get_high_resolution_clock()
Definition: os_utils.cpp:241
Botan::OS::get_system_timestamp_ns
uint64_t BOTAN_TEST_API get_system_timestamp_ns()
Definition: os_utils.cpp:293
Botan::OS::get_process_id
uint32_t BOTAN_TEST_API get_process_id()
Definition: os_utils.cpp:96
Botan
Definition: alg_id.cpp:13
Botan::system_rng
RandomNumberGenerator & system_rng()
Definition: system_rng.cpp:283
Botan::store_le
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:454