/* * Message Authentication Code base class * (C) 1999-2008 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #if defined(BOTAN_HAS_CBC_MAC) #include #endif #if defined(BOTAN_HAS_CMAC) #include #endif #if defined(BOTAN_HAS_GMAC) #include #include #endif #if defined(BOTAN_HAS_HMAC) #include #include #endif #if defined(BOTAN_HAS_POLY1305) #include #endif #if defined(BOTAN_HAS_SIPHASH) #include #endif #if defined(BOTAN_HAS_ANSI_X919_MAC) #include #endif namespace Botan { std::unique_ptr MessageAuthenticationCode::create(const std::string& algo_spec, const std::string& provider) { const SCAN_Name req(algo_spec); #if defined(BOTAN_HAS_GMAC) if(req.algo_name() == "GMAC" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { if(auto bc = BlockCipher::create(req.arg(0))) return std::unique_ptr(new GMAC(bc.release())); } } #endif #if defined(BOTAN_HAS_HMAC) if(req.algo_name() == "HMAC" && req.arg_count() == 1) { // TODO OpenSSL if(provider.empty() || provider == "base") { if(auto h = HashFunction::create(req.arg(0))) return std::unique_ptr(new HMAC(h.release())); } } #endif #if defined(BOTAN_HAS_POLY1305) if(req.algo_name() == "Poly1305" && req.arg_count() == 0) { if(provider.empty() || provider == "base") return std::unique_ptr(new Poly1305); } #endif #if defined(BOTAN_HAS_SIPHASH) if(req.algo_name() == "SipHash") { if(provider.empty() || provider == "base") { return std::unique_ptr( new SipHash(req.arg_as_integer(0, 2), req.arg_as_integer(1, 4))); } } #endif #if defined(BOTAN_HAS_CMAC) if((req.algo_name() == "CMAC" || req.algo_name() == "OMAC") && req.arg_count() == 1) { // TODO: OpenSSL CMAC if(provider.empty() || provider == "base") { if(auto bc = BlockCipher::create(req.arg(0))) return std::unique_ptr(new CMAC(bc.release())); } } #endif #if defined(BOTAN_HAS_CBC_MAC) if(req.algo_name() == "CBC-MAC" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { if(auto bc = BlockCipher::create(req.arg(0))) return std::unique_ptr(new CBC_MAC(bc.release())); } } #endif #if defined(BOTAN_HAS_ANSI_X919_MAC) if(req.algo_name() == "X9.19-MAC") { if(provider.empty() || provider == "base") { return std::unique_ptr(new ANSI_X919_MAC); } } #endif BOTAN_UNUSED(req); BOTAN_UNUSED(provider); return nullptr; } std::vector MessageAuthenticationCode::providers(const std::string& algo_spec) { return probe_providers_of(algo_spec, {"base", "openssl"}); } //static std::unique_ptr MessageAuthenticationCode::create_or_throw(const std::string& algo, const std::string& provider) { if(auto mac = MessageAuthenticationCode::create(algo, provider)) { return mac; } throw Lookup_Error("MAC", algo, provider); } /* * Default (deterministic) MAC verification operation */ bool MessageAuthenticationCode::verify_mac(const uint8_t mac[], size_t length) { secure_vector our_mac = final(); if(our_mac.size() != length) return false; return constant_time_compare(our_mac.data(), mac, length); } }