/* * Hash Functions * (C) 2015 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #if defined(BOTAN_HAS_ADLER32) #include #endif #if defined(BOTAN_HAS_CRC24) #include #endif #if defined(BOTAN_HAS_CRC32) #include #endif #if defined(BOTAN_HAS_GOST_34_11) #include #endif #if defined(BOTAN_HAS_KECCAK) #include #endif #if defined(BOTAN_HAS_MD4) #include #endif #if defined(BOTAN_HAS_MD5) #include #endif #if defined(BOTAN_HAS_RIPEMD_160) #include #endif #if defined(BOTAN_HAS_SHA1) #include #endif #if defined(BOTAN_HAS_SHA2_32) #include #endif #if defined(BOTAN_HAS_SHA2_64) #include #endif #if defined(BOTAN_HAS_SHA3) #include #endif #if defined(BOTAN_HAS_SHAKE) #include #endif #if defined(BOTAN_HAS_SKEIN_512) #include #endif #if defined(BOTAN_HAS_SM3) #include #endif #if defined(BOTAN_HAS_TIGER) #include #endif #if defined(BOTAN_HAS_WHIRLPOOL) #include #endif #if defined(BOTAN_HAS_PARALLEL_HASH) #include #endif #if defined(BOTAN_HAS_COMB4P) #include #endif #if defined(BOTAN_HAS_BLAKE2B) #include #endif #if defined(BOTAN_HAS_OPENSSL) #include #endif namespace Botan { std::unique_ptr HashFunction::create(const std::string& algo_spec, const std::string& provider) { #if defined(BOTAN_HAS_OPENSSL) if(provider.empty() || provider == "openssl") { if(auto hash = make_openssl_hash(algo_spec)) return hash; if(!provider.empty()) return nullptr; } #endif // TODO: CommonCrypto hashes if(provider.empty() == false && provider != "base") return nullptr; // unknown provider #if defined(BOTAN_HAS_SHA1) if(algo_spec == "SHA-160" || algo_spec == "SHA-1" || algo_spec == "SHA1") { return std::unique_ptr(new SHA_160); } #endif #if defined(BOTAN_HAS_SHA2_32) if(algo_spec == "SHA-224") { return std::unique_ptr(new SHA_224); } if(algo_spec == "SHA-256") { return std::unique_ptr(new SHA_256); } #endif #if defined(BOTAN_HAS_SHA2_64) if(algo_spec == "SHA-384") { return std::unique_ptr(new SHA_384); } if(algo_spec == "SHA-512") { return std::unique_ptr(new SHA_512); } if(algo_spec == "SHA-512-256") { return std::unique_ptr(new SHA_512_256); } #endif #if defined(BOTAN_HAS_RIPEMD_160) if(algo_spec == "RIPEMD-160") { return std::unique_ptr(new RIPEMD_160); } #endif #if defined(BOTAN_HAS_WHIRLPOOL) if(algo_spec == "Whirlpool") { return std::unique_ptr(new Whirlpool); } #endif #if defined(BOTAN_HAS_MD5) if(algo_spec == "MD5") { return std::unique_ptr(new MD5); } #endif #if defined(BOTAN_HAS_MD4) if(algo_spec == "MD4") { return std::unique_ptr(new MD4); } #endif #if defined(BOTAN_HAS_GOST_34_11) if(algo_spec == "GOST-R-34.11-94" || algo_spec == "GOST-34.11") { return std::unique_ptr(new GOST_34_11); } #endif #if defined(BOTAN_HAS_ADLER32) if(algo_spec == "Adler32") { return std::unique_ptr(new Adler32); } #endif #if defined(BOTAN_HAS_CRC24) if(algo_spec == "CRC24") { return std::unique_ptr(new CRC24); } #endif #if defined(BOTAN_HAS_CRC32) if(algo_spec == "CRC32") { return std::unique_ptr(new CRC32); } #endif const SCAN_Name req(algo_spec); #if defined(BOTAN_HAS_TIGER) if(req.algo_name() == "Tiger") { return std::unique_ptr( new Tiger(req.arg_as_integer(0, 24), req.arg_as_integer(1, 3))); } #endif #if defined(BOTAN_HAS_SKEIN_512) if(req.algo_name() == "Skein-512") { return std::unique_ptr( new Skein_512(req.arg_as_integer(0, 512), req.arg(1, ""))); } #endif #if defined(BOTAN_HAS_BLAKE2B) if(req.algo_name() == "Blake2b") { return std::unique_ptr( new Blake2b(req.arg_as_integer(0, 512))); } #endif #if defined(BOTAN_HAS_KECCAK) if(req.algo_name() == "Keccak-1600") { return std::unique_ptr( new Keccak_1600(req.arg_as_integer(0, 512))); } #endif #if defined(BOTAN_HAS_SHA3) if(req.algo_name() == "SHA-3") { return std::unique_ptr( new SHA_3(req.arg_as_integer(0, 512))); } #endif #if defined(BOTAN_HAS_SHAKE) if(req.algo_name() == "SHAKE-128") { return std::unique_ptr(new SHAKE_128(req.arg_as_integer(0, 128))); } if(req.algo_name() == "SHAKE-256") { return std::unique_ptr(new SHAKE_256(req.arg_as_integer(0, 256))); } #endif #if defined(BOTAN_HAS_SM3) if(algo_spec == "SM3") { return std::unique_ptr(new SM3); } #endif #if defined(BOTAN_HAS_WHIRLPOOL) if(req.algo_name() == "Whirlpool") { return std::unique_ptr(new Whirlpool); } #endif #if defined(BOTAN_HAS_PARALLEL_HASH) if(req.algo_name() == "Parallel") { std::vector> hashes; for(size_t i = 0; i != req.arg_count(); ++i) { auto h = HashFunction::create(req.arg(i)); if(!h) { return nullptr; } hashes.push_back(std::move(h)); } return std::unique_ptr(new Parallel(hashes)); } #endif #if defined(BOTAN_HAS_COMB4P) if(req.algo_name() == "Comb4P" && req.arg_count() == 2) { std::unique_ptr h1(HashFunction::create(req.arg(0))); std::unique_ptr h2(HashFunction::create(req.arg(1))); if(h1 && h2) return std::unique_ptr(new Comb4P(h1.release(), h2.release())); } #endif return nullptr; } //static std::unique_ptr HashFunction::create_or_throw(const std::string& algo, const std::string& provider) { if(auto hash = HashFunction::create(algo, provider)) { return hash; } throw Lookup_Error("Hash", algo, provider); } std::vector HashFunction::providers(const std::string& algo_spec) { return probe_providers_of(algo_spec, {"base", "openssl"}); } }