Botan  2.8.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 #if defined(BOTAN_HAS_COMMONCRYPTO)
105  #include <botan/internal/commoncrypto.h>
106 #endif
107 
108 namespace Botan {
109 
110 std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec,
111  const std::string& provider)
112  {
113 
114 #if defined(BOTAN_HAS_COMMONCRYPTO)
115  if(provider.empty() || provider == "commoncrypto")
116  {
117  if(auto hash = make_commoncrypto_hash(algo_spec))
118  return hash;
119 
120  if(!provider.empty())
121  return nullptr;
122  }
123 #endif
124 
125 #if defined(BOTAN_HAS_OPENSSL)
126  if(provider.empty() || provider == "openssl")
127  {
128  if(auto hash = make_openssl_hash(algo_spec))
129  return hash;
130 
131  if(!provider.empty())
132  return nullptr;
133  }
134 #endif
135 
136 #if defined(BOTAN_HAS_BEARSSL)
137  if(provider.empty() || provider == "bearssl")
138  {
139  if(auto hash = make_bearssl_hash(algo_spec))
140  return hash;
141 
142  if(!provider.empty())
143  return nullptr;
144  }
145 #endif
146 
147  if(provider.empty() == false && provider != "base")
148  return nullptr; // unknown provider
149 
150 #if defined(BOTAN_HAS_SHA1)
151  if(algo_spec == "SHA-160" ||
152  algo_spec == "SHA-1" ||
153  algo_spec == "SHA1")
154  {
155  return std::unique_ptr<HashFunction>(new SHA_160);
156  }
157 #endif
158 
159 #if defined(BOTAN_HAS_SHA2_32)
160  if(algo_spec == "SHA-224")
161  {
162  return std::unique_ptr<HashFunction>(new SHA_224);
163  }
164 
165  if(algo_spec == "SHA-256")
166  {
167  return std::unique_ptr<HashFunction>(new SHA_256);
168  }
169 #endif
170 
171 #if defined(BOTAN_HAS_SHA2_64)
172  if(algo_spec == "SHA-384")
173  {
174  return std::unique_ptr<HashFunction>(new SHA_384);
175  }
176 
177  if(algo_spec == "SHA-512")
178  {
179  return std::unique_ptr<HashFunction>(new SHA_512);
180  }
181 
182  if(algo_spec == "SHA-512-256")
183  {
184  return std::unique_ptr<HashFunction>(new SHA_512_256);
185  }
186 #endif
187 
188 #if defined(BOTAN_HAS_RIPEMD_160)
189  if(algo_spec == "RIPEMD-160")
190  {
191  return std::unique_ptr<HashFunction>(new RIPEMD_160);
192  }
193 #endif
194 
195 #if defined(BOTAN_HAS_WHIRLPOOL)
196  if(algo_spec == "Whirlpool")
197  {
198  return std::unique_ptr<HashFunction>(new Whirlpool);
199  }
200 #endif
201 
202 #if defined(BOTAN_HAS_MD5)
203  if(algo_spec == "MD5")
204  {
205  return std::unique_ptr<HashFunction>(new MD5);
206  }
207 #endif
208 
209 #if defined(BOTAN_HAS_MD4)
210  if(algo_spec == "MD4")
211  {
212  return std::unique_ptr<HashFunction>(new MD4);
213  }
214 #endif
215 
216 #if defined(BOTAN_HAS_GOST_34_11)
217  if(algo_spec == "GOST-R-34.11-94" || algo_spec == "GOST-34.11")
218  {
219  return std::unique_ptr<HashFunction>(new GOST_34_11);
220  }
221 #endif
222 
223 #if defined(BOTAN_HAS_ADLER32)
224  if(algo_spec == "Adler32")
225  {
226  return std::unique_ptr<HashFunction>(new Adler32);
227  }
228 #endif
229 
230 #if defined(BOTAN_HAS_CRC24)
231  if(algo_spec == "CRC24")
232  {
233  return std::unique_ptr<HashFunction>(new CRC24);
234  }
235 #endif
236 
237 #if defined(BOTAN_HAS_CRC32)
238  if(algo_spec == "CRC32")
239  {
240  return std::unique_ptr<HashFunction>(new CRC32);
241  }
242 #endif
243 
244  const SCAN_Name req(algo_spec);
245 
246 #if defined(BOTAN_HAS_TIGER)
247  if(req.algo_name() == "Tiger")
248  {
249  return std::unique_ptr<HashFunction>(
250  new Tiger(req.arg_as_integer(0, 24),
251  req.arg_as_integer(1, 3)));
252  }
253 #endif
254 
255 #if defined(BOTAN_HAS_SKEIN_512)
256  if(req.algo_name() == "Skein-512")
257  {
258  return std::unique_ptr<HashFunction>(
259  new Skein_512(req.arg_as_integer(0, 512), req.arg(1, "")));
260  }
261 #endif
262 
263 #if defined(BOTAN_HAS_BLAKE2B)
264  if(req.algo_name() == "Blake2b")
265  {
266  return std::unique_ptr<HashFunction>(
267  new Blake2b(req.arg_as_integer(0, 512)));
268  }
269 #endif
270 
271 #if defined(BOTAN_HAS_KECCAK)
272  if(req.algo_name() == "Keccak-1600")
273  {
274  return std::unique_ptr<HashFunction>(
275  new Keccak_1600(req.arg_as_integer(0, 512)));
276  }
277 #endif
278 
279 #if defined(BOTAN_HAS_SHA3)
280  if(req.algo_name() == "SHA-3")
281  {
282  return std::unique_ptr<HashFunction>(
283  new SHA_3(req.arg_as_integer(0, 512)));
284  }
285 #endif
286 
287 #if defined(BOTAN_HAS_SHAKE)
288  if(req.algo_name() == "SHAKE-128")
289  {
290  return std::unique_ptr<HashFunction>(new SHAKE_128(req.arg_as_integer(0, 128)));
291  }
292  if(req.algo_name() == "SHAKE-256")
293  {
294  return std::unique_ptr<HashFunction>(new SHAKE_256(req.arg_as_integer(0, 256)));
295  }
296 #endif
297 
298 #if defined(BOTAN_HAS_STREEBOG)
299  if(algo_spec == "Streebog-256")
300  {
301  return std::unique_ptr<HashFunction>(new Streebog_256);
302  }
303  if(algo_spec == "Streebog-512")
304  {
305  return std::unique_ptr<HashFunction>(new Streebog_512);
306  }
307 #endif
308 
309 #if defined(BOTAN_HAS_SM3)
310  if(algo_spec == "SM3")
311  {
312  return std::unique_ptr<HashFunction>(new SM3);
313  }
314 #endif
315 
316 #if defined(BOTAN_HAS_WHIRLPOOL)
317  if(req.algo_name() == "Whirlpool")
318  {
319  return std::unique_ptr<HashFunction>(new Whirlpool);
320  }
321 #endif
322 
323 #if defined(BOTAN_HAS_PARALLEL_HASH)
324  if(req.algo_name() == "Parallel")
325  {
326  std::vector<std::unique_ptr<HashFunction>> hashes;
327 
328  for(size_t i = 0; i != req.arg_count(); ++i)
329  {
330  auto h = HashFunction::create(req.arg(i));
331  if(!h)
332  {
333  return nullptr;
334  }
335  hashes.push_back(std::move(h));
336  }
337 
338  return std::unique_ptr<HashFunction>(new Parallel(hashes));
339  }
340 #endif
341 
342 #if defined(BOTAN_HAS_COMB4P)
343  if(req.algo_name() == "Comb4P" && req.arg_count() == 2)
344  {
345  std::unique_ptr<HashFunction> h1(HashFunction::create(req.arg(0)));
346  std::unique_ptr<HashFunction> h2(HashFunction::create(req.arg(1)));
347 
348  if(h1 && h2)
349  return std::unique_ptr<HashFunction>(new Comb4P(h1.release(), h2.release()));
350  }
351 #endif
352 
353 
354  return nullptr;
355  }
356 
357 //static
358 std::unique_ptr<HashFunction>
359 HashFunction::create_or_throw(const std::string& algo,
360  const std::string& provider)
361  {
362  if(auto hash = HashFunction::create(algo, provider))
363  {
364  return hash;
365  }
366  throw Lookup_Error("Hash", algo, provider);
367  }
368 
369 std::vector<std::string> HashFunction::providers(const std::string& algo_spec)
370  {
371  return probe_providers_of<HashFunction>(algo_spec, {"base", "bearssl", "openssl", "commoncrypto"});
372  }
373 
374 }
375 
size_t arg_count() const
Definition: scan_name.h:49
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:359
Definition: md4.h:18
size_t arg_as_integer(size_t i, size_t def_value) const
Definition: scan_name.cpp:137
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::string arg(size_t i) const
Definition: scan_name.cpp:122
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:110
static std::vector< std::string > providers(const std::string &algo_spec)
Definition: hash.cpp:369
Definition: alg_id.cpp:13
std::unique_ptr< HashFunction > make_commoncrypto_hash(const std::string &name)
const std::string & algo_name() const
Definition: scan_name.h:44
MechanismType hash