File indexing completed on 2024-05-12 04:45:14
0001 /* 0002 Copyright (C) 1999-2007 The Botan Project. All rights reserved. 0003 0004 Redistribution and use in source and binary forms, for any use, with or without 0005 modification, is permitted provided that the following conditions are met: 0006 0007 1. Redistributions of source code must retain the above copyright notice, this 0008 list of conditions, and the following disclaimer. 0009 0010 2. Redistributions in binary form must reproduce the above copyright notice, 0011 this list of conditions, and the following disclaimer in the documentation 0012 and/or other materials provided with the distribution. 0013 0014 THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED 0015 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 0016 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. 0017 0018 IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT, 0019 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 0020 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0021 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 0022 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 0023 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 0024 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0025 */ 0026 // LICENSEHEADER_END 0027 namespace QCA { // WRAPNS_LINE 0028 /************************************************* 0029 * Library Internal/Global State Source File * 0030 * (C) 1999-2007 The Botan Project * 0031 *************************************************/ 0032 0033 } // WRAPNS_LINE 0034 #include <botan/libstate.h> 0035 namespace QCA { // WRAPNS_LINE 0036 #ifndef BOTAN_TOOLS_ONLY 0037 } // WRAPNS_LINE 0038 #include <botan/config.h> 0039 namespace QCA { // WRAPNS_LINE 0040 #endif 0041 } // WRAPNS_LINE 0042 #include <botan/modules.h> 0043 namespace QCA { // WRAPNS_LINE 0044 #ifndef BOTAN_TOOLS_ONLY 0045 } // WRAPNS_LINE 0046 #include <botan/engine.h> 0047 namespace QCA { // WRAPNS_LINE 0048 } // WRAPNS_LINE 0049 #include <botan/x509stat.h> 0050 namespace QCA { // WRAPNS_LINE 0051 #endif 0052 } // WRAPNS_LINE 0053 #include <botan/stl_util.h> 0054 namespace QCA { // WRAPNS_LINE 0055 } // WRAPNS_LINE 0056 #include <botan/mutex.h> 0057 namespace QCA { // WRAPNS_LINE 0058 #ifndef BOTAN_TOOLS_ONLY 0059 } // WRAPNS_LINE 0060 #include <botan/timers.h> 0061 namespace QCA { // WRAPNS_LINE 0062 } // WRAPNS_LINE 0063 #include <botan/charset.h> 0064 namespace QCA { // WRAPNS_LINE 0065 #endif 0066 } // WRAPNS_LINE 0067 #include <algorithm> 0068 namespace QCA { // WRAPNS_LINE 0069 0070 namespace Botan { 0071 0072 /************************************************* 0073 * Botan's global state * 0074 *************************************************/ 0075 namespace { 0076 0077 Library_State *global_lib_state = nullptr; 0078 0079 } 0080 0081 /************************************************* 0082 * Access the global state object * 0083 *************************************************/ 0084 Library_State &global_state() 0085 { 0086 if (!global_lib_state) 0087 throw Invalid_State("Library was not initialized correctly"); 0088 return (*global_lib_state); 0089 } 0090 0091 /************************************************* 0092 * Set a new global state object * 0093 *************************************************/ 0094 void set_global_state(Library_State *new_state) 0095 { 0096 delete swap_global_state(new_state); 0097 } 0098 0099 /************************************************* 0100 * Swap two global state objects * 0101 *************************************************/ 0102 Library_State *swap_global_state(Library_State *new_state) 0103 { 0104 Library_State *old_state = global_lib_state; 0105 global_lib_state = new_state; 0106 return old_state; 0107 } 0108 0109 /************************************************* 0110 * Increment the Engine iterator * 0111 *************************************************/ 0112 #ifndef BOTAN_TOOLS_ONLY 0113 Engine *Library_State::Engine_Iterator::next() 0114 { 0115 return lib.get_engine_n(n++); 0116 } 0117 #endif 0118 0119 /************************************************* 0120 * Get a new mutex object * 0121 *************************************************/ 0122 Mutex *Library_State::get_mutex() const 0123 { 0124 return mutex_factory->make(); 0125 } 0126 0127 /************************************************* 0128 * Get a persistent named mutex object * 0129 *************************************************/ 0130 Mutex *Library_State::get_named_mutex(const std::string &name) 0131 { 0132 Mutex *mux = search_map<std::string, Mutex *>(locks, name, 0); 0133 if (mux) 0134 return mux; 0135 return (locks[name] = get_mutex()); 0136 } 0137 0138 /************************************************* 0139 * Get an allocator by its name * 0140 *************************************************/ 0141 Allocator *Library_State::get_allocator(const std::string &type) const 0142 { 0143 Named_Mutex_Holder lock("allocator"); 0144 0145 if (type != "") 0146 return search_map<std::string, Allocator *>(alloc_factory, type, 0); 0147 0148 if (!cached_default_allocator) { 0149 #ifdef BOTAN_TOOLS_ONLY 0150 std::string chosen = default_allocator_type; 0151 #else 0152 std::string chosen = config().option("base/default_allocator"); 0153 #endif 0154 if (chosen == "") 0155 chosen = "malloc"; 0156 0157 cached_default_allocator = search_map<std::string, Allocator *>(alloc_factory, chosen, 0); 0158 } 0159 0160 return cached_default_allocator; 0161 } 0162 0163 /************************************************* 0164 * Create a new name to object mapping * 0165 *************************************************/ 0166 void Library_State::add_allocator(Allocator *allocator) 0167 { 0168 Named_Mutex_Holder lock("allocator"); 0169 0170 allocator->init(); 0171 0172 allocators.push_back(allocator); 0173 alloc_factory[allocator->type()] = allocator; 0174 } 0175 0176 /************************************************* 0177 * Set the default allocator type * 0178 *************************************************/ 0179 #ifdef BOTAN_TOOLS_ONLY 0180 void Library_State::set_default_allocator(const std::string &type) 0181 #else 0182 void Library_State::set_default_allocator(const std::string &type) const 0183 #endif 0184 { 0185 Named_Mutex_Holder lock("allocator"); 0186 0187 if (type == "") 0188 return; 0189 0190 #ifdef BOTAN_TOOLS_ONLY 0191 default_allocator_type = type; 0192 #else 0193 config().set("conf", "base/default_allocator", type); 0194 #endif 0195 cached_default_allocator = nullptr; 0196 } 0197 0198 #ifndef BOTAN_TOOLS_ONLY 0199 /************************************************* 0200 * Set the high resolution clock implementation * 0201 *************************************************/ 0202 void Library_State::set_timer(Timer *new_timer) 0203 { 0204 if (new_timer) { 0205 delete timer; 0206 timer = new_timer; 0207 } 0208 } 0209 0210 /************************************************* 0211 * Read a high resolution clock * 0212 *************************************************/ 0213 u64bit Library_State::system_clock() const 0214 { 0215 return (timer) ? timer->clock() : 0; 0216 } 0217 0218 /************************************************* 0219 * Set the global PRNG * 0220 *************************************************/ 0221 void Library_State::set_prng(RandomNumberGenerator *new_rng) 0222 { 0223 Named_Mutex_Holder lock("rng"); 0224 0225 delete rng; 0226 rng = new_rng; 0227 } 0228 0229 /************************************************* 0230 * Get bytes from the global PRNG * 0231 *************************************************/ 0232 void Library_State::randomize(byte out[], u32bit length) 0233 { 0234 Named_Mutex_Holder lock("rng"); 0235 0236 rng->randomize(out, length); 0237 } 0238 0239 /************************************************* 0240 * Add a new entropy source to use * 0241 *************************************************/ 0242 void Library_State::add_entropy_source(EntropySource *src, bool last_in_list) 0243 { 0244 Named_Mutex_Holder lock("rng"); 0245 0246 if (last_in_list) 0247 entropy_sources.push_back(src); 0248 else 0249 entropy_sources.insert(entropy_sources.begin(), src); 0250 } 0251 0252 /************************************************* 0253 * Add some bytes of entropy to the global PRNG * 0254 *************************************************/ 0255 void Library_State::add_entropy(const byte in[], u32bit length) 0256 { 0257 Named_Mutex_Holder lock("rng"); 0258 0259 rng->add_entropy(in, length); 0260 } 0261 0262 /************************************************* 0263 * Add some bytes of entropy to the global PRNG * 0264 *************************************************/ 0265 void Library_State::add_entropy(EntropySource &source, bool slow_poll) 0266 { 0267 Named_Mutex_Holder lock("rng"); 0268 0269 rng->add_entropy(source, slow_poll); 0270 } 0271 0272 /************************************************* 0273 * Gather entropy for our PRNG object * 0274 *************************************************/ 0275 u32bit Library_State::seed_prng(bool slow_poll, u32bit bits_to_get) 0276 { 0277 Named_Mutex_Holder lock("rng"); 0278 0279 u32bit bits = 0; 0280 for (u32bit j = 0; j != entropy_sources.size(); ++j) { 0281 bits += rng->add_entropy(*(entropy_sources[j]), slow_poll); 0282 0283 if (bits_to_get && bits >= bits_to_get) 0284 return bits; 0285 } 0286 0287 return bits; 0288 } 0289 0290 /************************************************* 0291 * Get an engine out of the list * 0292 *************************************************/ 0293 Engine *Library_State::get_engine_n(u32bit n) const 0294 { 0295 Named_Mutex_Holder lock("engine"); 0296 0297 if (n >= engines.size()) 0298 return 0; 0299 return engines[n]; 0300 } 0301 0302 /************************************************* 0303 * Add a new engine to the list * 0304 *************************************************/ 0305 void Library_State::add_engine(Engine *engine) 0306 { 0307 Named_Mutex_Holder lock("engine"); 0308 engines.insert(engines.begin(), engine); 0309 } 0310 0311 /************************************************* 0312 * Set the character set transcoder object * 0313 *************************************************/ 0314 void Library_State::set_transcoder(class Charset_Transcoder *transcoder) 0315 { 0316 if (this->transcoder) 0317 delete this->transcoder; 0318 this->transcoder = transcoder; 0319 } 0320 0321 /************************************************* 0322 * Transcode a string from one charset to another * 0323 *************************************************/ 0324 std::string Library_State::transcode(const std::string str, Character_Set to, Character_Set from) const 0325 { 0326 if (!transcoder) 0327 throw Invalid_State("Library_State::transcode: No transcoder set"); 0328 0329 return transcoder->transcode(str, to, from); 0330 } 0331 0332 /************************************************* 0333 * Set the X509 global state class * 0334 *************************************************/ 0335 void Library_State::set_x509_state(X509_GlobalState *new_x509_state_obj) 0336 { 0337 delete x509_state_obj; 0338 x509_state_obj = new_x509_state_obj; 0339 } 0340 0341 /************************************************* 0342 * Get the X509 global state class * 0343 *************************************************/ 0344 X509_GlobalState &Library_State::x509_state() 0345 { 0346 if (!x509_state_obj) 0347 x509_state_obj = new X509_GlobalState(); 0348 0349 return (*x509_state_obj); 0350 } 0351 0352 /************************************************* 0353 * Set the UI object state * 0354 *************************************************/ 0355 void Library_State::set_ui(UI *new_ui) 0356 { 0357 delete ui; 0358 ui = new_ui; 0359 } 0360 0361 /************************************************* 0362 * Send a pulse to the UI object * 0363 *************************************************/ 0364 void Library_State::pulse(Pulse_Type pulse_type) const 0365 { 0366 if (ui) 0367 ui->pulse(pulse_type); 0368 } 0369 0370 /************************************************* 0371 * Set the configuration object * 0372 *************************************************/ 0373 Config &Library_State::config() const 0374 { 0375 if (!config_obj) 0376 throw Invalid_State("Library_State::config(): No config set"); 0377 0378 return (*config_obj); 0379 } 0380 0381 #endif 0382 0383 /************************************************* 0384 * Load modules * 0385 *************************************************/ 0386 void Library_State::load(Modules &modules) 0387 { 0388 #ifndef BOTAN_TOOLS_ONLY 0389 set_timer(modules.timer()); 0390 set_transcoder(modules.transcoder()); 0391 #endif 0392 0393 std::vector<Allocator *> mod_allocs = modules.allocators(); 0394 for (Allocator *mod_alloc : mod_allocs) 0395 add_allocator(mod_alloc); 0396 0397 set_default_allocator(modules.default_allocator()); 0398 0399 #ifndef BOTAN_TOOLS_ONLY 0400 std::vector<Engine *> mod_engines = modules.engines(); 0401 for (u32bit j = 0; j != mod_engines.size(); ++j) { 0402 Named_Mutex_Holder lock("engine"); 0403 engines.push_back(mod_engines[j]); 0404 } 0405 0406 std::vector<EntropySource *> sources = modules.entropy_sources(); 0407 for (u32bit j = 0; j != sources.size(); ++j) 0408 add_entropy_source(sources[j]); 0409 #endif 0410 } 0411 0412 /************************************************* 0413 * Library_State Constructor * 0414 *************************************************/ 0415 Library_State::Library_State(Mutex_Factory *mutex_factory) 0416 { 0417 if (!mutex_factory) 0418 throw Exception("Library_State: no mutex found"); 0419 0420 this->mutex_factory = mutex_factory; 0421 #ifndef BOTAN_TOOLS_ONLY 0422 this->timer = new Timer(); 0423 this->transcoder = 0; 0424 this->config_obj = new Config(); 0425 #endif 0426 0427 #ifndef BOTAN_TOOLS_ONLY 0428 locks["settings"] = get_mutex(); 0429 #endif 0430 locks["allocator"] = get_mutex(); 0431 #ifndef BOTAN_TOOLS_ONLY 0432 locks["rng"] = get_mutex(); 0433 locks["engine"] = get_mutex(); 0434 rng = 0; 0435 #endif 0436 cached_default_allocator = nullptr; 0437 #ifndef BOTAN_TOOLS_ONLY 0438 x509_state_obj = 0; 0439 ui = 0; 0440 #endif 0441 } 0442 0443 /************************************************* 0444 * Library_State Destructor * 0445 *************************************************/ 0446 static void delete_lock(std::pair<const std::string, Mutex *> &pair) 0447 { 0448 delete pair.second; 0449 } 0450 0451 Library_State::~Library_State() 0452 { 0453 #ifndef BOTAN_TOOLS_ONLY 0454 delete x509_state_obj; 0455 delete transcoder; 0456 delete rng; 0457 delete timer; 0458 delete config_obj; 0459 delete ui; 0460 0461 std::for_each(entropy_sources.begin(), entropy_sources.end(), del_fun<EntropySource>()); 0462 std::for_each(engines.begin(), engines.end(), del_fun<Engine>()); 0463 #endif 0464 0465 cached_default_allocator = nullptr; 0466 0467 for (Allocator *allocator : allocators) { 0468 allocator->destroy(); 0469 delete allocator; 0470 } 0471 0472 std::for_each(locks.begin(), locks.end(), delete_lock); 0473 0474 delete mutex_factory; 0475 } 0476 0477 } 0478 } // WRAPNS_LINE