Botan 1.10.17
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
59namespace Botan {
60
61namespace {
62
63/**
64* Add any known entropy sources to this RNG
65*/
66void 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(
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
113class 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
170RandomNumberGenerator* 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}
ANSI_X931_RNG(BlockCipher *cipher, RandomNumberGenerator *rng)
Definition x931_rng.cpp:132
Device_EntropySource(const std::vector< std::string > &fsnames)
EGD_EntropySource(const std::vector< std::string > &)
Definition es_egd.cpp:122
FTW_EntropySource(const std::string &root_dir)
Definition es_ftw.cpp:136
HMAC_RNG(MessageAuthenticationCode *extractor, MessageAuthenticationCode *prf)
Definition hmac_rng.cpp:169
Randpool(BlockCipher *cipher, MessageAuthenticationCode *mac, size_t pool_blocks=32, size_t iterations_before_reseed=128)
Definition randpool.cpp:169
Unix_EntropySource(const std::vector< std::string > &path)
Definition es_unix.cpp:38
std::vector< std::string > split_on(const std::string &str, char delim)
Definition parsing.cpp:152
Internal_Error(const std::string &err)
Definition exceptn.h:47