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 */
add_entropy_sources(RandomNumberGenerator * rng)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:
randomize(byte out[],size_t len)116 void randomize(byte out[], size_t len)
117 {
118 Mutex_Holder lock(mutex);
119 rng->randomize(out, len);
120 }
121
is_seeded() const122 bool is_seeded() const
123 {
124 Mutex_Holder lock(mutex);
125 return rng->is_seeded();
126 }
127
clear()128 void clear()
129 {
130 Mutex_Holder lock(mutex);
131 rng->clear();
132 }
133
name() const134 std::string name() const
135 {
136 Mutex_Holder lock(mutex);
137 return rng->name();
138 }
139
reseed(size_t poll_bits)140 void reseed(size_t poll_bits)
141 {
142 Mutex_Holder lock(mutex);
143 rng->reseed(poll_bits);
144 }
145
add_entropy_source(EntropySource * es)146 void add_entropy_source(EntropySource* es)
147 {
148 Mutex_Holder lock(mutex);
149 rng->add_entropy_source(es);
150 }
151
add_entropy(const byte in[],size_t len)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
Serialized_PRNG(RandomNumberGenerator * r,Mutex * m)159 Serialized_PRNG(RandomNumberGenerator* r, Mutex* m) :
160 mutex(m), rng(r) {}
161
~Serialized_PRNG()162 ~Serialized_PRNG() { delete rng; }
163 private:
164 Mutex* mutex;
165 RandomNumberGenerator* rng;
166 };
167
168 }
169
make_global_rng(Algorithm_Factory & af,Mutex * mutex)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 }
205