Botan  1.10.9
global_rng.cpp
Go to the documentation of this file.
1 /*
2 * Global PRNG
3 * (C) 2008-2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/libstate.h>
9 #include <botan/internal/mutex.h>
10 
11 #if defined(BOTAN_HAS_RANDPOOL)
12  #include <botan/randpool.h>
13 #endif
14 
15 #if defined(BOTAN_HAS_HMAC_RNG)
16  #include <botan/hmac_rng.h>
17 #endif
18 
19 #if defined(BOTAN_HAS_X931_RNG)
20  #include <botan/x931_rng.h>
21 #endif
22 
23 #if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER)
24  #include <botan/internal/hres_timer.h>
25 #endif
26 
27 #if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND)
28  #include <botan/internal/rdrand.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_EGD)
36  #include <botan/internal/es_egd.h>
37 #endif
38 
39 #if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
40  #include <botan/internal/es_unix.h>
41 #endif
42 
43 #if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
44  #include <botan/internal/es_beos.h>
45 #endif
46 
47 #if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
48  #include <botan/internal/es_capi.h>
49 #endif
50 
51 #if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
52  #include <botan/internal/es_win32.h>
53 #endif
54 
55 #if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
56  #include <botan/internal/es_ftw.h>
57 #endif
58 
59 namespace Botan {
60 
61 namespace {
62 
63 /**
64 * Add any known entropy sources to this RNG
65 */
66 void add_entropy_sources(RandomNumberGenerator* rng)
67  {
68 #if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER)
69  rng->add_entropy_source(new High_Resolution_Timestamp);
70 #endif
71 
72 #if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND)
73  rng->add_entropy_source(new Intel_Rdrand);
74 #endif
75 
76 #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM)
77  rng->add_entropy_source(
78  new Device_EntropySource(
79  split_on("/dev/urandom:/dev/srandom:/dev/random", ':')
80  )
81  );
82 #endif
83 
84 #if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
85  rng->add_entropy_source(
86  new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':'))
87  );
88 #endif
89 
90 #if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
91  rng->add_entropy_source(new Win32_CAPI_EntropySource);
92 #endif
93 
94 #if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
95  rng->add_entropy_source(new FTW_EntropySource("/proc"));
96 #endif
97 
98 #if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
99  rng->add_entropy_source(new Win32_EntropySource);
100 #endif
101 
102 #if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
103  rng->add_entropy_source(new BeOS_EntropySource);
104 #endif
105 
106 #if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
107  rng->add_entropy_source(
108  new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':'))
109  );
110 #endif
111  }
112 
113 class Serialized_PRNG : public RandomNumberGenerator
114  {
115  public:
116  void randomize(byte out[], size_t len)
117  {
118  Mutex_Holder lock(mutex);
119  rng->randomize(out, len);
120  }
121 
122  bool is_seeded() const
123  {
124  Mutex_Holder lock(mutex);
125  return rng->is_seeded();
126  }
127 
128  void clear()
129  {
130  Mutex_Holder lock(mutex);
131  rng->clear();
132  }
133 
134  std::string name() const
135  {
136  Mutex_Holder lock(mutex);
137  return rng->name();
138  }
139 
140  void reseed(size_t poll_bits)
141  {
142  Mutex_Holder lock(mutex);
143  rng->reseed(poll_bits);
144  }
145 
146  void add_entropy_source(EntropySource* es)
147  {
148  Mutex_Holder lock(mutex);
149  rng->add_entropy_source(es);
150  }
151 
152  void add_entropy(const byte in[], size_t len)
153  {
154  Mutex_Holder lock(mutex);
155  rng->add_entropy(in, len);
156  }
157 
158  // We do not own the mutex; Library_State does
159  Serialized_PRNG(RandomNumberGenerator* r, Mutex* m) :
160  mutex(m), rng(r) {}
161 
162  ~Serialized_PRNG() { delete rng; }
163  private:
164  Mutex* mutex;
165  RandomNumberGenerator* rng;
166  };
167 
168 }
169 
170 RandomNumberGenerator* Library_State::make_global_rng(Algorithm_Factory& af,
171  Mutex* mutex)
172  {
173  RandomNumberGenerator* rng = 0;
174 
175 #if defined(BOTAN_HAS_HMAC_RNG)
176 
177  rng = new HMAC_RNG(af.make_mac("HMAC(SHA-512)"),
178  af.make_mac("HMAC(SHA-256)"));
179 
180 #elif defined(BOTAN_HAS_RANDPOOL)
181 
182  rng = new Randpool(af.make_block_cipher("AES-256"),
183  af.make_mac("HMAC(SHA-256)"));
184 
185 #endif
186 
187  if(!rng)
188  throw Internal_Error("No usable RNG found enabled in build");
189 
190  /* If X9.31 is available, use it to wrap the other RNG as a failsafe */
191 #if defined(BOTAN_HAS_X931_RNG)
192 
193  rng = new ANSI_X931_RNG(af.make_block_cipher("AES-256"), rng);
194 
195 #endif
196 
197  add_entropy_sources(rng);
198 
199  rng->reseed(256);
200 
201  return new Serialized_PRNG(rng, mutex);
202  }
203 
204 }
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:152
Mutex * mutex
Definition: global_rng.cpp:164
unsigned char byte
Definition: types.h:22
RandomNumberGenerator * rng
Definition: global_rng.cpp:165
BigInt r
Definition: numthry.cpp:26