Botan
1.11.15
|
00001 /* 00002 * Block Cipher Cascade 00003 * (C) 2010 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/block_utils.h> 00009 #include <botan/cascade.h> 00010 00011 namespace Botan { 00012 00013 BOTAN_REGISTER_NAMED_T(BlockCipher, "Cascade", Cascade_Cipher, Cascade_Cipher::make); 00014 00015 Cascade_Cipher* Cascade_Cipher::make(const BlockCipher::Spec& spec) 00016 { 00017 auto& block_cipher = Algo_Registry<BlockCipher>::global_registry(); 00018 std::unique_ptr<BlockCipher> c1(block_cipher.make(spec.arg(0))); 00019 std::unique_ptr<BlockCipher> c2(block_cipher.make(spec.arg(1))); 00020 00021 if(c1 && c2) 00022 return new Cascade_Cipher(c1.release(), c2.release()); 00023 return nullptr; 00024 } 00025 00026 void Cascade_Cipher::encrypt_n(const byte in[], byte out[], 00027 size_t blocks) const 00028 { 00029 size_t c1_blocks = blocks * (block_size() / m_cipher1->block_size()); 00030 size_t c2_blocks = blocks * (block_size() / m_cipher2->block_size()); 00031 00032 m_cipher1->encrypt_n(in, out, c1_blocks); 00033 m_cipher2->encrypt_n(out, out, c2_blocks); 00034 } 00035 00036 void Cascade_Cipher::decrypt_n(const byte in[], byte out[], 00037 size_t blocks) const 00038 { 00039 size_t c1_blocks = blocks * (block_size() / m_cipher1->block_size()); 00040 size_t c2_blocks = blocks * (block_size() / m_cipher2->block_size()); 00041 00042 m_cipher2->decrypt_n(in, out, c2_blocks); 00043 m_cipher1->decrypt_n(out, out, c1_blocks); 00044 } 00045 00046 void Cascade_Cipher::key_schedule(const byte key[], size_t) 00047 { 00048 const byte* key2 = key + m_cipher1->maximum_keylength(); 00049 00050 m_cipher1->set_key(key , m_cipher1->maximum_keylength()); 00051 m_cipher2->set_key(key2, m_cipher2->maximum_keylength()); 00052 } 00053 00054 void Cascade_Cipher::clear() 00055 { 00056 m_cipher1->clear(); 00057 m_cipher2->clear(); 00058 } 00059 00060 std::string Cascade_Cipher::name() const 00061 { 00062 return "Cascade(" + m_cipher1->name() + "," + m_cipher2->name() + ")"; 00063 } 00064 00065 BlockCipher* Cascade_Cipher::clone() const 00066 { 00067 return new Cascade_Cipher(m_cipher1->clone(), 00068 m_cipher2->clone()); 00069 } 00070 00071 namespace { 00072 00073 size_t euclids_algorithm(size_t a, size_t b) 00074 { 00075 while(b != 0) // gcd 00076 { 00077 size_t t = b; 00078 b = a % b; 00079 a = t; 00080 } 00081 00082 return a; 00083 } 00084 00085 size_t block_size_for_cascade(size_t bs, size_t bs2) 00086 { 00087 if(bs == bs2) 00088 return bs; 00089 00090 size_t gcd = euclids_algorithm(bs, bs2); 00091 00092 return (bs * bs2) / gcd; 00093 } 00094 00095 } 00096 00097 Cascade_Cipher::Cascade_Cipher(BlockCipher* c1, BlockCipher* c2) : 00098 m_cipher1(c1), m_cipher2(c2) 00099 { 00100 m_block = block_size_for_cascade(c1->block_size(), c2->block_size()); 00101 00102 if(block_size() % c1->block_size() || block_size() % c2->block_size()) 00103 throw Internal_Error("Failure in " + name() + " constructor"); 00104 } 00105 00106 }