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