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