Botan 3.9.0
Crypto and TLS for C&
entropy_srcs.cpp
Go to the documentation of this file.
1/*
2* Entropy Source Polling
3* (C) 2008-2010,2015 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/entropy_src.h>
9
10#include <botan/assert.h>
11#include <botan/rng.h>
12#include <botan/internal/target_info.h>
13
14#if defined(BOTAN_HAS_SYSTEM_RNG)
15 #include <botan/system_rng.h>
16#endif
17
18#if defined(BOTAN_HAS_PROCESSOR_RNG)
19 #include <botan/processor_rng.h>
20#endif
21
22#if defined(BOTAN_HAS_ENTROPY_SRC_RDSEED)
23 #include <botan/internal/rdseed.h>
24#endif
25
26#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
27 #include <botan/internal/es_win32.h>
28#endif
29
30#if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY)
31 #include <botan/internal/getentropy.h>
32#endif
33
34#if defined(BOTAN_HAS_JITTER_RNG)
35 #include <botan/jitter_rng.h>
36#endif
37
38namespace Botan {
39
40namespace {
41
42#if defined(BOTAN_HAS_SYSTEM_RNG)
43
44class System_RNG_EntropySource final : public Entropy_Source {
45 public:
46 size_t poll(RandomNumberGenerator& rng) override {
47 const size_t poll_bits = RandomNumberGenerator::DefaultPollBits;
48 rng.reseed_from_rng(system_rng(), poll_bits);
49 return poll_bits;
50 }
51
52 std::string name() const override { return "system_rng"; }
53};
54
55#endif
56
57#if defined(BOTAN_HAS_PROCESSOR_RNG)
58
59class Processor_RNG_EntropySource final : public Entropy_Source {
60 public:
61 size_t poll(RandomNumberGenerator& rng) override {
62 /*
63 * Intel's documentation for RDRAND at
64 * https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
65 * claims that software can guarantee a reseed event by polling enough data:
66 * "There is an upper bound of 511 samples per seed in the implementation
67 * where samples are 128 bits in size and can provide two 64-bit random
68 * numbers each."
69 *
70 * By requesting 65536 bits we are asking for 512 samples and thus are assured
71 * that at some point in producing the output, at least one reseed of the
72 * internal state will occur.
73 *
74 * The reseeding conditions of the POWER and ARM processor RNGs are not known
75 * but probably work in a somewhat similar manner. The exact amount requested
76 * may be tweaked if and when such conditions become publically known.
77 */
78 const size_t poll_bits = 65536;
79 rng.reseed_from_rng(m_hwrng, poll_bits);
80 // Avoid trusting a black box, don't count this as contributing entropy:
81 return 0;
82 }
83
84 std::string name() const override { return m_hwrng.name(); }
85
86 private:
87 Processor_RNG m_hwrng;
88};
89
90#endif
91
92#if defined(BOTAN_HAS_JITTER_RNG)
93
94class Jitter_RNG_EntropySource final : public Entropy_Source {
95 public:
96 size_t poll(RandomNumberGenerator& rng) override {
97 rng.reseed_from_rng(m_rng);
98 return RandomNumberGenerator::DefaultPollBits;
99 }
100
101 std::string name() const override { return m_rng.name(); }
102
103 private:
104 Jitter_RNG m_rng;
105};
106
107#endif
108
109} // namespace
110
111std::unique_ptr<Entropy_Source> Entropy_Source::create(std::string_view name) {
112#if defined(BOTAN_HAS_SYSTEM_RNG)
113 if(name == "system_rng") {
114 return std::make_unique<System_RNG_EntropySource>();
115 }
116#endif
117
118#if defined(BOTAN_HAS_PROCESSOR_RNG)
119 if(name == "hwrng") {
121 return std::make_unique<Processor_RNG_EntropySource>();
122 }
123 }
124#endif
125
126#if defined(BOTAN_HAS_ENTROPY_SRC_RDSEED)
127 if(name == "rdseed") {
128 return std::make_unique<Intel_Rdseed>();
129 }
130#endif
131
132#if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY)
133 if(name == "getentropy") {
134 return std::make_unique<Getentropy>();
135 }
136#endif
137
138#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
139 if(name == "system_stats") {
140 return std::make_unique<Win32_EntropySource>();
141 }
142#endif
143
144#if defined(BOTAN_HAS_JITTER_RNG)
145 if(name == "jitter_rng") {
146 return std::make_unique<Jitter_RNG_EntropySource>();
147 }
148#endif
149
151 return nullptr;
152}
153
154void Entropy_Sources::add_source(std::unique_ptr<Entropy_Source> src) {
155 if(src) {
156 m_srcs.push_back(std::move(src));
157 }
158}
159
160std::vector<std::string> Entropy_Sources::enabled_sources() const {
161 std::vector<std::string> sources;
162 sources.reserve(m_srcs.size());
163 for(const auto& src : m_srcs) {
164 sources.push_back(src->name());
165 }
166 return sources;
167}
168
169size_t Entropy_Sources::poll(RandomNumberGenerator& rng, size_t poll_bits, std::chrono::milliseconds timeout) {
170#if defined(BOTAN_TARGET_OS_HAS_SYSTEM_CLOCK)
171 typedef std::chrono::system_clock clock;
172 auto timeout_expired = [to = clock::now() + timeout] { return clock::now() > to; };
173#else
174 auto timeout_expired = [] { return false; };
175#endif
176
177 size_t bits_collected = 0;
178
179 for(auto& src : m_srcs) {
180 bits_collected += src->poll(rng);
181
182 if(bits_collected >= poll_bits || timeout_expired()) {
183 break;
184 }
185 }
186
187 return bits_collected;
188}
189
190size_t Entropy_Sources::poll_just(RandomNumberGenerator& rng, std::string_view the_src) {
191 for(auto& src : m_srcs) {
192 if(src->name() == the_src) {
193 return src->poll(rng);
194 }
195 }
196
197 return 0;
198}
199
200Entropy_Sources::Entropy_Sources(const std::vector<std::string>& sources) {
201 for(auto&& src_name : sources) {
203 }
204}
205
207 static Entropy_Sources global_entropy_sources({"rdseed", "hwrng", "getentropy", "system_rng", "system_stats"});
208
209 return global_entropy_sources;
210}
211
212} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:144
virtual std::string name() const =0
static std::unique_ptr< Entropy_Source > create(std::string_view type)
static Entropy_Sources & global_sources()
size_t poll_just(RandomNumberGenerator &rng, std::string_view src)
void add_source(std::unique_ptr< Entropy_Source > src)
size_t poll(RandomNumberGenerator &rng, size_t bits, std::chrono::milliseconds timeout)
std::vector< std::string > enabled_sources() const
RandomNumberGenerator & system_rng()