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