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