monotone

monotone Mtn Source Tree

Root/botan/libstate.cpp

1/*************************************************
2* Library Internal/Global State Source File *
3* (C) 1999-2007 The Botan Project *
4*************************************************/
5
6#include <botan/libstate.h>
7#include <botan/config.h>
8#include <botan/modules.h>
9#include <botan/engine.h>
10#include <botan/x509stat.h>
11#include <botan/stl_util.h>
12#include <botan/mutex.h>
13#include <botan/timers.h>
14#include <botan/charset.h>
15#include <botan/x931_rng.h>
16#include <botan/fips140.h>
17#include <algorithm>
18
19namespace Botan {
20
21/*************************************************
22* Botan's global state *
23*************************************************/
24namespace {
25
26Library_State* global_lib_state = 0;
27
28}
29
30/*************************************************
31* Access the global state object *
32*************************************************/
33Library_State& global_state()
34 {
35 if(!global_lib_state)
36 LibraryInitializer::initialize();
37 return (*global_lib_state);
38 }
39
40/*************************************************
41* Set a new global state object *
42*************************************************/
43void set_global_state(Library_State* new_state)
44 {
45 delete swap_global_state(new_state);
46 }
47
48/*************************************************
49* Swap two global state objects *
50*************************************************/
51Library_State* swap_global_state(Library_State* new_state)
52 {
53 Library_State* old_state = global_lib_state;
54 global_lib_state = new_state;
55 return old_state;
56 }
57
58/*************************************************
59* Increment the Engine iterator *
60*************************************************/
61Engine* Library_State::Engine_Iterator::next()
62 {
63 return lib.get_engine_n(n++);
64 }
65
66/*************************************************
67* Get a new mutex object *
68*************************************************/
69Mutex* Library_State::get_mutex() const
70 {
71 return mutex_factory->make();
72 }
73
74/*************************************************
75* Get a persistent named mutex object *
76*************************************************/
77Mutex* Library_State::get_named_mutex(const std::string& name)
78 {
79 Mutex* mux = search_map<std::string, Mutex*>(locks, name, 0);
80 if(mux)
81 return mux;
82 return (locks[name] = get_mutex());
83 }
84
85/*************************************************
86* Get an allocator by its name *
87*************************************************/
88Allocator* Library_State::get_allocator(const std::string& type) const
89 {
90 Named_Mutex_Holder lock("allocator");
91
92 if(type != "")
93 return search_map<std::string, Allocator*>(alloc_factory, type, 0);
94
95 if(!cached_default_allocator)
96 {
97 std::string chosen = config().option("base/default_allocator");
98
99 if(chosen == "")
100 chosen = "malloc";
101
102 cached_default_allocator =
103 search_map<std::string, Allocator*>(alloc_factory, chosen, 0);
104 }
105
106 return cached_default_allocator;
107 }
108
109/*************************************************
110* Create a new name to object mapping *
111*************************************************/
112void Library_State::add_allocator(Allocator* allocator)
113 {
114 Named_Mutex_Holder lock("allocator");
115
116 allocator->init();
117
118 allocators.push_back(allocator);
119 alloc_factory[allocator->type()] = allocator;
120 }
121
122/*************************************************
123* Set the default allocator type *
124*************************************************/
125void Library_State::set_default_allocator(const std::string& type) const
126 {
127 Named_Mutex_Holder lock("allocator");
128
129 if(type == "")
130 return;
131
132 config().set("conf", "base/default_allocator", type);
133 cached_default_allocator = 0;
134 }
135
136/*************************************************
137* Set the high resolution clock implementation *
138*************************************************/
139void Library_State::set_timer(Timer* new_timer)
140 {
141 delete timer;
142 timer = new_timer;
143 }
144
145/*************************************************
146* Read a high resolution clock *
147*************************************************/
148u64bit Library_State::system_clock() const
149 {
150 return (timer) ? timer->clock() : 0;
151 }
152
153/*************************************************
154* Set the global PRNG *
155*************************************************/
156void Library_State::set_prng(RandomNumberGenerator* new_rng)
157 {
158 Named_Mutex_Holder lock("rng");
159
160 delete rng;
161 rng = new_rng;
162 }
163
164/*************************************************
165* Get bytes from the global PRNG *
166*************************************************/
167void Library_State::randomize(byte out[], u32bit length)
168 {
169 Named_Mutex_Holder lock("rng");
170
171 rng->randomize(out, length);
172 }
173
174/*************************************************
175* Add a new entropy source to use *
176*************************************************/
177void Library_State::add_entropy_source(EntropySource* src, bool last_in_list)
178 {
179 Named_Mutex_Holder lock("rng");
180
181 if(last_in_list)
182 entropy_sources.push_back(src);
183 else
184 entropy_sources.insert(entropy_sources.begin(), src);
185 }
186
187/*************************************************
188* Add some bytes of entropy to the global PRNG *
189*************************************************/
190void Library_State::add_entropy(const byte in[], u32bit length)
191 {
192 Named_Mutex_Holder lock("rng");
193
194 rng->add_entropy(in, length);
195 }
196
197/*************************************************
198* Add some bytes of entropy to the global PRNG *
199*************************************************/
200void Library_State::add_entropy(EntropySource& source, bool slow_poll)
201 {
202 Named_Mutex_Holder lock("rng");
203
204 rng->add_entropy(source, slow_poll);
205 }
206
207/*************************************************
208* Gather entropy for our PRNG object *
209*************************************************/
210u32bit Library_State::seed_prng(bool slow_poll, u32bit bits_to_get)
211 {
212 Named_Mutex_Holder lock("rng");
213
214 u32bit bits = 0;
215 for(u32bit j = 0; j != entropy_sources.size(); ++j)
216 {
217 bits += rng->add_entropy(*(entropy_sources[j]), slow_poll);
218
219 if(bits_to_get && bits >= bits_to_get)
220 return bits;
221 }
222
223 return bits;
224 }
225
226/*************************************************
227* Get an engine out of the list *
228*************************************************/
229Engine* Library_State::get_engine_n(u32bit n) const
230 {
231 Named_Mutex_Holder lock("engine");
232
233 if(n >= engines.size())
234 return 0;
235 return engines[n];
236 }
237
238/*************************************************
239* Add a new engine to the list *
240*************************************************/
241void Library_State::add_engine(Engine* engine)
242 {
243 Named_Mutex_Holder lock("engine");
244 engines.insert(engines.begin(), engine);
245 }
246
247/*************************************************
248* Set the character set transcoder object *
249*************************************************/
250void Library_State::set_transcoder(class Charset_Transcoder* transcoder)
251 {
252 if(this->transcoder)
253 delete this->transcoder;
254 this->transcoder = transcoder;
255 }
256
257/*************************************************
258* Transcode a string from one charset to another *
259*************************************************/
260std::string Library_State::transcode(const std::string str,
261 Character_Set to,
262 Character_Set from) const
263 {
264 if(!transcoder)
265 throw Invalid_State("Library_State::transcode: No transcoder set");
266
267 return transcoder->transcode(str, to, from);
268 }
269
270/*************************************************
271* Set the X509 global state class *
272*************************************************/
273void Library_State::set_x509_state(X509_GlobalState* new_x509_state_obj)
274 {
275 delete x509_state_obj;
276 x509_state_obj = new_x509_state_obj;
277 }
278
279/*************************************************
280* Get the X509 global state class *
281*************************************************/
282X509_GlobalState& Library_State::x509_state()
283 {
284 if(!x509_state_obj)
285 x509_state_obj = new X509_GlobalState();
286
287 return (*x509_state_obj);
288 }
289
290/*************************************************
291* Set the UI object state *
292*************************************************/
293void Library_State::set_ui(UI* new_ui)
294 {
295 delete ui;
296 ui = new_ui;
297 }
298
299/*************************************************
300* Send a pulse to the UI object *
301*************************************************/
302void Library_State::pulse(Pulse_Type pulse_type) const
303 {
304 if(ui)
305 ui->pulse(pulse_type);
306 }
307
308/*************************************************
309* Set the configuration object *
310*************************************************/
311Config& Library_State::config() const
312 {
313 if(!config_obj)
314 {
315 config_obj = new Config();
316 config_obj->load_defaults();
317 }
318
319 return (*config_obj);
320 }
321
322/*************************************************
323* Load a set of modules *
324*************************************************/
325void Library_State::initialize(const InitializerOptions& args,
326 Modules& modules)
327 {
328 if(mutex_factory)
329 throw Invalid_State("Library_State has already been initialized");
330
331 if(args.thread_safe())
332 mutex_factory = modules.mutex_factory();
333 else
334 mutex_factory = new Default_Mutex_Factory;
335
336 cached_default_allocator = 0;
337 x509_state_obj = 0;
338 ui = 0;
339
340 timer = modules.timer();
341 transcoder = modules.transcoder();
342
343 locks["settings"] = get_mutex();
344 locks["allocator"] = get_mutex();
345 locks["rng"] = get_mutex();
346 locks["engine"] = get_mutex();
347
348 std::vector<Allocator*> mod_allocs = modules.allocators();
349 for(u32bit j = 0; j != mod_allocs.size(); ++j)
350 add_allocator(mod_allocs[j]);
351
352 set_default_allocator(modules.default_allocator());
353
354 std::vector<Engine*> mod_engines = modules.engines();
355 for(u32bit j = 0; j != mod_engines.size(); ++j)
356 {
357 Named_Mutex_Holder lock("engine");
358 engines.push_back(mod_engines[j]);
359 }
360
361 std::vector<EntropySource*> sources = modules.entropy_sources();
362 for(u32bit j = 0; j != sources.size(); ++j)
363 add_entropy_source(sources[j]);
364
365 set_prng(new ANSI_X931_RNG);
366
367 if(args.seed_rng())
368 {
369 for(u32bit j = 0; j != 4; ++j)
370 {
371 seed_prng(true, 384);
372 if(rng_is_seeded())
373 break;
374 }
375
376 if(!rng_is_seeded())
377 throw PRNG_Unseeded("Unable to collect sufficient entropy");
378 }
379
380 if(args.fips_mode() || args.self_test())
381 {
382 if(!FIPS140::passes_self_tests())
383 throw Self_Test_Failure("FIPS-140 startup tests");
384 }
385 }
386
387/*************************************************
388* Library_State Constructor *
389*************************************************/
390Library_State::Library_State()
391 {
392 mutex_factory = 0;
393
394 timer = 0;
395 config_obj = 0;
396 x509_state_obj = 0;
397
398 ui = 0;
399 transcoder = 0;
400 rng = 0;
401 cached_default_allocator = 0;
402 ui = 0;
403 }
404
405/*************************************************
406* Library_State Destructor *
407*************************************************/
408Library_State::~Library_State()
409 {
410 delete x509_state_obj;
411 delete transcoder;
412 delete rng;
413 delete timer;
414 delete config_obj;
415 delete ui;
416
417 std::for_each(entropy_sources.begin(), entropy_sources.end(),
418 del_fun<EntropySource>());
419 std::for_each(engines.begin(), engines.end(), del_fun<Engine>());
420
421 cached_default_allocator = 0;
422
423 for(u32bit j = 0; j != allocators.size(); ++j)
424 {
425 allocators[j]->destroy();
426 delete allocators[j];
427 }
428
429 std::for_each(locks.begin(), locks.end(),
430 delete2nd<std::map<std::string, Mutex*>::value_type>);
431
432 delete mutex_factory;
433 }
434
435}

Archive Download this file

Branches

Tags

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