summaryrefslogtreecommitdiffstats
path: root/old/botan/src/algo_factory
diff options
context:
space:
mode:
authorDavid Clark <david.a.clark@nokia.com>2010-11-18 16:20:48 +1000
committerDavid Clark <david.a.clark@nokia.com>2010-11-18 16:20:48 +1000
commitc223232bc15106750da632598047a35ad3762723 (patch)
tree403f7aa2c3a5a912edce6feae869046c89d29178 /old/botan/src/algo_factory
parentb984b0b62076067f1f75db5a7eda5aaa2cdaad2a (diff)
Mark repository as deprecatedHEADmaster
Diffstat (limited to 'old/botan/src/algo_factory')
-rw-r--r--old/botan/src/algo_factory/algo_cache.h224
-rw-r--r--old/botan/src/algo_factory/algo_factory.cpp286
-rw-r--r--old/botan/src/algo_factory/algo_factory.h132
-rw-r--r--old/botan/src/algo_factory/info.txt21
-rw-r--r--old/botan/src/algo_factory/prov_weight.cpp33
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
+ }
+
+}