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