monotone

monotone Mtn Source Tree

Root/botan/rng.cpp

1/*************************************************
2* Global RNG Source File *
3* (C) 1999-2005 The Botan Project *
4*************************************************/
5
6#include <botan/rng.h>
7#include <botan/mutex.h>
8#include <botan/lookup.h>
9#include <botan/init.h>
10#include <botan/util.h>
11#include <memory>
12#include <vector>
13
14namespace Botan {
15
16namespace {
17
18/*************************************************
19* Global RNG/EntropySource state *
20*************************************************/
21class RNG_State
22 {
23 public:
24 void set_rngs(RandomNumberGenerator*, RandomNumberGenerator*);
25 void add_es(EntropySource*, bool);
26 void add_entropy(const byte[], u32bit);
27 u32bit poll_es(EntropySource*, bool);
28
29 u32bit seed(bool, u32bit);
30
31 void randomize(byte[], u32bit, RNG_Quality);
32
33 RNG_State();
34 ~RNG_State();
35 private:
36 void seed_nonce_rng();
37 RandomNumberGenerator* global_rng;
38 RandomNumberGenerator* nonce_rng;
39 Mutex* rng_mutex;
40 Mutex* sources_mutex;
41 std::vector<EntropySource*> sources;
42 };
43
44/*************************************************
45* Create the RNG state *
46*************************************************/
47RNG_State::RNG_State()
48 {
49 global_rng = nonce_rng = 0;
50 rng_mutex = get_mutex();
51 sources_mutex = get_mutex();
52 }
53
54/*************************************************
55* Destroy the RNG state *
56*************************************************/
57RNG_State::~RNG_State()
58 {
59 delete global_rng;
60 delete nonce_rng;
61 for(u32bit j = 0; j != sources.size(); j++)
62 delete sources[j];
63
64 delete rng_mutex;
65 delete sources_mutex;
66 }
67
68/*************************************************
69* Set the RNG algorithms *
70*************************************************/
71void RNG_State::set_rngs(RandomNumberGenerator* rng1,
72 RandomNumberGenerator* rng2)
73 {
74 if(rng1)
75 {
76 if(global_rng)
77 delete global_rng;
78 global_rng = rng1;
79 }
80
81 if(rng2)
82 {
83 if(nonce_rng)
84 delete nonce_rng;
85 nonce_rng = rng2;
86 }
87 }
88
89/*************************************************
90* Get entropy from the global RNG *
91*************************************************/
92void RNG_State::randomize(byte output[], u32bit size, RNG_Quality level)
93 {
94 const std::string LTERM_CIPHER = "WiderWake4+1";
95
96 Mutex_Holder lock(rng_mutex);
97
98 if(!global_rng || !nonce_rng)
99 throw Invalid_State("Global_RNG::randomize: The global RNG is unset");
100
101 if(level == Nonce)
102 nonce_rng->randomize(output, size);
103 else if(level == SessionKey)
104 global_rng->randomize(output, size);
105 else if(level == LongTermKey)
106 {
107 global_rng->randomize(output, size);
108 if(have_stream_cipher(LTERM_CIPHER))
109 {
110 std::auto_ptr<StreamCipher> cipher(get_stream_cipher(LTERM_CIPHER));
111 SecureVector<byte> key(cipher->MAXIMUM_KEYLENGTH);
112 global_rng->randomize(key.begin(), key.size());
113 cipher->set_key(key.begin(), key.size());
114 cipher->encrypt(output, size);
115 }
116 }
117 else
118 throw Invalid_Argument("Global_RNG::randomize: Invalid RNG_Quality");
119 }
120
121/*************************************************
122* Add entropy to the RNG *
123*************************************************/
124void RNG_State::add_entropy(const byte buf[], u32bit length)
125 {
126 Mutex_Holder lock(rng_mutex);
127
128 if(!global_rng || !nonce_rng)
129 throw Invalid_State("Global_RNG::add_entropy: The global RNG is unset");
130
131 global_rng->add_entropy(buf, length);
132 seed_nonce_rng();
133 }
134
135/*************************************************
136* Add an EntropySource to the list *
137*************************************************/
138void RNG_State::add_es(EntropySource* src, bool last)
139 {
140 Mutex_Holder lock(sources_mutex);
141 if(last)
142 sources.push_back(src);
143 else
144 sources.insert(sources.begin(), src);
145 }
146
147/*************************************************
148* Seed the nonce RNG *
149*************************************************/
150void RNG_State::seed_nonce_rng()
151 {
152 if(!global_rng->is_seeded())
153 return;
154
155 for(u32bit j = 0; j != 3; j++)
156 {
157 if(nonce_rng->is_seeded())
158 break;
159
160 SecureVector<byte> entropy(64);
161 global_rng->randomize(entropy.begin(), entropy.size());
162 nonce_rng->add_entropy(entropy.begin(), entropy.size());
163 }
164 }
165
166/*************************************************
167* Try to do a poll on an EntropySource *
168*************************************************/
169u32bit RNG_State::poll_es(EntropySource* source, bool slow_poll)
170 {
171 SecureVector<byte> buffer(256);
172 u32bit got = 0;
173
174 if(slow_poll) got = source->slow_poll(buffer.begin(), buffer.size());
175 else got = source->fast_poll(buffer.begin(), buffer.size());
176
177 add_entropy(buffer.begin(), got);
178 return entropy_estimate(buffer.begin(), got);
179 }
180
181/*************************************************
182* Attempt to seed the RNGs *
183*************************************************/
184u32bit RNG_State::seed(bool slow_poll, u32bit bits_to_get)
185 {
186 Mutex_Holder lock(sources_mutex);
187
188 u32bit bits = 0;
189 for(u32bit j = 0; j != sources.size(); j++)
190 {
191 bits += poll_es(sources[j], slow_poll);
192 if(bits_to_get && bits >= bits_to_get)
193 return bits;
194 }
195 return bits;
196 }
197
198/*************************************************
199* The global RNG state *
200*************************************************/
201RNG_State* rng_state = 0;
202
203}
204
205namespace Global_RNG {
206
207/*************************************************
208* Get entropy from the global RNG *
209*************************************************/
210void randomize(byte output[], u32bit size, RNG_Quality level)
211 {
212 if(!rng_state)
213 throw Internal_Error("Global_RNG::randomize: RNG state never created");
214 rng_state->randomize(output, size, level);
215 }
216
217/*************************************************
218* Get entropy from the global RNG *
219*************************************************/
220byte random(RNG_Quality level)
221 {
222 byte ret = 0;
223 randomize(&ret, 1, level);
224 return ret;
225 }
226
227/*************************************************
228* Add entropy to the global RNG *
229*************************************************/
230void add_entropy(const byte entropy[], u32bit size)
231 {
232 if(!rng_state)
233 throw Internal_Error("Global_RNG::add_entropy: RNG state never created");
234 rng_state->add_entropy(entropy, size);
235 }
236
237/*************************************************
238* Add entropy to the global RNG *
239*************************************************/
240void add_entropy(EntropySource& src, bool slow_poll)
241 {
242 if(!rng_state)
243 throw Internal_Error("Global_RNG::poll_es: RNG state never created");
244 rng_state->poll_es(&src, slow_poll);
245 }
246
247/*************************************************
248* Add an EntropySource to the list *
249*************************************************/
250void add_es(EntropySource* src, bool last)
251 {
252 if(!rng_state)
253 throw Internal_Error("Global_RNG::add_es: RNG state never created");
254 rng_state->add_es(src, last);
255 }
256
257/*************************************************
258* Seed the global RNG *
259*************************************************/
260u32bit seed(bool slow_poll, u32bit bits_to_get)
261 {
262 if(!rng_state)
263 throw Internal_Error("Global_RNG::seed: RNG state never created");
264 return rng_state->seed(slow_poll, bits_to_get);
265 }
266
267}
268
269namespace Init {
270
271/*************************************************
272* Initialize the RNG system *
273*************************************************/
274void init_rng_subsystem()
275 {
276 rng_state = new RNG_State;
277 }
278
279/*************************************************
280* Deinitialize the RNG system *
281*************************************************/
282void shutdown_rng_subsystem()
283 {
284 delete rng_state;
285 rng_state = 0;
286 }
287
288/*************************************************
289* Setup the global RNG *
290*************************************************/
291void set_global_rngs(RandomNumberGenerator* rng1, RandomNumberGenerator* rng2)
292 {
293 if(!rng_state)
294 throw Internal_Error("set_global_rngs: RNG state never created");
295 rng_state->set_rngs(rng1, rng2);
296 }
297
298}
299
300}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status