/* * (C) 2013,2015 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #include #if defined(BOTAN_HAS_BLOCK_CIPHER) #include #endif #if defined(BOTAN_HAS_AEAD_CCM) #include #endif #if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) #include #endif #if defined(BOTAN_HAS_AEAD_EAX) #include #endif #if defined(BOTAN_HAS_AEAD_GCM) #include #endif #if defined(BOTAN_HAS_AEAD_OCB) #include #endif #if defined(BOTAN_HAS_AEAD_SIV) #include #endif namespace Botan { std::unique_ptr AEAD_Mode::create_or_throw(const std::string& algo, Cipher_Dir dir, const std::string& provider) { if(auto aead = AEAD_Mode::create(algo, dir, provider)) return aead; throw Lookup_Error("AEAD", algo, provider); } std::unique_ptr AEAD_Mode::create(const std::string& algo, Cipher_Dir dir, const std::string& provider) { #if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) if(algo == "ChaCha20Poly1305") { if(dir == ENCRYPTION) return std::unique_ptr(new ChaCha20Poly1305_Encryption); else return std::unique_ptr(new ChaCha20Poly1305_Decryption); } #endif if(algo.find('/') != std::string::npos) { const std::vector algo_parts = split_on(algo, '/'); const std::string cipher_name = algo_parts[0]; const std::vector mode_info = parse_algorithm_name(algo_parts[1]); if(mode_info.empty()) return std::unique_ptr(); std::ostringstream alg_args; alg_args << '(' << cipher_name; for(size_t i = 1; i < mode_info.size(); ++i) alg_args << ',' << mode_info[i]; for(size_t i = 2; i < algo_parts.size(); ++i) alg_args << ',' << algo_parts[i]; alg_args << ')'; const std::string mode_name = mode_info[0] + alg_args.str(); return AEAD_Mode::create(mode_name, dir); } #if defined(BOTAN_HAS_BLOCK_CIPHER) SCAN_Name req(algo); if(req.arg_count() == 0) { return std::unique_ptr(); } std::unique_ptr bc(BlockCipher::create(req.arg(0), provider)); if(!bc) { return std::unique_ptr(); } #if defined(BOTAN_HAS_AEAD_CCM) if(req.algo_name() == "CCM") { size_t tag_len = req.arg_as_integer(1, 16); size_t L_len = req.arg_as_integer(2, 3); if(dir == ENCRYPTION) return std::unique_ptr(new CCM_Encryption(bc.release(), tag_len, L_len)); else return std::unique_ptr(new CCM_Decryption(bc.release(), tag_len, L_len)); } #endif #if defined(BOTAN_HAS_AEAD_GCM) if(req.algo_name() == "GCM") { size_t tag_len = req.arg_as_integer(1, 16); if(dir == ENCRYPTION) return std::unique_ptr(new GCM_Encryption(bc.release(), tag_len)); else return std::unique_ptr(new GCM_Decryption(bc.release(), tag_len)); } #endif #if defined(BOTAN_HAS_AEAD_OCB) if(req.algo_name() == "OCB") { size_t tag_len = req.arg_as_integer(1, 16); if(dir == ENCRYPTION) return std::unique_ptr(new OCB_Encryption(bc.release(), tag_len)); else return std::unique_ptr(new OCB_Decryption(bc.release(), tag_len)); } #endif #if defined(BOTAN_HAS_AEAD_EAX) if(req.algo_name() == "EAX") { size_t tag_len = req.arg_as_integer(1, bc->block_size()); if(dir == ENCRYPTION) return std::unique_ptr(new EAX_Encryption(bc.release(), tag_len)); else return std::unique_ptr(new EAX_Decryption(bc.release(), tag_len)); } #endif #if defined(BOTAN_HAS_AEAD_SIV) if(req.algo_name() == "SIV") { if(dir == ENCRYPTION) return std::unique_ptr(new SIV_Encryption(bc.release())); else return std::unique_ptr(new SIV_Decryption(bc.release())); } #endif #endif return std::unique_ptr(); } }