Botan  1.11.15
src/lib/block/cascade/cascade.cpp
Go to the documentation of this file.
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 }