/************************************************* * Default Engine Source File * * (C) 1999-2007 Jack Lloyd * *************************************************/ #include #include #include #include #include #if defined(BOTAN_HAS_ECB) #include #endif #if defined(BOTAN_HAS_CBC) #include #endif #if defined(BOTAN_HAS_CTS) #include #endif #if defined(BOTAN_HAS_CFB) #include #endif #if defined(BOTAN_HAS_OFB) #include #endif #if defined(BOTAN_HAS_CTR) #include #endif #if defined(BOTAN_HAS_EAX) #include #endif namespace Botan { /************************************************* * Get a cipher object * *************************************************/ Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, Cipher_Dir direction) { std::vector algo_parts = split_on(algo_spec, '/'); if(algo_parts.empty()) throw Invalid_Algorithm_Name(algo_spec); const std::string cipher_name = algo_parts[0]; if(have_stream_cipher(cipher_name)) { if(algo_parts.size() == 1) return new StreamCipher_Filter(cipher_name); return 0; } if(!have_block_cipher(cipher_name)) return 0; std::auto_ptr cipher(get_block_cipher(cipher_name)); if(algo_parts.size() != 2 && algo_parts.size() != 3) return 0; std::string mode = algo_parts[1]; u32bit bits = 0; if(mode.find("CFB") != std::string::npos || mode.find("EAX") != std::string::npos) { std::vector algo_info = parse_algorithm_name(mode); mode = algo_info[0]; if(algo_info.size() == 1) bits = 8*cipher->BLOCK_SIZE; else if(algo_info.size() == 2) bits = to_u32bit(algo_info[1]); else throw Invalid_Algorithm_Name(algo_spec); } std::string padding; if(algo_parts.size() == 3) padding = algo_parts[2]; else padding = (mode == "CBC") ? "PKCS7" : "NoPadding"; if(mode == "ECB" && padding == "CTS") return 0; else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding") throw Invalid_Algorithm_Name(algo_spec); if(mode == "OFB") { #if defined(BOTAN_HAS_OFB) return new OFB(cipher.release()); #else return 0; #endif } if(mode == "CTR-BE") { #if defined(BOTAN_HAS_CTR) return new CTR_BE(cipher.release()); #else return 0; #endif } if(mode == "ECB") { #if defined(BOTAN_HAS_ECB) if(direction == ENCRYPTION) return new ECB_Encryption(cipher.release(), get_bc_pad(padding)); else return new ECB_Decryption(cipher.release(), get_bc_pad(padding)); #else return 0; #endif } if(mode == "CFB") { #if defined(BOTAN_HAS_CFB) if(direction == ENCRYPTION) return new CFB_Encryption(cipher.release(), bits); else return new CFB_Decryption(cipher.release(), bits); #else return 0; #endif } if(mode == "CBC") { if(padding == "CTS") { #if defined(BOTAN_HAS_CTS) if(direction == ENCRYPTION) return new CTS_Encryption(cipher.release()); else return new CTS_Decryption(cipher.release()); #else return 0; #endif } #if defined(BOTAN_HAS_CBC) if(direction == ENCRYPTION) return new CBC_Encryption(cipher.release(), get_bc_pad(padding)); else return new CBC_Decryption(cipher.release(), get_bc_pad(padding)); #else return 0; #endif } if(mode == "EAX") { #if defined(BOTAN_HAS_EAX) if(direction == ENCRYPTION) return new EAX_Encryption(cipher.release(), bits); else return new EAX_Decryption(cipher.release(), bits); #else return 0; #endif } throw Algorithm_Not_Found("get_mode: " + cipher_name + "/" + mode + "/" + padding); } }