Botan 3.4.0
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
9#include <botan/internal/loadstor.h>
10#include <botan/internal/os_utils.h>
11
12namespace Botan {
13
16 m_reseed_counter = 0;
17 m_last_pid = 0;
19}
20
23 m_reseed_counter = 0;
24}
25
28 return m_reseed_counter > 0;
29}
30
31void Stateful_RNG::initialize_with(std::span<const uint8_t> input) {
33
34 clear();
35 add_entropy(input);
36}
37
38void Stateful_RNG::generate_batched_output(std::span<uint8_t> output, std::span<const uint8_t> input) {
39 BOTAN_ASSERT_NOMSG(!output.empty());
40
41 const size_t max_per_request = max_number_of_bytes_per_request();
42
43 if(max_per_request == 0) // no limit
44 {
46 this->generate_output(output, input);
47 } else {
48 while(!output.empty()) {
49 const size_t this_req = std::min(max_per_request, output.size());
50
52 this->generate_output(output.subspan(0, this_req), input);
53
54 // only include the input for the first iteration
55 input = {};
56
57 output = output.subspan(this_req);
58 }
59 }
60}
61
62void Stateful_RNG::fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) {
63 lock_guard_type<recursive_mutex_type> lock(m_mutex);
64
65 if(output.empty()) {
66 // Special case for exclusively adding entropy to the stateful RNG.
67 this->update(input);
68
69 if(8 * input.size() >= security_level()) {
70 reset_reseed_counter();
71 }
72 } else {
73 generate_batched_output(output, input);
74 }
75}
76
77size_t Stateful_RNG::reseed(Entropy_Sources& srcs, size_t poll_bits, std::chrono::milliseconds poll_timeout) {
79
80 const size_t bits_collected = RandomNumberGenerator::reseed(srcs, poll_bits, poll_timeout);
81
82 if(bits_collected >= security_level()) {
83 reset_reseed_counter();
84 }
85
86 return bits_collected;
87}
88
91
93
94 if(poll_bits >= security_level()) {
95 reset_reseed_counter();
96 }
97}
98
99void Stateful_RNG::reset_reseed_counter() {
100 // Lock is held whenever this function is called
101 m_reseed_counter = 1;
102}
103
105 // Lock is held whenever this function is called
106
107 const uint32_t cur_pid = OS::get_process_id();
108
109 const bool fork_detected = (m_last_pid > 0) && (cur_pid != m_last_pid);
110
111 if(is_seeded() == false || fork_detected || (m_reseed_interval > 0 && m_reseed_counter >= m_reseed_interval)) {
112 m_reseed_counter = 0;
113 m_last_pid = cur_pid;
114
115 if(m_underlying_rng) {
116 reseed_from_rng(*m_underlying_rng, security_level());
117 }
118
119 if(m_entropy_sources) {
120 reseed(*m_entropy_sources, security_level());
121 }
122
123 if(!is_seeded()) {
124 if(fork_detected) {
125 throw Invalid_State("Detected use of fork but cannot reseed DRBG");
126 } else {
127 throw PRNG_Unseeded(name());
128 }
129 }
130 } else {
131 BOTAN_ASSERT(m_reseed_counter != 0, "RNG is seeded");
132 m_reseed_counter += 1;
133 }
134}
135
136} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
void add_entropy(std::span< const uint8_t > input)
Definition rng.h:75
virtual void reseed_from_rng(RandomNumberGenerator &rng, size_t poll_bits=BOTAN_RNG_RESEED_POLL_BITS)
Definition rng.cpp:57
virtual std::string name() const =0
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:49
bool is_seeded() const final
virtual size_t security_level() const =0
virtual void clear_state()=0
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
virtual void generate_output(std::span< uint8_t > output, std::span< const uint8_t > input)=0
virtual size_t max_number_of_bytes_per_request() const =0
void reseed_from_rng(RandomNumberGenerator &rng, size_t poll_bits=BOTAN_RNG_RESEED_POLL_BITS) final
void initialize_with(std::span< const uint8_t > input)
int(* update)(CTX *, const void *, CC_LONG len)
uint32_t BOTAN_TEST_API get_process_id()
Definition os_utils.cpp:116
secure_vector< T > lock(const std::vector< T > &in)
Definition secmem.h:70