1 /*
2 * Block Ciphers
3 * (C) 2015 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/block_cipher.h>
9 #include <botan/scan_name.h>
10 #include <botan/exceptn.h>
11 
12 #if defined(BOTAN_HAS_AES)
13   #include <botan/aes.h>
14 #endif
15 
16 #if defined(BOTAN_HAS_ARIA)
17   #include <botan/aria.h>
18 #endif
19 
20 #if defined(BOTAN_HAS_BLOWFISH)
21   #include <botan/blowfish.h>
22 #endif
23 
24 #if defined(BOTAN_HAS_CAMELLIA)
25   #include <botan/camellia.h>
26 #endif
27 
28 #if defined(BOTAN_HAS_CAST_128)
29   #include <botan/cast128.h>
30 #endif
31 
32 #if defined(BOTAN_HAS_CAST_256)
33   #include <botan/cast256.h>
34 #endif
35 
36 #if defined(BOTAN_HAS_CASCADE)
37   #include <botan/cascade.h>
38 #endif
39 
40 #if defined(BOTAN_HAS_DES)
41   #include <botan/des.h>
42   #include <botan/desx.h>
43 #endif
44 
45 #if defined(BOTAN_HAS_GOST_28147_89)
46   #include <botan/gost_28147.h>
47 #endif
48 
49 #if defined(BOTAN_HAS_IDEA)
50   #include <botan/idea.h>
51 #endif
52 
53 #if defined(BOTAN_HAS_KASUMI)
54   #include <botan/kasumi.h>
55 #endif
56 
57 #if defined(BOTAN_HAS_LION)
58   #include <botan/lion.h>
59 #endif
60 
61 #if defined(BOTAN_HAS_MISTY1)
62   #include <botan/misty1.h>
63 #endif
64 
65 #if defined(BOTAN_HAS_NOEKEON)
66   #include <botan/noekeon.h>
67 #endif
68 
69 #if defined(BOTAN_HAS_SEED)
70   #include <botan/seed.h>
71 #endif
72 
73 #if defined(BOTAN_HAS_SERPENT)
74   #include <botan/serpent.h>
75 #endif
76 
77 #if defined(BOTAN_HAS_SHACAL2)
78   #include <botan/shacal2.h>
79 #endif
80 
81 #if defined(BOTAN_HAS_SM4)
82   #include <botan/sm4.h>
83 #endif
84 
85 #if defined(BOTAN_HAS_TWOFISH)
86   #include <botan/twofish.h>
87 #endif
88 
89 #if defined(BOTAN_HAS_THREEFISH_512)
90   #include <botan/threefish_512.h>
91 #endif
92 
93 #if defined(BOTAN_HAS_XTEA)
94   #include <botan/xtea.h>
95 #endif
96 
97 #if defined(BOTAN_HAS_OPENSSL)
98   #include <botan/internal/openssl.h>
99 #endif
100 
101 #if defined(BOTAN_HAS_COMMONCRYPTO)
102   #include <botan/internal/commoncrypto.h>
103 #endif
104 
105 namespace Botan {
106 
107 std::unique_ptr<BlockCipher>
create(const std::string & algo,const std::string & provider)108 BlockCipher::create(const std::string& algo,
109                     const std::string& provider)
110    {
111 #if defined(BOTAN_HAS_COMMONCRYPTO)
112    if(provider.empty() || provider == "commoncrypto")
113       {
114       if(auto bc = make_commoncrypto_block_cipher(algo))
115          return bc;
116 
117       if(!provider.empty())
118          return nullptr;
119       }
120 #endif
121 
122 #if defined(BOTAN_HAS_OPENSSL)
123    if(provider.empty() || provider == "openssl")
124       {
125       if(auto bc = make_openssl_block_cipher(algo))
126          return bc;
127 
128       if(!provider.empty())
129          return nullptr;
130       }
131 #endif
132 
133    // TODO: CryptoAPI
134    // TODO: /dev/crypto
135 
136    // Only base providers from here on out
137    if(provider.empty() == false && provider != "base")
138       return nullptr;
139 
140 #if defined(BOTAN_HAS_AES)
141    if(algo == "AES-128")
142       {
143       return std::unique_ptr<BlockCipher>(new AES_128);
144       }
145 
146    if(algo == "AES-192")
147       {
148       return std::unique_ptr<BlockCipher>(new AES_192);
149       }
150 
151    if(algo == "AES-256")
152       {
153       return std::unique_ptr<BlockCipher>(new AES_256);
154       }
155 #endif
156 
157 #if defined(BOTAN_HAS_ARIA)
158    if(algo == "ARIA-128")
159       {
160       return std::unique_ptr<BlockCipher>(new ARIA_128);
161       }
162 
163    if(algo == "ARIA-192")
164       {
165       return std::unique_ptr<BlockCipher>(new ARIA_192);
166       }
167 
168    if(algo == "ARIA-256")
169       {
170       return std::unique_ptr<BlockCipher>(new ARIA_256);
171       }
172 #endif
173 
174 #if defined(BOTAN_HAS_SERPENT)
175    if(algo == "Serpent")
176       {
177       return std::unique_ptr<BlockCipher>(new Serpent);
178       }
179 #endif
180 
181 #if defined(BOTAN_HAS_SHACAL2)
182    if(algo == "SHACAL2")
183       {
184       return std::unique_ptr<BlockCipher>(new SHACAL2);
185       }
186 #endif
187 
188 #if defined(BOTAN_HAS_TWOFISH)
189    if(algo == "Twofish")
190       {
191       return std::unique_ptr<BlockCipher>(new Twofish);
192       }
193 #endif
194 
195 #if defined(BOTAN_HAS_THREEFISH_512)
196    if(algo == "Threefish-512")
197       {
198       return std::unique_ptr<BlockCipher>(new Threefish_512);
199       }
200 #endif
201 
202 #if defined(BOTAN_HAS_BLOWFISH)
203    if(algo == "Blowfish")
204       {
205       return std::unique_ptr<BlockCipher>(new Blowfish);
206       }
207 #endif
208 
209 #if defined(BOTAN_HAS_CAMELLIA)
210    if(algo == "Camellia-128")
211       {
212       return std::unique_ptr<BlockCipher>(new Camellia_128);
213       }
214 
215    if(algo == "Camellia-192")
216       {
217       return std::unique_ptr<BlockCipher>(new Camellia_192);
218       }
219 
220    if(algo == "Camellia-256")
221       {
222       return std::unique_ptr<BlockCipher>(new Camellia_256);
223       }
224 #endif
225 
226 #if defined(BOTAN_HAS_DES)
227    if(algo == "DES")
228       {
229       return std::unique_ptr<BlockCipher>(new DES);
230       }
231 
232    if(algo == "DESX")
233       {
234       return std::unique_ptr<BlockCipher>(new DESX);
235       }
236 
237    if(algo == "TripleDES" || algo == "3DES" || algo == "DES-EDE")
238       {
239       return std::unique_ptr<BlockCipher>(new TripleDES);
240       }
241 #endif
242 
243 #if defined(BOTAN_HAS_NOEKEON)
244    if(algo == "Noekeon")
245       {
246       return std::unique_ptr<BlockCipher>(new Noekeon);
247       }
248 #endif
249 
250 #if defined(BOTAN_HAS_CAST_128)
251    if(algo == "CAST-128" || algo == "CAST5")
252       {
253       return std::unique_ptr<BlockCipher>(new CAST_128);
254       }
255 #endif
256 
257 #if defined(BOTAN_HAS_CAST_256)
258    if(algo == "CAST-256")
259       {
260       return std::unique_ptr<BlockCipher>(new CAST_256);
261       }
262 #endif
263 
264 #if defined(BOTAN_HAS_IDEA)
265    if(algo == "IDEA")
266       {
267       return std::unique_ptr<BlockCipher>(new IDEA);
268       }
269 #endif
270 
271 #if defined(BOTAN_HAS_KASUMI)
272    if(algo == "KASUMI")
273       {
274       return std::unique_ptr<BlockCipher>(new KASUMI);
275       }
276 #endif
277 
278 #if defined(BOTAN_HAS_MISTY1)
279    if(algo == "MISTY1")
280       {
281       return std::unique_ptr<BlockCipher>(new MISTY1);
282       }
283 #endif
284 
285 #if defined(BOTAN_HAS_SEED)
286    if(algo == "SEED")
287       {
288       return std::unique_ptr<BlockCipher>(new SEED);
289       }
290 #endif
291 
292 #if defined(BOTAN_HAS_SM4)
293    if(algo == "SM4")
294       {
295       return std::unique_ptr<BlockCipher>(new SM4);
296       }
297 #endif
298 
299 #if defined(BOTAN_HAS_XTEA)
300    if(algo == "XTEA")
301       {
302       return std::unique_ptr<BlockCipher>(new XTEA);
303       }
304 #endif
305 
306    const SCAN_Name req(algo);
307 
308 #if defined(BOTAN_HAS_GOST_28147_89)
309    if(req.algo_name() == "GOST-28147-89")
310       {
311       return std::unique_ptr<BlockCipher>(new GOST_28147_89(req.arg(0, "R3411_94_TestParam")));
312       }
313 #endif
314 
315 #if defined(BOTAN_HAS_CASCADE)
316    if(req.algo_name() == "Cascade" && req.arg_count() == 2)
317       {
318       std::unique_ptr<BlockCipher> c1(BlockCipher::create(req.arg(0)));
319       std::unique_ptr<BlockCipher> c2(BlockCipher::create(req.arg(1)));
320 
321       if(c1 && c2)
322          return std::unique_ptr<BlockCipher>(new Cascade_Cipher(c1.release(), c2.release()));
323       }
324 #endif
325 
326 #if defined(BOTAN_HAS_LION)
327    if(req.algo_name() == "Lion" && req.arg_count_between(2, 3))
328       {
329       std::unique_ptr<HashFunction> hash(HashFunction::create(req.arg(0)));
330       std::unique_ptr<StreamCipher> stream(StreamCipher::create(req.arg(1)));
331 
332       if(hash && stream)
333          {
334          const size_t block_size = req.arg_as_integer(2, 1024);
335          return std::unique_ptr<BlockCipher>(new Lion(hash.release(), stream.release(), block_size));
336          }
337       }
338 #endif
339 
340    BOTAN_UNUSED(req);
341    BOTAN_UNUSED(provider);
342 
343    return nullptr;
344    }
345 
346 //static
347 std::unique_ptr<BlockCipher>
create_or_throw(const std::string & algo,const std::string & provider)348 BlockCipher::create_or_throw(const std::string& algo,
349                              const std::string& provider)
350    {
351    if(auto bc = BlockCipher::create(algo, provider))
352       {
353       return bc;
354       }
355    throw Lookup_Error("Block cipher", algo, provider);
356    }
357 
providers(const std::string & algo)358 std::vector<std::string> BlockCipher::providers(const std::string& algo)
359    {
360    return probe_providers_of<BlockCipher>(algo, { "base", "openssl", "commoncrypto" });
361    }
362 
363 }
364