1/*
2Copyright (C) 1999-2007 The Botan Project. All rights reserved.
3
4Redistribution and use in source and binary forms, for any use, with or without
5modification, is permitted provided that the following conditions are met:
6
71. Redistributions of source code must retain the above copyright notice, this
8list of conditions, and the following disclaimer.
9
102. Redistributions in binary form must reproduce the above copyright notice,
11this list of conditions, and the following disclaimer in the documentation
12and/or other materials provided with the distribution.
13
14THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED
15WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
17
18IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT,
19INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*/
26// LICENSEHEADER_END
27namespace QCA { // WRAPNS_LINE
28/*************************************************
29 * Library Internal/Global State Source File *
30 * (C) 1999-2007 The Botan Project *
31 *************************************************/
32
33} // WRAPNS_LINE
34#include <botan/libstate.h>
35namespace QCA { // WRAPNS_LINE
36#ifndef BOTAN_TOOLS_ONLY
37} // WRAPNS_LINE
38#include <botan/config.h>
39namespace QCA { // WRAPNS_LINE
40#endif
41} // WRAPNS_LINE
42#include <botan/modules.h>
43namespace QCA { // WRAPNS_LINE
44#ifndef BOTAN_TOOLS_ONLY
45} // WRAPNS_LINE
46#include <botan/engine.h>
47namespace QCA { // WRAPNS_LINE
48} // WRAPNS_LINE
49#include <botan/x509stat.h>
50namespace QCA { // WRAPNS_LINE
51#endif
52} // WRAPNS_LINE
53#include <botan/stl_util.h>
54namespace QCA { // WRAPNS_LINE
55} // WRAPNS_LINE
56#include <botan/mutex.h>
57namespace QCA { // WRAPNS_LINE
58#ifndef BOTAN_TOOLS_ONLY
59} // WRAPNS_LINE
60#include <botan/timers.h>
61namespace QCA { // WRAPNS_LINE
62} // WRAPNS_LINE
63#include <botan/charset.h>
64namespace QCA { // WRAPNS_LINE
65#endif
66} // WRAPNS_LINE
67#include <algorithm>
68namespace QCA { // WRAPNS_LINE
69
70namespace Botan {
71
72/*************************************************
73 * Botan's global state *
74 *************************************************/
75namespace {
76
77Library_State *global_lib_state = nullptr;
78
79}
80
81/*************************************************
82 * Access the global state object *
83 *************************************************/
84Library_State &global_state()
85{
86 if (!global_lib_state)
87 throw Invalid_State("Library was not initialized correctly");
88 return (*global_lib_state);
89}
90
91/*************************************************
92 * Set a new global state object *
93 *************************************************/
94void set_global_state(Library_State *new_state)
95{
96 delete swap_global_state(new_state);
97}
98
99/*************************************************
100 * Swap two global state objects *
101 *************************************************/
102Library_State *swap_global_state(Library_State *new_state)
103{
104 Library_State *old_state = global_lib_state;
105 global_lib_state = new_state;
106 return old_state;
107}
108
109/*************************************************
110 * Increment the Engine iterator *
111 *************************************************/
112#ifndef BOTAN_TOOLS_ONLY
113Engine *Library_State::Engine_Iterator::next()
114{
115 return lib.get_engine_n(n++);
116}
117#endif
118
119/*************************************************
120 * Get a new mutex object *
121 *************************************************/
122Mutex *Library_State::get_mutex() const
123{
124 return mutex_factory->make();
125}
126
127/*************************************************
128 * Get a persistent named mutex object *
129 *************************************************/
130Mutex *Library_State::get_named_mutex(const std::string &name)
131{
132 Mutex *mux = search_map<std::string, Mutex *>(mapping: locks, key: name, null_result: 0);
133 if (mux)
134 return mux;
135 return (locks[name] = get_mutex());
136}
137
138/*************************************************
139 * Get an allocator by its name *
140 *************************************************/
141Allocator *Library_State::get_allocator(const std::string &type) const
142{
143 Named_Mutex_Holder lock("allocator");
144
145 if (type != "")
146 return search_map<std::string, Allocator *>(mapping: alloc_factory, key: type, null_result: 0);
147
148 if (!cached_default_allocator) {
149#ifdef BOTAN_TOOLS_ONLY
150 std::string chosen = default_allocator_type;
151#else
152 std::string chosen = config().option("base/default_allocator");
153#endif
154 if (chosen == "")
155 chosen = "malloc";
156
157 cached_default_allocator = search_map<std::string, Allocator *>(mapping: alloc_factory, key: chosen, null_result: 0);
158 }
159
160 return cached_default_allocator;
161}
162
163/*************************************************
164 * Create a new name to object mapping *
165 *************************************************/
166void Library_State::add_allocator(Allocator *allocator)
167{
168 Named_Mutex_Holder lock("allocator");
169
170 allocator->init();
171
172 allocators.push_back(x: allocator);
173 alloc_factory[allocator->type()] = allocator;
174}
175
176/*************************************************
177 * Set the default allocator type *
178 *************************************************/
179#ifdef BOTAN_TOOLS_ONLY
180void Library_State::set_default_allocator(const std::string &type)
181#else
182void Library_State::set_default_allocator(const std::string &type) const
183#endif
184{
185 Named_Mutex_Holder lock("allocator");
186
187 if (type == "")
188 return;
189
190#ifdef BOTAN_TOOLS_ONLY
191 default_allocator_type = type;
192#else
193 config().set("conf", "base/default_allocator", type);
194#endif
195 cached_default_allocator = nullptr;
196}
197
198#ifndef BOTAN_TOOLS_ONLY
199/*************************************************
200 * Set the high resolution clock implementation *
201 *************************************************/
202void Library_State::set_timer(Timer *new_timer)
203{
204 if (new_timer) {
205 delete timer;
206 timer = new_timer;
207 }
208}
209
210/*************************************************
211 * Read a high resolution clock *
212 *************************************************/
213u64bit Library_State::system_clock() const
214{
215 return (timer) ? timer->clock() : 0;
216}
217
218/*************************************************
219 * Set the global PRNG *
220 *************************************************/
221void Library_State::set_prng(RandomNumberGenerator *new_rng)
222{
223 Named_Mutex_Holder lock("rng");
224
225 delete rng;
226 rng = new_rng;
227}
228
229/*************************************************
230 * Get bytes from the global PRNG *
231 *************************************************/
232void Library_State::randomize(byte out[], u32bit length)
233{
234 Named_Mutex_Holder lock("rng");
235
236 rng->randomize(out, length);
237}
238
239/*************************************************
240 * Add a new entropy source to use *
241 *************************************************/
242void Library_State::add_entropy_source(EntropySource *src, bool last_in_list)
243{
244 Named_Mutex_Holder lock("rng");
245
246 if (last_in_list)
247 entropy_sources.push_back(src);
248 else
249 entropy_sources.insert(entropy_sources.begin(), src);
250}
251
252/*************************************************
253 * Add some bytes of entropy to the global PRNG *
254 *************************************************/
255void Library_State::add_entropy(const byte in[], u32bit length)
256{
257 Named_Mutex_Holder lock("rng");
258
259 rng->add_entropy(in, length);
260}
261
262/*************************************************
263 * Add some bytes of entropy to the global PRNG *
264 *************************************************/
265void Library_State::add_entropy(EntropySource &source, bool slow_poll)
266{
267 Named_Mutex_Holder lock("rng");
268
269 rng->add_entropy(source, slow_poll);
270}
271
272/*************************************************
273 * Gather entropy for our PRNG object *
274 *************************************************/
275u32bit Library_State::seed_prng(bool slow_poll, u32bit bits_to_get)
276{
277 Named_Mutex_Holder lock("rng");
278
279 u32bit bits = 0;
280 for (u32bit j = 0; j != entropy_sources.size(); ++j) {
281 bits += rng->add_entropy(*(entropy_sources[j]), slow_poll);
282
283 if (bits_to_get && bits >= bits_to_get)
284 return bits;
285 }
286
287 return bits;
288}
289
290/*************************************************
291 * Get an engine out of the list *
292 *************************************************/
293Engine *Library_State::get_engine_n(u32bit n) const
294{
295 Named_Mutex_Holder lock("engine");
296
297 if (n >= engines.size())
298 return 0;
299 return engines[n];
300}
301
302/*************************************************
303 * Add a new engine to the list *
304 *************************************************/
305void Library_State::add_engine(Engine *engine)
306{
307 Named_Mutex_Holder lock("engine");
308 engines.insert(engines.begin(), engine);
309}
310
311/*************************************************
312 * Set the character set transcoder object *
313 *************************************************/
314void Library_State::set_transcoder(class Charset_Transcoder *transcoder)
315{
316 if (this->transcoder)
317 delete this->transcoder;
318 this->transcoder = transcoder;
319}
320
321/*************************************************
322 * Transcode a string from one charset to another *
323 *************************************************/
324std::string Library_State::transcode(const std::string str, Character_Set to, Character_Set from) const
325{
326 if (!transcoder)
327 throw Invalid_State("Library_State::transcode: No transcoder set");
328
329 return transcoder->transcode(str, to, from);
330}
331
332/*************************************************
333 * Set the X509 global state class *
334 *************************************************/
335void Library_State::set_x509_state(X509_GlobalState *new_x509_state_obj)
336{
337 delete x509_state_obj;
338 x509_state_obj = new_x509_state_obj;
339}
340
341/*************************************************
342 * Get the X509 global state class *
343 *************************************************/
344X509_GlobalState &Library_State::x509_state()
345{
346 if (!x509_state_obj)
347 x509_state_obj = new X509_GlobalState();
348
349 return (*x509_state_obj);
350}
351
352/*************************************************
353 * Set the UI object state *
354 *************************************************/
355void Library_State::set_ui(UI *new_ui)
356{
357 delete ui;
358 ui = new_ui;
359}
360
361/*************************************************
362 * Send a pulse to the UI object *
363 *************************************************/
364void Library_State::pulse(Pulse_Type pulse_type) const
365{
366 if (ui)
367 ui->pulse(pulse_type);
368}
369
370/*************************************************
371 * Set the configuration object *
372 *************************************************/
373Config &Library_State::config() const
374{
375 if (!config_obj)
376 throw Invalid_State("Library_State::config(): No config set");
377
378 return (*config_obj);
379}
380
381#endif
382
383/*************************************************
384 * Load modules *
385 *************************************************/
386void Library_State::load(Modules &modules)
387{
388#ifndef BOTAN_TOOLS_ONLY
389 set_timer(modules.timer());
390 set_transcoder(modules.transcoder());
391#endif
392
393 std::vector<Allocator *> mod_allocs = modules.allocators();
394 for (Allocator *mod_alloc : mod_allocs)
395 add_allocator(allocator: mod_alloc);
396
397 set_default_allocator(modules.default_allocator());
398
399#ifndef BOTAN_TOOLS_ONLY
400 std::vector<Engine *> mod_engines = modules.engines();
401 for (u32bit j = 0; j != mod_engines.size(); ++j) {
402 Named_Mutex_Holder lock("engine");
403 engines.push_back(mod_engines[j]);
404 }
405
406 std::vector<EntropySource *> sources = modules.entropy_sources();
407 for (u32bit j = 0; j != sources.size(); ++j)
408 add_entropy_source(sources[j]);
409#endif
410}
411
412/*************************************************
413 * Library_State Constructor *
414 *************************************************/
415Library_State::Library_State(Mutex_Factory *mutex_factory)
416{
417 if (!mutex_factory)
418 throw Exception("Library_State: no mutex found");
419
420 this->mutex_factory = mutex_factory;
421#ifndef BOTAN_TOOLS_ONLY
422 this->timer = new Timer();
423 this->transcoder = 0;
424 this->config_obj = new Config();
425#endif
426
427#ifndef BOTAN_TOOLS_ONLY
428 locks["settings"] = get_mutex();
429#endif
430 locks["allocator"] = get_mutex();
431#ifndef BOTAN_TOOLS_ONLY
432 locks["rng"] = get_mutex();
433 locks["engine"] = get_mutex();
434 rng = 0;
435#endif
436 cached_default_allocator = nullptr;
437#ifndef BOTAN_TOOLS_ONLY
438 x509_state_obj = 0;
439 ui = 0;
440#endif
441}
442
443/*************************************************
444 * Library_State Destructor *
445 *************************************************/
446static void delete_lock(std::pair<const std::string, Mutex *> &pair)
447{
448 delete pair.second;
449}
450
451Library_State::~Library_State()
452{
453#ifndef BOTAN_TOOLS_ONLY
454 delete x509_state_obj;
455 delete transcoder;
456 delete rng;
457 delete timer;
458 delete config_obj;
459 delete ui;
460
461 std::for_each(entropy_sources.begin(), entropy_sources.end(), del_fun<EntropySource>());
462 std::for_each(engines.begin(), engines.end(), del_fun<Engine>());
463#endif
464
465 cached_default_allocator = nullptr;
466
467 for (Allocator *allocator : allocators) {
468 allocator->destroy();
469 delete allocator;
470 }
471
472 std::for_each(first: locks.begin(), last: locks.end(), f: delete_lock);
473
474 delete mutex_factory;
475}
476
477}
478} // WRAPNS_LINE
479

source code of qca/src/botantools/botan/libstate.cpp