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