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
22 namespace Botan {
23
24 namespace {
25
26 /*
27 * Template functions for the factory prototype/search algorithm
28 */
29 template<typename T>
30 T* engine_get_algo(Engine*,
31 const SCAN_Name&,
32 Algorithm_Factory&)
33 { return 0; }
34
35 template<>
36 BlockCipher* engine_get_algo(Engine* engine,
37 const SCAN_Name& request,
38 Algorithm_Factory& af)
39 { return engine->find_block_cipher(request, af); }
40
41 template<>
42 StreamCipher* engine_get_algo(Engine* engine,
43 const SCAN_Name& request,
44 Algorithm_Factory& af)
45 { return engine->find_stream_cipher(request, af); }
46
47 template<>
48 HashFunction* engine_get_algo(Engine* engine,
49 const SCAN_Name& request,
50 Algorithm_Factory& af)
51 { return engine->find_hash(request, af); }
52
53 template<>
54 MessageAuthenticationCode* engine_get_algo(Engine* engine,
55 const SCAN_Name& request,
56 Algorithm_Factory& af)
57 { return engine->find_mac(request, af); }
58
59 template<>
60 PBKDF* engine_get_algo(Engine* engine,
61 const SCAN_Name& request,
62 Algorithm_Factory& af)
63 { return engine->find_pbkdf(request, af); }
64
65 template<typename T>
66 const T* factory_prototype(const std::string& algo_spec,
67 const std::string& provider,
68 const std::vector<Engine*>& engines,
69 Algorithm_Factory& af,
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 */
97 Algorithm_Factory::Algorithm_Factory(Mutex_Factory& mf)
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());
102 mac_cache = new Algorithm_Cache<MessageAuthenticationCode>(mf.make());
103 pbkdf_cache = new Algorithm_Cache<PBKDF>(mf.make());
104 }
105
106 /*
107 * Delete all engines
108 */
109 Algorithm_Factory::~Algorithm_Factory()
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
120 void Algorithm_Factory::clear_caches()
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
129 void Algorithm_Factory::add_engine(Engine* engine)
130 {
131 clear_caches();
132 engines.push_back(engine);
133 }
134
135 /*
136 * Set the preferred provider for an algorithm
137 */
138 void 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 */
156 Engine* 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 */
167 std::vector<std::string>
168 Algorithm_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 */
192 const BlockCipher*
193 Algorithm_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 */
203 const StreamCipher*
204 Algorithm_Factory::prototype_stream_cipher(const std::string& algo_spec,
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 */
214 const HashFunction*
215 Algorithm_Factory::prototype_hash_function(const std::string& algo_spec,
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 */
225 const MessageAuthenticationCode*
226 Algorithm_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 */
237 const PBKDF*
238 Algorithm_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 */
249 BlockCipher*
250 Algorithm_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 */
261 StreamCipher*
262 Algorithm_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 */
273 HashFunction*
274 Algorithm_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 */
285 MessageAuthenticationCode*
286 Algorithm_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 */
297 PBKDF*
298 Algorithm_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 */
309 void Algorithm_Factory::add_block_cipher(BlockCipher* block_cipher,
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 */
318 void Algorithm_Factory::add_stream_cipher(StreamCipher* stream_cipher,
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 */
327 void Algorithm_Factory::add_hash_function(HashFunction* hash,
328 const std::string& provider)
329 {
330 hash_cache->add(hash, hash->name(), provider);
331 }
332
333 /*
334 * Add a new mac
335 */
336 void Algorithm_Factory::add_mac(MessageAuthenticationCode* mac,
337 const std::string& provider)
338 {
339 mac_cache->add(mac, mac->name(), provider);
340 }
341
342 /*
343 * Add a new PBKDF
344 */
345 void Algorithm_Factory::add_pbkdf(PBKDF* pbkdf,
346 const std::string& provider)
347 {
348 pbkdf_cache->add(pbkdf, pbkdf->name(), provider);
349 }
350
351 }
Botan::Algorithm_Factory::add_block_cipher
void add_block_cipher(BlockCipher *algo, const std::string &provider)
Definition: algo_factory.cpp:309
Botan::Algorithm_Factory::prototype_pbkdf
const PBKDF * prototype_pbkdf(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:238
Botan::Mutex_Factory
Definition: mutex.h:36
Botan::Algorithm_Factory::make_pbkdf
PBKDF * make_pbkdf(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:298
Botan::BlockCipher::clone
virtual BlockCipher * clone() const =0
Botan::Algorithm_Factory::prototype_block_cipher
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:193
Botan::Algorithm_Factory::add_stream_cipher
void add_stream_cipher(StreamCipher *algo, const std::string &provider)
Definition: algo_factory.cpp:318
Botan::Algorithm_Factory::make_block_cipher
BlockCipher * make_block_cipher(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:250
Botan::MessageAuthenticationCode
Definition: mac.h:20
Botan::Algorithm_Cache
Definition: algo_cache.h:29
Botan::HashFunction::clone
virtual HashFunction * clone() const =0
Botan::Algorithm_Factory::add_hash_function
void add_hash_function(HashFunction *algo, const std::string &provider)
Definition: algo_factory.cpp:327
Botan::Algorithm_Factory::make_mac
MessageAuthenticationCode * make_mac(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:286
Botan::Algorithm_Factory::make_stream_cipher
StreamCipher * make_stream_cipher(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:262
Botan::Algorithm_Factory::add_mac
void add_mac(MessageAuthenticationCode *algo, const std::string &provider)
Definition: algo_factory.cpp:336
Botan::Algorithm_Factory::prototype_hash_function
const HashFunction * prototype_hash_function(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:215
Botan::Mutex_Factory::make
virtual Mutex * make()=0
Botan::Engine
Definition: engine.h:32
Botan::StreamCipher
Definition: stream_cipher.h:18
Botan::Algorithm_Factory::prototype_mac
const MessageAuthenticationCode * prototype_mac(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:226
Botan::Algorithm_Factory::clear_caches
void clear_caches()
Definition: algo_factory.cpp:120
Botan::Algorithm_Factory::Algorithm_Factory
Algorithm_Factory(Mutex_Factory &mf)
Definition: algo_factory.cpp:97
Botan
Definition: algo_base.h:14
Botan::Algorithm::name
virtual std::string name() const =0
Botan::Algorithm_Factory::providers_of
std::vector< std::string > providers_of(const std::string &algo_spec)
Definition: algo_factory.cpp:168
Botan::Algorithm_Factory::make_hash_function
HashFunction * make_hash_function(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:274
Botan::Algorithm_Factory::~Algorithm_Factory
~Algorithm_Factory()
Definition: algo_factory.cpp:109
Botan::HashFunction
Definition: hash.h:20
Botan::del_fun
Definition: stl_util.h:57
Botan::PBKDF::clone
virtual PBKDF * clone() const =0
Botan::Algorithm_Factory::add_engine
void add_engine(Engine *engine)
Definition: algo_factory.cpp:129
Botan::StreamCipher::clone
virtual StreamCipher * clone() const =0
Botan::MessageAuthenticationCode::clone
virtual MessageAuthenticationCode * clone() const =0
Botan::Algorithm_Not_Found
Definition: exceptn.h:109
Botan::Algorithm_Factory::add_pbkdf
void add_pbkdf(PBKDF *algo, const std::string &provider)
Definition: algo_factory.cpp:345
Botan::Algorithm_Factory::set_preferred_provider
void set_preferred_provider(const std::string &algo_spec, const std::string &provider)
Definition: algo_factory.cpp:138
Botan::Algorithm_Factory::prototype_stream_cipher
const StreamCipher * prototype_stream_cipher(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:204
Botan::BlockCipher
Definition: block_cipher.h:18
Botan::PBKDF
Definition: pbkdf.h:21