Botan 1.10.17
algo_factory.cpp
Go to the documentation of this file.
1/*
2* Algorithm Factory
3* (C) 2008-2010 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#include <botan/algo_factory.h>
9#include <botan/internal/algo_cache.h>
10#include <botan/internal/stl_util.h>
11#include <botan/engine.h>
12#include <botan/exceptn.h>
13
14#include <botan/block_cipher.h>
15#include <botan/stream_cipher.h>
16#include <botan/hash.h>
17#include <botan/mac.h>
18#include <botan/pbkdf.h>
19
20#include <algorithm>
21
22namespace Botan {
23
24namespace {
25
26/*
27* Template functions for the factory prototype/search algorithm
28*/
29template<typename T>
30T* engine_get_algo(Engine*,
31 const SCAN_Name&,
33 { return 0; }
34
35template<>
36BlockCipher* engine_get_algo(Engine* engine,
37 const SCAN_Name& request,
39 { return engine->find_block_cipher(request, af); }
40
41template<>
42StreamCipher* engine_get_algo(Engine* engine,
43 const SCAN_Name& request,
45 { return engine->find_stream_cipher(request, af); }
46
47template<>
48HashFunction* engine_get_algo(Engine* engine,
49 const SCAN_Name& request,
51 { return engine->find_hash(request, af); }
52
53template<>
54MessageAuthenticationCode* engine_get_algo(Engine* engine,
55 const SCAN_Name& request,
57 { return engine->find_mac(request, af); }
58
59template<>
60PBKDF* engine_get_algo(Engine* engine,
61 const SCAN_Name& request,
63 { return engine->find_pbkdf(request, af); }
64
65template<typename T>
66const T* factory_prototype(const std::string& algo_spec,
67 const std::string& provider,
68 const std::vector<Engine*>& engines,
70 Algorithm_Cache<T>* cache)
71 {
72 if(const T* cache_hit = cache->get(algo_spec, provider))
73 return cache_hit;
74
75 SCAN_Name scan_name(algo_spec);
76
77 if(scan_name.cipher_mode() != "")
78 return 0;
79
80 for(size_t i = 0; i != engines.size(); ++i)
81 {
82 if(provider == "" || engines[i]->provider_name() == provider)
83 {
84 if(T* impl = engine_get_algo<T>(engines[i], scan_name, af))
85 cache->add(impl, algo_spec, engines[i]->provider_name());
86 }
87 }
88
89 return cache->get(algo_spec, provider);
90 }
91
92}
93
94/*
95* Setup caches
96*/
98 {
99 block_cipher_cache = new Algorithm_Cache<BlockCipher>(mf.make());
100 stream_cipher_cache = new Algorithm_Cache<StreamCipher>(mf.make());
101 hash_cache = new Algorithm_Cache<HashFunction>(mf.make());
103 pbkdf_cache = new Algorithm_Cache<PBKDF>(mf.make());
104 }
105
106/*
107* Delete all engines
108*/
110 {
111 delete block_cipher_cache;
112 delete stream_cipher_cache;
113 delete hash_cache;
114 delete mac_cache;
115 delete pbkdf_cache;
116
117 std::for_each(engines.begin(), engines.end(), del_fun<Engine>());
118 }
119
121 {
122 block_cipher_cache->clear_cache();
123 stream_cipher_cache->clear_cache();
124 hash_cache->clear_cache();
125 mac_cache->clear_cache();
126 pbkdf_cache->clear_cache();
127 }
128
130 {
131 clear_caches();
132 engines.push_back(engine);
133 }
134
135/*
136* Set the preferred provider for an algorithm
137*/
138void Algorithm_Factory::set_preferred_provider(const std::string& algo_spec,
139 const std::string& provider)
140 {
141 if(prototype_block_cipher(algo_spec))
142 block_cipher_cache->set_preferred_provider(algo_spec, provider);
143 else if(prototype_stream_cipher(algo_spec))
144 stream_cipher_cache->set_preferred_provider(algo_spec, provider);
145 else if(prototype_hash_function(algo_spec))
146 hash_cache->set_preferred_provider(algo_spec, provider);
147 else if(prototype_mac(algo_spec))
148 mac_cache->set_preferred_provider(algo_spec, provider);
149 else if(prototype_pbkdf(algo_spec))
150 pbkdf_cache->set_preferred_provider(algo_spec, provider);
151 }
152
153/*
154* Get an engine out of the list
155*/
156Engine* Algorithm_Factory::get_engine_n(size_t n) const
157 {
158 if(n >= engines.size())
159 return 0;
160 return engines[n];
161 }
162
163/*
164* Return the possible providers of a request
165* Note: assumes you don't have different types by the same name
166*/
167std::vector<std::string>
168Algorithm_Factory::providers_of(const std::string& algo_spec)
169 {
170 /* The checks with if(prototype_X(algo_spec)) have the effect of
171 forcing a full search, since otherwise there might not be any
172 providers at all in the cache.
173 */
174
175 if(prototype_block_cipher(algo_spec))
176 return block_cipher_cache->providers_of(algo_spec);
177 else if(prototype_stream_cipher(algo_spec))
178 return stream_cipher_cache->providers_of(algo_spec);
179 else if(prototype_hash_function(algo_spec))
180 return hash_cache->providers_of(algo_spec);
181 else if(prototype_mac(algo_spec))
182 return mac_cache->providers_of(algo_spec);
183 else if(prototype_pbkdf(algo_spec))
184 return pbkdf_cache->providers_of(algo_spec);
185 else
186 return std::vector<std::string>();
187 }
188
189/*
190* Return the prototypical block cipher corresponding to this request
191*/
192const BlockCipher*
193Algorithm_Factory::prototype_block_cipher(const std::string& algo_spec,
194 const std::string& provider)
195 {
196 return factory_prototype<BlockCipher>(algo_spec, provider, engines,
197 *this, block_cipher_cache);
198 }
199
200/*
201* Return the prototypical stream cipher corresponding to this request
202*/
203const StreamCipher*
205 const std::string& provider)
206 {
207 return factory_prototype<StreamCipher>(algo_spec, provider, engines,
208 *this, stream_cipher_cache);
209 }
210
211/*
212* Return the prototypical object corresponding to this request (if found)
213*/
214const HashFunction*
216 const std::string& provider)
217 {
218 return factory_prototype<HashFunction>(algo_spec, provider, engines,
219 *this, hash_cache);
220 }
221
222/*
223* Return the prototypical object corresponding to this request
224*/
226Algorithm_Factory::prototype_mac(const std::string& algo_spec,
227 const std::string& provider)
228 {
229 return factory_prototype<MessageAuthenticationCode>(algo_spec, provider,
230 engines,
231 *this, mac_cache);
232 }
233
234/*
235* Return the prototypical object corresponding to this request
236*/
237const PBKDF*
238Algorithm_Factory::prototype_pbkdf(const std::string& algo_spec,
239 const std::string& provider)
240 {
241 return factory_prototype<PBKDF>(algo_spec, provider,
242 engines,
243 *this, pbkdf_cache);
244 }
245
246/*
247* Return a new block cipher corresponding to this request
248*/
250Algorithm_Factory::make_block_cipher(const std::string& algo_spec,
251 const std::string& provider)
252 {
253 if(const BlockCipher* proto = prototype_block_cipher(algo_spec, provider))
254 return proto->clone();
255 throw Algorithm_Not_Found(algo_spec);
256 }
257
258/*
259* Return a new stream cipher corresponding to this request
260*/
262Algorithm_Factory::make_stream_cipher(const std::string& algo_spec,
263 const std::string& provider)
264 {
265 if(const StreamCipher* proto = prototype_stream_cipher(algo_spec, provider))
266 return proto->clone();
267 throw Algorithm_Not_Found(algo_spec);
268 }
269
270/*
271* Return a new object corresponding to this request
272*/
274Algorithm_Factory::make_hash_function(const std::string& algo_spec,
275 const std::string& provider)
276 {
277 if(const HashFunction* proto = prototype_hash_function(algo_spec, provider))
278 return proto->clone();
279 throw Algorithm_Not_Found(algo_spec);
280 }
281
282/*
283* Return a new object corresponding to this request
284*/
286Algorithm_Factory::make_mac(const std::string& algo_spec,
287 const std::string& provider)
288 {
289 if(const MessageAuthenticationCode* proto = prototype_mac(algo_spec, provider))
290 return proto->clone();
291 throw Algorithm_Not_Found(algo_spec);
292 }
293
294/*
295* Return a new object corresponding to this request
296*/
297PBKDF*
298Algorithm_Factory::make_pbkdf(const std::string& algo_spec,
299 const std::string& provider)
300 {
301 if(const PBKDF* proto = prototype_pbkdf(algo_spec, provider))
302 return proto->clone();
303 throw Algorithm_Not_Found(algo_spec);
304 }
305
306/*
307* Add a new block cipher
308*/
310 const std::string& provider)
311 {
312 block_cipher_cache->add(block_cipher, block_cipher->name(), provider);
313 }
314
315/*
316* Add a new stream cipher
317*/
319 const std::string& provider)
320 {
321 stream_cipher_cache->add(stream_cipher, stream_cipher->name(), provider);
322 }
323
324/*
325* Add a new hash
326*/
328 const std::string& provider)
329 {
330 hash_cache->add(hash, hash->name(), provider);
331 }
332
333/*
334* Add a new mac
335*/
337 const std::string& provider)
338 {
339 mac_cache->add(mac, mac->name(), provider);
340 }
341
342/*
343* Add a new PBKDF
344*/
346 const std::string& provider)
347 {
348 pbkdf_cache->add(pbkdf, pbkdf->name(), provider);
349 }
350
351}
Algorithm_Cache(Mutex *m)
Definition algo_cache.h:74
StreamCipher * make_stream_cipher(const std::string &algo_spec, const std::string &provider="")
void add_hash_function(HashFunction *algo, const std::string &provider)
std::vector< std::string > providers_of(const std::string &algo_spec)
PBKDF * make_pbkdf(const std::string &algo_spec, const std::string &provider="")
void set_preferred_provider(const std::string &algo_spec, const std::string &provider)
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_mac(MessageAuthenticationCode *algo, const std::string &provider)
void add_pbkdf(PBKDF *algo, const std::string &provider)
void add_stream_cipher(StreamCipher *algo, const std::string &provider)
void add_engine(Engine *engine)
MessageAuthenticationCode * make_mac(const std::string &algo_spec, const std::string &provider="")
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
const MessageAuthenticationCode * prototype_mac(const std::string &algo_spec, const std::string &provider="")
void add_block_cipher(BlockCipher *algo, const std::string &provider)
const PBKDF * prototype_pbkdf(const std::string &algo_spec, const std::string &provider="")
const StreamCipher * prototype_stream_cipher(const std::string &algo_spec, const std::string &provider="")
Algorithm_Factory(Mutex_Factory &mf)
BlockCipher * make_block_cipher(const std::string &algo_spec, const std::string &provider="")
virtual std::string name() const =0
virtual BlockCipher * clone() const =0
virtual HashFunction * clone() const =0
virtual std::string name() const =0
virtual MessageAuthenticationCode * clone() const =0
virtual Mutex * make()=0
virtual PBKDF * clone() const =0
virtual StreamCipher * clone() const =0
Algorithm_Not_Found(const std::string &name)
Definition exceptn.h:111