diff options
author | David Clark <david.a.clark@nokia.com> | 2010-11-18 16:20:48 +1000 |
---|---|---|
committer | David Clark <david.a.clark@nokia.com> | 2010-11-18 16:20:48 +1000 |
commit | c223232bc15106750da632598047a35ad3762723 (patch) | |
tree | 403f7aa2c3a5a912edce6feae869046c89d29178 /old/botan/src/algo_factory | |
parent | b984b0b62076067f1f75db5a7eda5aaa2cdaad2a (diff) |
Diffstat (limited to 'old/botan/src/algo_factory')
-rw-r--r-- | old/botan/src/algo_factory/algo_cache.h | 224 | ||||
-rw-r--r-- | old/botan/src/algo_factory/algo_factory.cpp | 286 | ||||
-rw-r--r-- | old/botan/src/algo_factory/algo_factory.h | 132 | ||||
-rw-r--r-- | old/botan/src/algo_factory/info.txt | 21 | ||||
-rw-r--r-- | old/botan/src/algo_factory/prov_weight.cpp | 33 |
5 files changed, 696 insertions, 0 deletions
diff --git a/old/botan/src/algo_factory/algo_cache.h b/old/botan/src/algo_factory/algo_cache.h new file mode 100644 index 0000000..17ea996 --- /dev/null +++ b/old/botan/src/algo_factory/algo_cache.h @@ -0,0 +1,224 @@ +/** +* An algorithm cache (used by Algorithm_Factory) +*/ + +#ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ +#define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ + +#include <botan/mutex.h> +#include <botan/stl_util.h> +#include <string> +#include <vector> +#include <map> + +namespace Botan { + +/** +* @param prov_name a provider name +* @return weight for this provider +*/ +u32bit static_provider_weight(const std::string& prov_name); + +/** +* Algorithm_Cache (used by Algorithm_Factory) +*/ +template<typename T> +class Algorithm_Cache + { + public: + const T* get(const std::string& algo_spec, + const std::string& pref_provider); + + /** + * Add a new algorithm implementation to the cache + */ + void add(T* algo, + const std::string& requested_name, + const std::string& provider_name); + + /** + * Set the preferred provider + */ + void set_preferred_provider(const std::string& algo_spec, + const std::string& provider); + + /** + * Return the list of providers of this algorithm + */ + std::vector<std::string> providers_of(const std::string& algo_name); + + Algorithm_Cache(Mutex* m) : mutex(m) {} + ~Algorithm_Cache(); + private: + typedef typename std::map<std::string, std::map<std::string, T*> >::iterator + algorithms_iterator; + + typedef typename std::map<std::string, T*>::iterator provider_iterator; + + algorithms_iterator find_algorithm(const std::string& algo_spec); + + Mutex* mutex; + std::map<std::string, std::string> aliases; + std::map<std::string, std::string> pref_providers; + std::map<std::string, std::map<std::string, T*> > algorithms; + }; + +/** +* Look for an algorithm implementation in the cache, also checking aliases +* Assumes object lock is held +*/ +template<typename T> +typename Algorithm_Cache<T>::algorithms_iterator +Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec) + { + algorithms_iterator algo = algorithms.find(algo_spec); + + // Not found? Check if a known alias + if(algo == algorithms.end()) + { + std::map<std::string, std::string>::const_iterator alias = + aliases.find(algo_spec); + + if(alias != aliases.end()) + algo = algorithms.find(alias->second); + } + + return algo; + } + +/** +* Look for an algorithm implementation by a particular provider +*/ +template<typename T> +const T* Algorithm_Cache<T>::get(const std::string& algo_spec, + const std::string& requested_provider) + { + Mutex_Holder lock(mutex); + + algorithms_iterator algo = find_algorithm(algo_spec); + if(algo == algorithms.end()) // algo not found at all (no providers) + return 0; + + // If a provider is requested specifically, return it or fail entirely + if(requested_provider != "") + { + provider_iterator prov = algo->second.find(requested_provider); + if(prov != algo->second.end()) + return prov->second; + return 0; + } + + const T* prototype = 0; + std::string prototype_provider; + u32bit prototype_prov_weight = 0; + + const std::string pref_provider = search_map(pref_providers, algo_spec); + + for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i) + { + const std::string prov_name = i->first; + const u32bit prov_weight = static_provider_weight(prov_name); + + // preferred prov exists, return immediately + if(prov_name == pref_provider) + return i->second; + + if(prototype == 0 || prov_weight > prototype_prov_weight) + { + prototype = i->second; + prototype_provider = i->first; + prototype_prov_weight = prov_weight; + } + } + + return prototype; + } + +/** +* Add an implementation to the cache +*/ +template<typename T> +void Algorithm_Cache<T>::add(T* algo, + const std::string& requested_name, + const std::string& provider) + { + if(!algo) + return; + + Mutex_Holder lock(mutex); + + delete algorithms[algo->name()][provider]; + algorithms[algo->name()][provider] = algo; + + if(algo->name() != requested_name && + aliases.find(requested_name) == aliases.end()) + { + aliases[requested_name] = algo->name(); + } + } + +/** +* Find the providers of this algo (if any) +*/ +template<typename T> std::vector<std::string> +Algorithm_Cache<T>::providers_of(const std::string& algo_name) + { + Mutex_Holder lock(mutex); + + std::vector<std::string> providers; + + algorithms_iterator algo = find_algorithm(algo_name); + + if(algo != algorithms.end()) + { + provider_iterator provider = algo->second.begin(); + + while(provider != algo->second.end()) + { + providers.push_back(provider->first); + ++provider; + } + } + + return providers; + } + +/** +* Set the preferred provider for an algorithm +*/ +template<typename T> +void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec, + const std::string& provider) + { + Mutex_Holder lock(mutex); + + pref_providers[algo_spec] = provider; + } + +/** +* Algorithm_Cache<T> Destructor +*/ +template<typename T> +Algorithm_Cache<T>::~Algorithm_Cache() + { + algorithms_iterator algo = algorithms.begin(); + + while(algo != algorithms.end()) + { + provider_iterator provider = algo->second.begin(); + + while(provider != algo->second.end()) + { + delete provider->second; + ++provider; + } + + ++algo; + } + + delete mutex; + } + +} + +#endif diff --git a/old/botan/src/algo_factory/algo_factory.cpp b/old/botan/src/algo_factory/algo_factory.cpp new file mode 100644 index 0000000..269c58c --- /dev/null +++ b/old/botan/src/algo_factory/algo_factory.cpp @@ -0,0 +1,286 @@ +/* +Algorithm Factory +(C) 2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/algo_factory.h> +#include <botan/algo_cache.h> +#include <botan/stl_util.h> +#include <botan/engine.h> +#include <botan/exceptn.h> + +#include <botan/block_cipher.h> +#include <botan/stream_cipher.h> +#include <botan/hash.h> +#include <botan/mac.h> + +#include <algorithm> + +namespace Botan { + +namespace { + +/** +* Template functions for the factory prototype/search algorithm +*/ +template<typename T> +T* engine_get_algo(Engine* engine, const SCAN_Name& request, + Algorithm_Factory& af) + { return 0; } + +template<> +BlockCipher* engine_get_algo(Engine* engine, const SCAN_Name& request, + Algorithm_Factory& af) + { return engine->find_block_cipher(request, af); } + +template<> +StreamCipher* engine_get_algo(Engine* engine, const SCAN_Name& request, + Algorithm_Factory& af) + { return engine->find_stream_cipher(request, af); } + +template<> +HashFunction* engine_get_algo(Engine* engine, const SCAN_Name& request, + Algorithm_Factory& af) + { return engine->find_hash(request, af); } + +template<> +MessageAuthenticationCode* engine_get_algo(Engine* engine, + const SCAN_Name& request, + Algorithm_Factory& af) + { return engine->find_mac(request, af); } + +template<typename T> +const T* factory_prototype(const std::string& algo_spec, + const std::string& provider, + const std::vector<Engine*>& engines, + Algorithm_Factory& af, + Algorithm_Cache<T>* cache) + { + if(const T* cache_hit = cache->get(algo_spec, provider)) + return cache_hit; + + SCAN_Name scan_name(algo_spec); + for(u32bit i = 0; i != engines.size(); ++i) + { + if(provider == "" || engines[i]->provider_name() == provider) + { + T* impl = engine_get_algo<T>(engines[i], scan_name, af); + if(impl) + cache->add(impl, algo_spec, engines[i]->provider_name()); + } + } + + return cache->get(algo_spec, provider); + } + +} + +/** +* Setup caches +*/ +Algorithm_Factory::Algorithm_Factory(const std::vector<Engine*>& engines_in, + Mutex_Factory& mf) + { + engines = engines_in; + + block_cipher_cache = new Algorithm_Cache<BlockCipher>(mf.make()); + stream_cipher_cache = new Algorithm_Cache<StreamCipher>(mf.make()); + hash_cache = new Algorithm_Cache<HashFunction>(mf.make()); + mac_cache = new Algorithm_Cache<MessageAuthenticationCode>(mf.make()); + } + +/** +* Delete all engines +*/ +Algorithm_Factory::~Algorithm_Factory() + { + std::for_each(engines.begin(), engines.end(), del_fun<Engine>()); + + delete block_cipher_cache; + delete stream_cipher_cache; + delete hash_cache; + delete mac_cache; + } + +/** +* Set the preferred provider for an algorithm +*/ +void Algorithm_Factory::set_preferred_provider(const std::string& algo_spec, + const std::string& provider) + { + if(prototype_block_cipher(algo_spec)) + block_cipher_cache->set_preferred_provider(algo_spec, provider); + else if(prototype_stream_cipher(algo_spec)) + stream_cipher_cache->set_preferred_provider(algo_spec, provider); + else if(prototype_hash_function(algo_spec)) + hash_cache->set_preferred_provider(algo_spec, provider); + else if(prototype_mac(algo_spec)) + mac_cache->set_preferred_provider(algo_spec, provider); + } + +/** +* Get an engine out of the list +*/ +Engine* Algorithm_Factory::get_engine_n(u32bit n) const + { + if(n >= engines.size()) + return 0; + return engines[n]; + } + +/** +* Return the possible providers of a request +* Note: assumes you don't have different types by the same name +*/ +std::vector<std::string> +Algorithm_Factory::providers_of(const std::string& algo_spec) + { + /* The checks with if(prototype_X(algo_spec)) have the effect of + forcing a full search, since otherwise there might not be any + providers at all in the cache. + */ + + if(prototype_block_cipher(algo_spec)) + return block_cipher_cache->providers_of(algo_spec); + else if(prototype_stream_cipher(algo_spec)) + return stream_cipher_cache->providers_of(algo_spec); + else if(prototype_hash_function(algo_spec)) + return hash_cache->providers_of(algo_spec); + else if(prototype_mac(algo_spec)) + return mac_cache->providers_of(algo_spec); + else + return std::vector<std::string>(); + } + +/** +* Return the prototypical block cipher corresponding to this request +*/ +const BlockCipher* +Algorithm_Factory::prototype_block_cipher(const std::string& algo_spec, + const std::string& provider) + { + return factory_prototype<BlockCipher>(algo_spec, provider, engines, + *this, block_cipher_cache); + } + +/** +* Return the prototypical stream cipher corresponding to this request +*/ +const StreamCipher* +Algorithm_Factory::prototype_stream_cipher(const std::string& algo_spec, + const std::string& provider) + { + return factory_prototype<StreamCipher>(algo_spec, provider, engines, + *this, stream_cipher_cache); + } + +/** +* Return the prototypical object corresponding to this request (if found) +*/ +const HashFunction* +Algorithm_Factory::prototype_hash_function(const std::string& algo_spec, + const std::string& provider) + { + return factory_prototype<HashFunction>(algo_spec, provider, engines, + *this, hash_cache); + } + +/** +* Return the prototypical object corresponding to this request +*/ +const MessageAuthenticationCode* +Algorithm_Factory::prototype_mac(const std::string& algo_spec, + const std::string& provider) + { + return factory_prototype<MessageAuthenticationCode>(algo_spec, provider, + engines, + *this, mac_cache); + } + +/** +* Return a new block cipher corresponding to this request +*/ +BlockCipher* +Algorithm_Factory::make_block_cipher(const std::string& algo_spec, + const std::string& provider) + { + if(const BlockCipher* proto = prototype_block_cipher(algo_spec, provider)) + return proto->clone(); + throw Algorithm_Not_Found(algo_spec); + } + +/** +* Return a new stream cipher corresponding to this request +*/ +StreamCipher* +Algorithm_Factory::make_stream_cipher(const std::string& algo_spec, + const std::string& provider) + { + if(const StreamCipher* proto = prototype_stream_cipher(algo_spec, provider)) + return proto->clone(); + throw Algorithm_Not_Found(algo_spec); + } + +/** +* Return a new object corresponding to this request +*/ +HashFunction* +Algorithm_Factory::make_hash_function(const std::string& algo_spec, + const std::string& provider) + { + if(const HashFunction* proto = prototype_hash_function(algo_spec, provider)) + return proto->clone(); + throw Algorithm_Not_Found(algo_spec); + } + +/** +* Return a new object corresponding to this request +*/ +MessageAuthenticationCode* +Algorithm_Factory::make_mac(const std::string& algo_spec, + const std::string& provider) + { + if(const MessageAuthenticationCode* proto = prototype_mac(algo_spec, provider)) + return proto->clone(); + throw Algorithm_Not_Found(algo_spec); + } + +/** +* Add a new block cipher +*/ +void Algorithm_Factory::add_block_cipher(BlockCipher* block_cipher, + const std::string& provider) + { + block_cipher_cache->add(block_cipher, block_cipher->name(), provider); + } + +/** +* Add a new stream cipher +*/ +void Algorithm_Factory::add_stream_cipher(StreamCipher* stream_cipher, + const std::string& provider) + { + stream_cipher_cache->add(stream_cipher, stream_cipher->name(), provider); + } + +/** +* Add a new hash +*/ +void Algorithm_Factory::add_hash_function(HashFunction* hash, + const std::string& provider) + { + hash_cache->add(hash, hash->name(), provider); + } + +/** +* Add a new mac +*/ +void Algorithm_Factory::add_mac(MessageAuthenticationCode* mac, + const std::string& provider) + { + mac_cache->add(mac, mac->name(), provider); + } + +} diff --git a/old/botan/src/algo_factory/algo_factory.h b/old/botan/src/algo_factory/algo_factory.h new file mode 100644 index 0000000..73e5920 --- /dev/null +++ b/old/botan/src/algo_factory/algo_factory.h @@ -0,0 +1,132 @@ +/** +* Algorithm Factory +* (C) 2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_ALGORITHM_FACTORY_H__ +#define BOTAN_ALGORITHM_FACTORY_H__ + +#include <botan/mutex.h> +#include <string> +#include <vector> + +namespace Botan { + +/** +* Forward declarations (don't need full definitions here) +*/ +class BlockCipher; +class StreamCipher; +class HashFunction; +class MessageAuthenticationCode; + +template<typename T> class Algorithm_Cache; + +class Engine; + +/** +* Algorithm Factory +*/ +class BOTAN_DLL Algorithm_Factory + { + public: + /** + * Constructor + * @param engines_in the list of engines to use + * @param mf a mutex factory + */ + Algorithm_Factory(const std::vector<Engine*>& engines_in, + Mutex_Factory& mf); + + /** + * Destructor + */ + ~Algorithm_Factory(); + + /* + * Provider management + */ + std::vector<std::string> providers_of(const std::string& algo_spec); + + void set_preferred_provider(const std::string& algo_spec, + const std::string& provider); + + /* + * Block cipher operations + */ + const BlockCipher* + prototype_block_cipher(const std::string& algo_spec, + const std::string& provider = ""); + + BlockCipher* make_block_cipher(const std::string& algo_spec, + const std::string& provider = ""); + + void add_block_cipher(BlockCipher* hash, const std::string& provider); + + /* + * Stream cipher operations + */ + const StreamCipher* + prototype_stream_cipher(const std::string& algo_spec, + const std::string& provider = ""); + + StreamCipher* make_stream_cipher(const std::string& algo_spec, + const std::string& provider = ""); + + void add_stream_cipher(StreamCipher* hash, const std::string& provider); + + /* + * Hash function operations + */ + const HashFunction* + prototype_hash_function(const std::string& algo_spec, + const std::string& provider = ""); + + HashFunction* make_hash_function(const std::string& algo_spec, + const std::string& provider = ""); + + void add_hash_function(HashFunction* hash, const std::string& provider); + + /* + * MAC operations + */ + const MessageAuthenticationCode* + prototype_mac(const std::string& algo_spec, + const std::string& provider = ""); + + MessageAuthenticationCode* make_mac(const std::string& algo_spec, + const std::string& provider = ""); + + void add_mac(MessageAuthenticationCode* mac, + const std::string& provider); + + /* + * Deprecated + */ + class BOTAN_DLL Engine_Iterator + { + public: + class Engine* next() { return af.get_engine_n(n++); } + Engine_Iterator(const Algorithm_Factory& a) : af(a) { n = 0; } + private: + const Algorithm_Factory& af; + u32bit n; + }; + friend class Engine_Iterator; + + private: + class Engine* get_engine_n(u32bit) const; + + std::vector<class Engine*> engines; + + Algorithm_Cache<BlockCipher>* block_cipher_cache; + Algorithm_Cache<StreamCipher>* stream_cipher_cache; + Algorithm_Cache<HashFunction>* hash_cache; + Algorithm_Cache<MessageAuthenticationCode>* mac_cache; + }; + +} + +#endif diff --git a/old/botan/src/algo_factory/info.txt b/old/botan/src/algo_factory/info.txt new file mode 100644 index 0000000..dfc4223 --- /dev/null +++ b/old/botan/src/algo_factory/info.txt @@ -0,0 +1,21 @@ +realname "Algorithm Factory" + +load_on auto + +define ALGORITHM_FACTORY + +<add> +algo_factory.cpp +algo_factory.h +algo_cache.h +prov_weight.cpp +</add> + +<requires> +block +engine +hash +mac +mutex +stream +</requires> diff --git a/old/botan/src/algo_factory/prov_weight.cpp b/old/botan/src/algo_factory/prov_weight.cpp new file mode 100644 index 0000000..a55a8b1 --- /dev/null +++ b/old/botan/src/algo_factory/prov_weight.cpp @@ -0,0 +1,33 @@ +/** +* Default provider weights for Algorithm_Cache +* (C) 2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/algo_cache.h> + +namespace Botan { + +/** +* Return a static provider weighing +*/ +u32bit static_provider_weight(const std::string& prov_name) + { + /* + * Prefer asm over C++, but prefer anything over OpenSSL or GNU MP; to use + * them, set the provider explicitly for the algorithms you want + */ + + if(prov_name == "core") return 5; + if(prov_name == "ia32") return 6; + if(prov_name == "amd64") return 7; + if(prov_name == "sse2") return 8; + + if(prov_name == "openssl") return 2; + if(prov_name == "gmp") return 1; + + return 0; // other + } + +} |