Botan  1.10.9
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 }
void add_block_cipher(BlockCipher *algo, const std::string &provider)
BigInt n
Definition: numthry.cpp:26
const PBKDF * prototype_pbkdf(const std::string &algo_spec, const std::string &provider="")
PBKDF * make_pbkdf(const std::string &algo_spec, const std::string &provider="")
virtual BlockCipher * clone() const =0
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
void add_stream_cipher(StreamCipher *algo, const std::string &provider)
BlockCipher * make_block_cipher(const std::string &algo_spec, const std::string &provider="")
virtual HashFunction * clone() const =0
void add_hash_function(HashFunction *algo, const std::string &provider)
MessageAuthenticationCode * make_mac(const std::string &algo_spec, const std::string &provider="")
StreamCipher * make_stream_cipher(const std::string &algo_spec, const std::string &provider="")
void add_mac(MessageAuthenticationCode *algo, const std::string &provider)
const HashFunction * prototype_hash_function(const std::string &algo_spec, const std::string &provider="")
virtual Mutex * make()=0
virtual std::string name() const =0
MessageAuthenticationCode * mac
Definition: fpe_fe1.cpp:94
const MessageAuthenticationCode * prototype_mac(const std::string &algo_spec, const std::string &provider="")
Algorithm_Factory(Mutex_Factory &mf)
virtual std::string name() const =0
std::vector< std::string > providers_of(const std::string &algo_spec)
HashFunction * make_hash_function(const std::string &algo_spec, const std::string &provider="")
virtual PBKDF * clone() const =0
void add_engine(Engine *engine)
virtual StreamCipher * clone() const =0
virtual MessageAuthenticationCode * clone() const =0
void add_pbkdf(PBKDF *algo, const std::string &provider)
void set_preferred_provider(const std::string &algo_spec, const std::string &provider)
const StreamCipher * prototype_stream_cipher(const std::string &algo_spec, const std::string &provider="")