aboutsummaryrefslogtreecommitdiffstats
path: root/src/algo_factory
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-11-11 19:08:06 +0000
committerlloyd <[email protected]>2008-11-11 19:08:06 +0000
commit25d7b7aa9e9896df45f12fa59db4c44411bc21f0 (patch)
treec7ef12dbca65449bde6d4f5183dc2f400914e426 /src/algo_factory
parent1954e73dbf4e4984d33a45d6ce05ee5aecb84714 (diff)
Use cache in Algorithm_Factory for ciphers
Diffstat (limited to 'src/algo_factory')
-rw-r--r--src/algo_factory/algo_cache.h64
-rw-r--r--src/algo_factory/algo_factory.cpp173
-rw-r--r--src/algo_factory/algo_factory.h16
3 files changed, 124 insertions, 129 deletions
diff --git a/src/algo_factory/algo_cache.h b/src/algo_factory/algo_cache.h
index c6d2ebdac..dafa59c3e 100644
--- a/src/algo_factory/algo_cache.h
+++ b/src/algo_factory/algo_cache.h
@@ -22,43 +22,60 @@ class Algorithm_Cache
const std::string& requested_name,
const std::string& provider);
+ 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::map<std::string, T*> > algorithms;
- typedef typename std::map<std::string, std::map<std::string, T*> >::iterator algorithms_iterator;
- typedef typename std::map<std::string, T*>::iterator provider_iterator;
};
/**
-* Look for an algorithm implementation in the cache
+* Look for an algorithm implementation in the cache, also checking aliases
*/
template<typename T>
-const T* Algorithm_Cache<T>::get(const SCAN_Name& request)
+typename Algorithm_Cache<T>::algorithms_iterator
+Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec)
{
- Mutex_Holder lock(mutex);
-
- algorithms_iterator algo = algorithms.find(request.as_string());
+ // Assumes mutex is held
+ 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(request.as_string());
+ aliases.find(algo_spec);
if(alias != aliases.end())
algo = algorithms.find(alias->second);
}
- if(algo == algorithms.end())
+ return algo;
+ }
+
+/**
+* Look for an algorithm implementation in the cache
+*/
+template<typename T>
+const T* Algorithm_Cache<T>::get(const SCAN_Name& request)
+ {
+ Mutex_Holder lock(mutex);
+
+ algorithms_iterator algo = find_algorithm(request.as_string());
+ if(algo == algorithms.end()) // not found at all
return 0;
const std::string requested_provider = request.provider();
- if(requested_provider != "")
+ if(requested_provider != "") // If a specific request, allow that provider or core
{
provider_iterator provider = algo->second.find(requested_provider);
@@ -67,6 +84,7 @@ const T* Algorithm_Cache<T>::get(const SCAN_Name& request)
}
else // no specific provider requested: pick one
{
+ printf("No specific provider requested for %s\n", request.as_string().c_str());
provider_iterator provider = algo->second.begin();
while(provider != algo->second.end())
@@ -102,6 +120,32 @@ void Algorithm_Cache<T>::add(T* algo,
}
/**
+* 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;
+ }
+
+/**
* Algorithm_Cache<T> Destructor
*/
template<typename T>
diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp
index 4f137d636..e2debf7c9 100644
--- a/src/algo_factory/algo_factory.cpp
+++ b/src/algo_factory/algo_factory.cpp
@@ -19,7 +19,10 @@ namespace Botan {
Algorithm_Factory::Algorithm_Factory(Mutex_Factory& mf) :
mutex_factory(mf),
- hash_cache(mf.make())
+ block_cipher_cache(mf.make()),
+ stream_cipher_cache(mf.make()),
+ hash_cache(mf.make()),
+ mac_cache(mf.make())
{
}
@@ -56,125 +59,95 @@ Engine* Algorithm_Factory::get_engine_n(u32bit n) const
* Return the possible providers of a request
*/
std::vector<std::string>
-Algorithm_Factory::providers_of(const SCAN_Name& request)
+Algorithm_Factory::providers_of(const std::string& algo_name)
{
- std::vector<std::string> providers;
- for(u32bit i = 0; i != engines.size(); ++i)
- {
- std::string provider = engines[i]->provider_name();
- if(request.provider_allowed(provider))
- {
- if(engines[i]->prototype_block_cipher(request, *this) ||
- engines[i]->prototype_stream_cipher(request, *this) ||
- engines[i]->prototype_hash_function(request, *this) ||
- engines[i]->prototype_mac(request, *this))
- {
- providers.push_back(provider);
- }
- }
- }
+ if(prototype_block_cipher(algo_name))
+ return block_cipher_cache.providers_of(algo_name);
+
+ if(prototype_stream_cipher(algo_name))
+ return stream_cipher_cache.providers_of(algo_name);
+
+ if(prototype_hash_function(algo_name))
+ return hash_cache.providers_of(algo_name);
- return providers;
+ if(prototype_mac(algo_name))
+ return mac_cache.providers_of(algo_name);
+
+ return std::vector<std::string>();
}
/**
-* Return the prototypical object cooresponding to this request
+* Return the prototypical block cipher cooresponding to this request
*/
const BlockCipher*
Algorithm_Factory::prototype_block_cipher(const SCAN_Name& request)
{
+ if(const BlockCipher* cache_hit = block_cipher_cache.get(request))
+ return cache_hit;
+
for(u32bit i = 0; i != engines.size(); ++i)
{
- if(request.provider_allowed(engines[i]->provider_name()))
- {
- const BlockCipher* algo =
- engines[i]->prototype_block_cipher(request, *this);
-
- if(algo)
- return algo;
- }
+ if(BlockCipher* impl = engines[i]->find_block_cipher(request, *this))
+ block_cipher_cache.add(impl, request.as_string(), engines[i]->provider_name());
}
- return 0;
+ return block_cipher_cache.get(request);
}
/**
-* Return a new object cooresponding to this request
+* Return a new block cipher cooresponding to this request
*/
BlockCipher* Algorithm_Factory::make_block_cipher(const SCAN_Name& request)
{
- const BlockCipher* prototype = prototype_block_cipher(request);
- if(prototype)
+ if(const BlockCipher* prototype = prototype_block_cipher(request))
return prototype->clone();
-
throw Algorithm_Not_Found(request.as_string());
}
/**
-* Add a new object
+* Add a new block cipher
*/
-void Algorithm_Factory::add_block_cipher(BlockCipher* hash)
+void Algorithm_Factory::add_block_cipher(BlockCipher* block_cipher,
+ const std::string& provider)
{
- for(u32bit i = 0; i != engines.size(); ++i)
- {
- if(engines[i]->can_add_algorithms())
- {
- engines[i]->add_algorithm(hash);
- return;
- }
- }
-
- throw Exception("Algorithm_Factory::add_block_cipher: No engine found");
+ block_cipher_cache.add(block_cipher, block_cipher->name(), provider);
}
/**
-* Return the prototypical object cooresponding to this request
+* Return the prototypical stream cipher cooresponding to this request
*/
const StreamCipher*
Algorithm_Factory::prototype_stream_cipher(const SCAN_Name& request)
{
+ if(const StreamCipher* cache_hit = stream_cipher_cache.get(request))
+ return cache_hit;
+
for(u32bit i = 0; i != engines.size(); ++i)
{
- if(request.provider_allowed(engines[i]->provider_name()))
- {
- const StreamCipher* algo =
- engines[i]->prototype_stream_cipher(request, *this);
-
- if(algo)
- return algo;
- }
+ if(StreamCipher* impl = engines[i]->find_stream_cipher(request, *this))
+ stream_cipher_cache.add(impl, request.as_string(), engines[i]->provider_name());
}
- return 0;
+ return stream_cipher_cache.get(request);
}
/**
-* Return a new object cooresponding to this request
+* Return a new stream cipher cooresponding to this request
*/
StreamCipher* Algorithm_Factory::make_stream_cipher(const SCAN_Name& request)
{
- const StreamCipher* prototype = prototype_stream_cipher(request);
- if(prototype)
+ if(const StreamCipher* prototype = prototype_stream_cipher(request))
return prototype->clone();
-
throw Algorithm_Not_Found(request.as_string());
}
/**
-* Add a new object
+* Add a new stream cipher
*/
-void Algorithm_Factory::add_stream_cipher(StreamCipher* hash)
+void Algorithm_Factory::add_stream_cipher(StreamCipher* stream_cipher,
+ const std::string& provider)
{
- for(u32bit i = 0; i != engines.size(); ++i)
- {
- if(engines[i]->can_add_algorithms())
- {
- engines[i]->add_algorithm(hash);
- return;
- }
- }
-
- throw Exception("Algorithm_Factory::add_stream_cipher: No engine found");
+ stream_cipher_cache.add(stream_cipher, stream_cipher->name(), provider);
}
/**
@@ -183,16 +156,13 @@ void Algorithm_Factory::add_stream_cipher(StreamCipher* hash)
const HashFunction*
Algorithm_Factory::prototype_hash_function(const SCAN_Name& request)
{
- const HashFunction* cache_hit = hash_cache.get(request);
- if(cache_hit)
+ if(const HashFunction* cache_hit = hash_cache.get(request))
return cache_hit;
for(u32bit i = 0; i != engines.size(); ++i)
{
if(HashFunction* impl = engines[i]->find_hash(request, *this))
- {
hash_cache.add(impl, request.as_string(), engines[i]->provider_name());
- }
}
return hash_cache.get(request);
@@ -203,28 +173,18 @@ Algorithm_Factory::prototype_hash_function(const SCAN_Name& request)
*/
HashFunction* Algorithm_Factory::make_hash_function(const SCAN_Name& request)
{
- const HashFunction* prototype = prototype_hash_function(request);
- if(prototype)
+ if(const HashFunction* prototype = prototype_hash_function(request))
return prototype->clone();
-
throw Algorithm_Not_Found(request.as_string());
}
/**
-* Add a new object
+* Add a new hash
*/
-void Algorithm_Factory::add_hash_function(HashFunction* hash)
+void Algorithm_Factory::add_hash_function(HashFunction* hash,
+ const std::string& provider)
{
- for(u32bit i = 0; i != engines.size(); ++i)
- {
- if(engines[i]->can_add_algorithms())
- {
- engines[i]->add_algorithm(hash);
- return;
- }
- }
-
- throw Exception("Algorithm_Factory::add_hash_function: No engine found");
+ hash_cache.add(hash, hash->name(), provider);
}
/**
@@ -233,19 +193,16 @@ void Algorithm_Factory::add_hash_function(HashFunction* hash)
const MessageAuthenticationCode*
Algorithm_Factory::prototype_mac(const SCAN_Name& request)
{
+ if(const MessageAuthenticationCode* cache_hit = mac_cache.get(request))
+ return cache_hit;
+
for(u32bit i = 0; i != engines.size(); ++i)
{
- if(request.provider_allowed(engines[i]->provider_name()))
- {
- const MessageAuthenticationCode* algo =
- engines[i]->prototype_mac(request, *this);
-
- if(algo)
- return algo;
- }
+ if(MessageAuthenticationCode* impl = engines[i]->find_mac(request, *this))
+ mac_cache.add(impl, request.as_string(), engines[i]->provider_name());
}
- return 0;
+ return mac_cache.get(request);
}
/**
@@ -254,28 +211,18 @@ Algorithm_Factory::prototype_mac(const SCAN_Name& request)
MessageAuthenticationCode*
Algorithm_Factory::make_mac(const SCAN_Name& request)
{
- const MessageAuthenticationCode* prototype = prototype_mac(request);
- if(prototype)
+ if(const MessageAuthenticationCode* prototype = prototype_mac(request))
return prototype->clone();
-
throw Algorithm_Not_Found(request.as_string());
}
/**
-* Add a new object
+* Add a new mac
*/
-void Algorithm_Factory::add_mac(MessageAuthenticationCode* hash)
+void Algorithm_Factory::add_mac(MessageAuthenticationCode* mac,
+ const std::string& provider)
{
- for(u32bit i = 0; i != engines.size(); ++i)
- {
- if(engines[i]->can_add_algorithms())
- {
- engines[i]->add_algorithm(hash);
- return;
- }
- }
-
- throw Exception("Algorithm_Factory::add_mac: No engine found");
+ mac_cache.add(mac, mac->name(), provider);
}
}
diff --git a/src/algo_factory/algo_factory.h b/src/algo_factory/algo_factory.h
index 2bbfde7d1..64b2128ec 100644
--- a/src/algo_factory/algo_factory.h
+++ b/src/algo_factory/algo_factory.h
@@ -45,35 +45,39 @@ class BOTAN_DLL Algorithm_Factory
};
friend class Engine_Iterator;
- std::vector<std::string> providers_of(const SCAN_Name& request);
+ std::vector<std::string> providers_of(const std::string& algo_spec);
// Block cipher operations
const BlockCipher* prototype_block_cipher(const SCAN_Name& request);
BlockCipher* make_block_cipher(const SCAN_Name& request);
- void add_block_cipher(BlockCipher* hash);
+ void add_block_cipher(BlockCipher* hash, const std::string& provider);
// Stream cipher operations
const StreamCipher* prototype_stream_cipher(const SCAN_Name& request);
StreamCipher* make_stream_cipher(const SCAN_Name& request);
- void add_stream_cipher(StreamCipher* hash);
+ void add_stream_cipher(StreamCipher* hash, const std::string& provider);
// Hash function operations
const HashFunction* prototype_hash_function(const SCAN_Name& request);
HashFunction* make_hash_function(const SCAN_Name& request);
- void add_hash_function(HashFunction* hash);
+ void add_hash_function(HashFunction* hash, const std::string& provider);
// MAC operations
const MessageAuthenticationCode* prototype_mac(const SCAN_Name& request);
MessageAuthenticationCode* make_mac(const SCAN_Name& request);
- void add_mac(MessageAuthenticationCode* mac);
-
+ void add_mac(MessageAuthenticationCode* mac,
+ const std::string& provider);
private:
Mutex_Factory& mutex_factory;
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;
};
}