1 | /* |
2 | Copyright (C) 1999-2007 The Botan Project. All rights reserved. |
3 | |
4 | Redistribution and use in source and binary forms, for any use, with or without |
5 | modification, is permitted provided that the following conditions are met: |
6 | |
7 | 1. Redistributions of source code must retain the above copyright notice, this |
8 | list of conditions, and the following disclaimer. |
9 | |
10 | 2. Redistributions in binary form must reproduce the above copyright notice, |
11 | this list of conditions, and the following disclaimer in the documentation |
12 | and/or other materials provided with the distribution. |
13 | |
14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED |
15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
16 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. |
17 | |
18 | IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT, |
19 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
20 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
22 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
23 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ |
26 | // LICENSEHEADER_END |
27 | namespace 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> |
35 | namespace QCA { // WRAPNS_LINE |
36 | #ifndef BOTAN_TOOLS_ONLY |
37 | } // WRAPNS_LINE |
38 | #include <botan/config.h> |
39 | namespace QCA { // WRAPNS_LINE |
40 | #endif |
41 | } // WRAPNS_LINE |
42 | #include <botan/modules.h> |
43 | namespace QCA { // WRAPNS_LINE |
44 | #ifndef BOTAN_TOOLS_ONLY |
45 | } // WRAPNS_LINE |
46 | #include <botan/engine.h> |
47 | namespace QCA { // WRAPNS_LINE |
48 | } // WRAPNS_LINE |
49 | #include <botan/x509stat.h> |
50 | namespace QCA { // WRAPNS_LINE |
51 | #endif |
52 | } // WRAPNS_LINE |
53 | #include <botan/stl_util.h> |
54 | namespace QCA { // WRAPNS_LINE |
55 | } // WRAPNS_LINE |
56 | #include <botan/mutex.h> |
57 | namespace QCA { // WRAPNS_LINE |
58 | #ifndef BOTAN_TOOLS_ONLY |
59 | } // WRAPNS_LINE |
60 | #include <botan/timers.h> |
61 | namespace QCA { // WRAPNS_LINE |
62 | } // WRAPNS_LINE |
63 | #include <botan/charset.h> |
64 | namespace QCA { // WRAPNS_LINE |
65 | #endif |
66 | } // WRAPNS_LINE |
67 | #include <algorithm> |
68 | namespace QCA { // WRAPNS_LINE |
69 | |
70 | namespace Botan { |
71 | |
72 | /************************************************* |
73 | * Botan's global state * |
74 | *************************************************/ |
75 | namespace { |
76 | |
77 | Library_State *global_lib_state = nullptr; |
78 | |
79 | } |
80 | |
81 | /************************************************* |
82 | * Access the global state object * |
83 | *************************************************/ |
84 | Library_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 | *************************************************/ |
94 | void 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 | *************************************************/ |
102 | Library_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 |
113 | Engine *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 | *************************************************/ |
122 | Mutex *Library_State::get_mutex() const |
123 | { |
124 | return mutex_factory->make(); |
125 | } |
126 | |
127 | /************************************************* |
128 | * Get a persistent named mutex object * |
129 | *************************************************/ |
130 | Mutex *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 | *************************************************/ |
141 | Allocator *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 | *************************************************/ |
166 | void 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 |
180 | void Library_State::set_default_allocator(const std::string &type) |
181 | #else |
182 | void 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 | *************************************************/ |
202 | void 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 | *************************************************/ |
213 | u64bit Library_State::system_clock() const |
214 | { |
215 | return (timer) ? timer->clock() : 0; |
216 | } |
217 | |
218 | /************************************************* |
219 | * Set the global PRNG * |
220 | *************************************************/ |
221 | void 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 | *************************************************/ |
232 | void 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 | *************************************************/ |
242 | void 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 | *************************************************/ |
255 | void 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 | *************************************************/ |
265 | void 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 | *************************************************/ |
275 | u32bit 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 | *************************************************/ |
293 | Engine *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 | *************************************************/ |
305 | void 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 | *************************************************/ |
314 | void 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 | *************************************************/ |
324 | std::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 | *************************************************/ |
335 | void 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 | *************************************************/ |
344 | X509_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 | *************************************************/ |
355 | void 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 | *************************************************/ |
364 | void 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 | *************************************************/ |
373 | Config &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 | *************************************************/ |
386 | void 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 | *************************************************/ |
415 | Library_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 | *************************************************/ |
446 | static void delete_lock(std::pair<const std::string, Mutex *> &pair) |
447 | { |
448 | delete pair.second; |
449 | } |
450 | |
451 | Library_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 | |