Botan  2.19.1
Crypto and TLS for C++11
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 
48 namespace Botan {
49 
50 namespace {
51 
52 #if defined(BOTAN_HAS_SYSTEM_RNG)
53 
54 class 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 
71 class 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 
107 std::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 
163  BOTAN_UNUSED(name);
164  return std::unique_ptr<Entropy_Source>();
165  }
166 
167 void 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 
175 std::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 
206 size_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 
219 Entropy_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 
RandomNumberGenerator & system_rng()
Definition: system_rng.cpp:283
int(* final)(unsigned char *, CTX *)
std::vector< std::string > enabled_sources() const
size_t poll_just(RandomNumberGenerator &rng, const std::string &src)
bool running_in_privileged_state()
Definition: os_utils.cpp:143
std::string name
Definition: alg_id.cpp:13
#define BOTAN_UNUSED(...)
Definition: assert.h:142
static bool available()
void add_source(std::unique_ptr< Entropy_Source > src)
static std::unique_ptr< Entropy_Source > create(const std::string &type)
static Entropy_Sources & global_sources()
size_t poll(RandomNumberGenerator &rng, size_t bits, std::chrono::milliseconds timeout)