1 /**
2 * Algorithm Lookup
3 * 
4 * Copyright:
5 * (C) 1999-2007 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.libstate.lookup;
12 
13 public import botan.filters.filters;
14 public import botan.modes.mode_pad;
15 public import botan.kdf.kdf;
16 public import botan.pk_pad.eme;
17 public import botan.pk_pad.emsa;
18 public import botan.pbkdf.pbkdf;
19 public import botan.engine.engine;
20 import botan.libstate.libstate;
21 
22 /**
23 * Retrieve an object prototype from the global factory
24 * Params:
25 *  algo_spec = an algorithm name
26 * Returns: constant prototype object (use clone to create usable object),
27              library retains ownership
28 */
29 const(BlockCipher) retrieveBlockCipher(in string algo_spec)
30 {
31     AlgorithmFactory af = globalState().algorithmFactory();
32     auto ret = af.prototypeBlockCipher(algo_spec);
33 	if (!ret)
34 		throw new AlgorithmNotFound(algo_spec);
35 	return ret;
36 }
37 
38 /**
39 * Retrieve an object prototype from the global factory
40 * Params:
41 *  algo_spec = an algorithm name
42 * Returns: constant prototype object (use clone to create usable object),
43              library retains ownership
44 */
45 const(StreamCipher) retrieveStreamCipher(in string algo_spec)
46 {
47     AlgorithmFactory af = globalState().algorithmFactory();
48     auto ret = af.prototypeStreamCipher(algo_spec);
49 	if (!ret)
50 		throw new AlgorithmNotFound(algo_spec);
51 	return ret;
52 }
53 
54 /**
55 * Retrieve an object prototype from the global factory
56 * Params:
57 *  algo_spec = an algorithm name
58 * Returns: constant prototype object (use clone to create usable object),
59              library retains ownership
60 */
61 const(HashFunction) retrieveHash(in string algo_spec)
62 {
63     AlgorithmFactory af = globalState().algorithmFactory();
64     auto ret = af.prototypeHashFunction(algo_spec);
65 	if (!ret)
66 		throw new AlgorithmNotFound(algo_spec);
67 	return ret;
68 }
69 
70 /**
71 * Retrieve an object prototype from the global factory
72 * Params:
73 *  algo_spec = an algorithm name
74 * Returns: constant prototype object (use clone to create usable object),
75              library retains ownership
76 */
77 const(MessageAuthenticationCode) retrieveMac(in string algo_spec)
78 {
79     AlgorithmFactory af = globalState().algorithmFactory();
80     auto ret = af.prototypeMac(algo_spec);
81 	if (!ret)
82 		throw new AlgorithmNotFound(algo_spec);
83 	return ret;
84 }
85 
86 /**
87 * Password based key derivation function factory method
88 * Params:
89 *  algo_spec = the name of the desired PBKDF algorithm
90 * Returns: pointer to newly allocated object of that type
91 */
92 PBKDF getPbkdf(in string algo_spec)
93 {
94     AlgorithmFactory af = globalState().algorithmFactory();
95     
96     if (PBKDF pbkdf = af.makePbkdf(algo_spec))
97         return pbkdf;
98     
99     throw new AlgorithmNotFound(algo_spec);
100 }
101 
102 /**
103 * Get a cipher object.
104 * Factory method for general symmetric cipher filters.
105 * Params:
106 *  algo_spec = the name of the desired cipher
107 *  key = the key to be used for encryption/decryption performed by
108 * the filter
109 *  iv = the initialization vector to be used
110 *  direction = determines whether the filter will be an encrypting
111 * or decrypting filter
112 * Returns: pointer to newly allocated encryption or decryption filter
113 */
114 KeyedFilter getCipher(in string algo_spec, in SymmetricKey key, in InitializationVector iv, CipherDir direction)
115 {
116     KeyedFilter cipher = getCipher(algo_spec, direction);
117 	if (!cipher)
118 		throw new AlgorithmNotFound(algo_spec);
119     cipher.setKey(key);
120     
121     if (iv.length)
122         cipher.setIv(iv);
123     
124     return cipher;
125 }
126 
127 /**
128 * Factory method for general symmetric cipher filters.
129 * Params:
130 *  algo_spec = the name of the desired cipher
131 *  key = the key to be used for encryption/decryption performed by
132 * the filter
133 *  direction = determines whether the filter will be an encrypting
134 * or decrypting filter
135 * Returns: pointer to the encryption or decryption filter
136 */
137 KeyedFilter getCipher(in string algo_spec, in SymmetricKey key, CipherDir direction)
138 {
139 	auto ret = getCipher(algo_spec, key, InitializationVector(), direction);
140 	if (!ret)
141 		throw new AlgorithmNotFound(algo_spec);
142 	return ret;
143 }
144 
145 
146 /**
147 * Factory method for general symmetric cipher filters. No key will be
148 * set in the filter.
149 *
150 * Params:
151 *  algo_spec = the name of the desired cipher
152 *  direction = determines whether the filter will be an encrypting or
153 * decrypting filter
154 * Returns: pointer to the encryption or decryption filter
155 */
156 KeyedFilter getCipher(in string algo_spec, CipherDir direction)
157 {
158     AlgorithmFactory af = globalState().algorithmFactory();
159 
160     foreach (Engine engine; af.engines[]) {
161         if (KeyedFilter algo = engine.getCipher(algo_spec, direction, af))
162             return algo;
163     }
164     
165     throw new AlgorithmNotFound(algo_spec);
166 }
167 
168 /**
169 * Check if an algorithm exists.
170 * Params:
171 *  name = the name of the algorithm to check for
172 * Returns: true if the algorithm exists, false otherwise
173 */
174 bool haveAlgorithm(in string name)
175 {
176     AlgorithmFactory af = globalState().algorithmFactory();
177     
178     if (af.prototypeBlockCipher(name))
179         return true;
180     if (af.prototypeStreamCipher(name))
181         return true;
182     if (af.prototypeHashFunction(name))
183         return true;
184     if (af.prototypeMac(name))
185         return true;
186 	if (af.prototypePbkdf(name))
187 		return true;
188     return false;
189 }
190 
191 string algorithmType(in string name) 
192 {
193 	AlgorithmFactory af = globalState().algorithmFactory();
194 	
195 	if (af.prototypeBlockCipher(name))
196 		return "Block";
197 	if (af.prototypeStreamCipher(name))
198 		return "Stream";
199 	if (af.prototypeHashFunction(name))
200 		return "Hash";
201 	if (af.prototypeMac(name))
202 		return "MAC";
203 	if (af.prototypePbkdf(name))
204 		return "PBKDF";
205 	throw new InvalidAlgorithmName(name);
206 }