Botan  2.4.0
Crypto and TLS for C++11
hash.cpp
Go to the documentation of this file.
1 /*
2 * Hash Functions
3 * (C) 2015 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/hash.h>
9 #include <botan/scan_name.h>
10 #include <botan/exceptn.h>
11 
12 #if defined(BOTAN_HAS_ADLER32)
13  #include <botan/adler32.h>
14 #endif
15 
16 #if defined(BOTAN_HAS_CRC24)
17  #include <botan/crc24.h>
18 #endif
19 
20 #if defined(BOTAN_HAS_CRC32)
21  #include <botan/crc32.h>
22 #endif
23 
24 #if defined(BOTAN_HAS_GOST_34_11)
25  #include <botan/gost_3411.h>
26 #endif
27 
28 #if defined(BOTAN_HAS_KECCAK)
29  #include <botan/keccak.h>
30 #endif
31 
32 #if defined(BOTAN_HAS_MD4)
33  #include <botan/md4.h>
34 #endif
35 
36 #if defined(BOTAN_HAS_MD5)
37  #include <botan/md5.h>
38 #endif
39 
40 #if defined(BOTAN_HAS_RIPEMD_160)
41  #include <botan/rmd160.h>
42 #endif
43 
44 #if defined(BOTAN_HAS_SHA1)
45  #include <botan/sha160.h>
46 #endif
47 
48 #if defined(BOTAN_HAS_SHA2_32)
49  #include <botan/sha2_32.h>
50 #endif
51 
52 #if defined(BOTAN_HAS_SHA2_64)
53  #include <botan/sha2_64.h>
54 #endif
55 
56 #if defined(BOTAN_HAS_SHA3)
57  #include <botan/sha3.h>
58 #endif
59 
60 #if defined(BOTAN_HAS_SHAKE)
61  #include <botan/shake.h>
62 #endif
63 
64 #if defined(BOTAN_HAS_SKEIN_512)
65  #include <botan/skein_512.h>
66 #endif
67 
68 #if defined(BOTAN_HAS_STREEBOG)
69  #include <botan/streebog.h>
70 #endif
71 
72 #if defined(BOTAN_HAS_SM3)
73  #include <botan/sm3.h>
74 #endif
75 
76 #if defined(BOTAN_HAS_TIGER)
77  #include <botan/tiger.h>
78 #endif
79 
80 #if defined(BOTAN_HAS_WHIRLPOOL)
81  #include <botan/whrlpool.h>
82 #endif
83 
84 #if defined(BOTAN_HAS_PARALLEL_HASH)
85  #include <botan/par_hash.h>
86 #endif
87 
88 #if defined(BOTAN_HAS_COMB4P)
89  #include <botan/comb4p.h>
90 #endif
91 
92 #if defined(BOTAN_HAS_BLAKE2B)
93  #include <botan/blake2b.h>
94 #endif
95 
96 #if defined(BOTAN_HAS_BEARSSL)
97  #include <botan/internal/bearssl.h>
98 #endif
99 
100 #if defined(BOTAN_HAS_OPENSSL)
101  #include <botan/internal/openssl.h>
102 #endif
103 
104 namespace Botan {
105 
106 std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec,
107  const std::string& provider)
108  {
109 #if defined(BOTAN_HAS_OPENSSL)
110  if(provider.empty() || provider == "openssl")
111  {
112  if(auto hash = make_openssl_hash(algo_spec))
113  return hash;
114 
115  if(!provider.empty())
116  return nullptr;
117  }
118 #endif
119 
120 #if defined(BOTAN_HAS_BEARSSL)
121  if(provider.empty() || provider == "bearssl")
122  {
123  if(auto hash = make_bearssl_hash(algo_spec))
124  return hash;
125 
126  if(!provider.empty())
127  return nullptr;
128  }
129 #endif
130 
131  // TODO: CommonCrypto hashes
132 
133  if(provider.empty() == false && provider != "base")
134  return nullptr; // unknown provider
135 
136 #if defined(BOTAN_HAS_SHA1)
137  if(algo_spec == "SHA-160" ||
138  algo_spec == "SHA-1" ||
139  algo_spec == "SHA1")
140  {
141  return std::unique_ptr<HashFunction>(new SHA_160);
142  }
143 #endif
144 
145 #if defined(BOTAN_HAS_SHA2_32)
146  if(algo_spec == "SHA-224")
147  {
148  return std::unique_ptr<HashFunction>(new SHA_224);
149  }
150 
151  if(algo_spec == "SHA-256")
152  {
153  return std::unique_ptr<HashFunction>(new SHA_256);
154  }
155 #endif
156 
157 #if defined(BOTAN_HAS_SHA2_64)
158  if(algo_spec == "SHA-384")
159  {
160  return std::unique_ptr<HashFunction>(new SHA_384);
161  }
162 
163  if(algo_spec == "SHA-512")
164  {
165  return std::unique_ptr<HashFunction>(new SHA_512);
166  }
167 
168  if(algo_spec == "SHA-512-256")
169  {
170  return std::unique_ptr<HashFunction>(new SHA_512_256);
171  }
172 #endif
173 
174 #if defined(BOTAN_HAS_RIPEMD_160)
175  if(algo_spec == "RIPEMD-160")
176  {
177  return std::unique_ptr<HashFunction>(new RIPEMD_160);
178  }
179 #endif
180 
181 #if defined(BOTAN_HAS_WHIRLPOOL)
182  if(algo_spec == "Whirlpool")
183  {
184  return std::unique_ptr<HashFunction>(new Whirlpool);
185  }
186 #endif
187 
188 #if defined(BOTAN_HAS_MD5)
189  if(algo_spec == "MD5")
190  {
191  return std::unique_ptr<HashFunction>(new MD5);
192  }
193 #endif
194 
195 #if defined(BOTAN_HAS_MD4)
196  if(algo_spec == "MD4")
197  {
198  return std::unique_ptr<HashFunction>(new MD4);
199  }
200 #endif
201 
202 #if defined(BOTAN_HAS_GOST_34_11)
203  if(algo_spec == "GOST-R-34.11-94" || algo_spec == "GOST-34.11")
204  {
205  return std::unique_ptr<HashFunction>(new GOST_34_11);
206  }
207 #endif
208 
209 #if defined(BOTAN_HAS_ADLER32)
210  if(algo_spec == "Adler32")
211  {
212  return std::unique_ptr<HashFunction>(new Adler32);
213  }
214 #endif
215 
216 #if defined(BOTAN_HAS_CRC24)
217  if(algo_spec == "CRC24")
218  {
219  return std::unique_ptr<HashFunction>(new CRC24);
220  }
221 #endif
222 
223 #if defined(BOTAN_HAS_CRC32)
224  if(algo_spec == "CRC32")
225  {
226  return std::unique_ptr<HashFunction>(new CRC32);
227  }
228 #endif
229 
230  const SCAN_Name req(algo_spec);
231 
232 #if defined(BOTAN_HAS_TIGER)
233  if(req.algo_name() == "Tiger")
234  {
235  return std::unique_ptr<HashFunction>(
236  new Tiger(req.arg_as_integer(0, 24),
237  req.arg_as_integer(1, 3)));
238  }
239 #endif
240 
241 #if defined(BOTAN_HAS_SKEIN_512)
242  if(req.algo_name() == "Skein-512")
243  {
244  return std::unique_ptr<HashFunction>(
245  new Skein_512(req.arg_as_integer(0, 512), req.arg(1, "")));
246  }
247 #endif
248 
249 #if defined(BOTAN_HAS_BLAKE2B)
250  if(req.algo_name() == "Blake2b")
251  {
252  return std::unique_ptr<HashFunction>(
253  new Blake2b(req.arg_as_integer(0, 512)));
254  }
255 #endif
256 
257 #if defined(BOTAN_HAS_KECCAK)
258  if(req.algo_name() == "Keccak-1600")
259  {
260  return std::unique_ptr<HashFunction>(
261  new Keccak_1600(req.arg_as_integer(0, 512)));
262  }
263 #endif
264 
265 #if defined(BOTAN_HAS_SHA3)
266  if(req.algo_name() == "SHA-3")
267  {
268  return std::unique_ptr<HashFunction>(
269  new SHA_3(req.arg_as_integer(0, 512)));
270  }
271 #endif
272 
273 #if defined(BOTAN_HAS_SHAKE)
274  if(req.algo_name() == "SHAKE-128")
275  {
276  return std::unique_ptr<HashFunction>(new SHAKE_128(req.arg_as_integer(0, 128)));
277  }
278  if(req.algo_name() == "SHAKE-256")
279  {
280  return std::unique_ptr<HashFunction>(new SHAKE_256(req.arg_as_integer(0, 256)));
281  }
282 #endif
283 
284 #if defined(BOTAN_HAS_STREEBOG)
285  if(algo_spec == "Streebog-256")
286  {
287  return std::unique_ptr<HashFunction>(new Streebog_256);
288  }
289  if(algo_spec == "Streebog-512")
290  {
291  return std::unique_ptr<HashFunction>(new Streebog_512);
292  }
293 #endif
294 
295 #if defined(BOTAN_HAS_SM3)
296  if(algo_spec == "SM3")
297  {
298  return std::unique_ptr<HashFunction>(new SM3);
299  }
300 #endif
301 
302 #if defined(BOTAN_HAS_WHIRLPOOL)
303  if(req.algo_name() == "Whirlpool")
304  {
305  return std::unique_ptr<HashFunction>(new Whirlpool);
306  }
307 #endif
308 
309 #if defined(BOTAN_HAS_PARALLEL_HASH)
310  if(req.algo_name() == "Parallel")
311  {
312  std::vector<std::unique_ptr<HashFunction>> hashes;
313 
314  for(size_t i = 0; i != req.arg_count(); ++i)
315  {
316  auto h = HashFunction::create(req.arg(i));
317  if(!h)
318  {
319  return nullptr;
320  }
321  hashes.push_back(std::move(h));
322  }
323 
324  return std::unique_ptr<HashFunction>(new Parallel(hashes));
325  }
326 #endif
327 
328 #if defined(BOTAN_HAS_COMB4P)
329  if(req.algo_name() == "Comb4P" && req.arg_count() == 2)
330  {
331  std::unique_ptr<HashFunction> h1(HashFunction::create(req.arg(0)));
332  std::unique_ptr<HashFunction> h2(HashFunction::create(req.arg(1)));
333 
334  if(h1 && h2)
335  return std::unique_ptr<HashFunction>(new Comb4P(h1.release(), h2.release()));
336  }
337 #endif
338 
339 
340  return nullptr;
341  }
342 
343 //static
344 std::unique_ptr<HashFunction>
345 HashFunction::create_or_throw(const std::string& algo,
346  const std::string& provider)
347  {
348  if(auto hash = HashFunction::create(algo, provider))
349  {
350  return hash;
351  }
352  throw Lookup_Error("Hash", algo, provider);
353  }
354 
355 std::vector<std::string> HashFunction::providers(const std::string& algo_spec)
356  {
357  return probe_providers_of<HashFunction>(algo_spec, {"base", "bearssl", "openssl"});
358  }
359 
360 }
361 
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:345
Definition: md4.h:18
Definition: sm3.h:23
std::unique_ptr< HashFunction > make_bearssl_hash(const std::string &name)
virtual std::string provider() const
Definition: hash.h:58
std::unique_ptr< HashFunction > make_openssl_hash(const std::string &name)
Definition: md5.h:18
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:106
static std::vector< std::string > providers(const std::string &algo_spec)
Definition: hash.cpp:355
Definition: alg_id.cpp:13
MechanismType hash