Botan  1.11.15
src/lib/modes/ecb/ecb.cpp
Go to the documentation of this file.
00001 /*
00002 * ECB Mode
00003 * (C) 1999-2009,2013 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/internal/mode_utils.h>
00009 #include <botan/ecb.h>
00010 
00011 namespace Botan {
00012 
00013 template<typename T>
00014 Transform* make_ecb_mode(const Transform::Spec& spec)
00015    {
00016    std::unique_ptr<BlockCipher> bc(Algo_Registry<BlockCipher>::global_registry().make(spec.arg(0)));
00017    std::unique_ptr<BlockCipherModePaddingMethod> pad(get_bc_pad(spec.arg(1, "NoPadding")));
00018    if(bc && pad)
00019       return new T(bc.release(), pad.release());
00020    return nullptr;
00021    }
00022 
00023 BOTAN_REGISTER_TRANSFORM(ECB_Encryption, make_ecb_mode<ECB_Encryption>);
00024 BOTAN_REGISTER_TRANSFORM(ECB_Decryption, make_ecb_mode<ECB_Decryption>);
00025 
00026 ECB_Mode::ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
00027    m_cipher(cipher),
00028    m_padding(padding)
00029    {
00030    if(!m_padding->valid_blocksize(cipher->block_size()))
00031       throw std::invalid_argument("Padding " + m_padding->name() +
00032                                   " cannot be used with " +
00033                                   cipher->name() + "/ECB");
00034    }
00035 
00036 void ECB_Mode::clear()
00037    {
00038    m_cipher->clear();
00039    }
00040 
00041 std::string ECB_Mode::name() const
00042    {
00043    return cipher().name() + "/ECB/" + padding().name();
00044    }
00045 
00046 size_t ECB_Mode::update_granularity() const
00047    {
00048    return cipher().parallel_bytes();
00049    }
00050 
00051 Key_Length_Specification ECB_Mode::key_spec() const
00052    {
00053    return cipher().key_spec();
00054    }
00055 
00056 size_t ECB_Mode::default_nonce_length() const
00057    {
00058    return 0;
00059    }
00060 
00061 bool ECB_Mode::valid_nonce_length(size_t n) const
00062    {
00063    return (n == 0);
00064    }
00065 
00066 void ECB_Mode::key_schedule(const byte key[], size_t length)
00067    {
00068    m_cipher->set_key(key, length);
00069    }
00070 
00071 secure_vector<byte> ECB_Mode::start_raw(const byte[], size_t nonce_len)
00072    {
00073    if(!valid_nonce_length(nonce_len))
00074       throw Invalid_IV_Length(name(), nonce_len);
00075 
00076    return secure_vector<byte>();
00077    }
00078 
00079 size_t ECB_Encryption::minimum_final_size() const
00080    {
00081    return 0;
00082    }
00083 
00084 size_t ECB_Encryption::output_length(size_t input_length) const
00085    {
00086    return round_up(input_length, cipher().block_size());
00087    }
00088 
00089 void ECB_Encryption::update(secure_vector<byte>& buffer, size_t offset)
00090    {
00091    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00092    const size_t sz = buffer.size() - offset;
00093    byte* buf = &buffer[offset];
00094 
00095    const size_t BS = cipher().block_size();
00096 
00097    BOTAN_ASSERT(sz % BS == 0, "ECB input is full blocks");
00098    const size_t blocks = sz / BS;
00099 
00100    cipher().encrypt_n(&buf[0], &buf[0], blocks);
00101    }
00102 
00103 void ECB_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
00104    {
00105    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00106    const size_t sz = buffer.size() - offset;
00107 
00108    const size_t BS = cipher().block_size();
00109 
00110    const size_t bytes_in_final_block = sz % BS;
00111 
00112    padding().add_padding(buffer, bytes_in_final_block, BS);
00113 
00114    if(buffer.size() % BS)
00115       throw std::runtime_error("Did not pad to full block size in " + name());
00116 
00117    update(buffer, offset);
00118    }
00119 
00120 size_t ECB_Decryption::output_length(size_t input_length) const
00121    {
00122    return input_length;
00123    }
00124 
00125 size_t ECB_Decryption::minimum_final_size() const
00126    {
00127    return cipher().block_size();
00128    }
00129 
00130 void ECB_Decryption::update(secure_vector<byte>& buffer, size_t offset)
00131    {
00132    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00133    const size_t sz = buffer.size() - offset;
00134    byte* buf = &buffer[offset];
00135 
00136    const size_t BS = cipher().block_size();
00137 
00138    BOTAN_ASSERT(sz % BS == 0, "Input is full blocks");
00139    size_t blocks = sz / BS;
00140 
00141    cipher().decrypt_n(&buf[0], &buf[0], blocks);
00142    }
00143 
00144 void ECB_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
00145    {
00146    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00147    const size_t sz = buffer.size() - offset;
00148 
00149    const size_t BS = cipher().block_size();
00150 
00151    if(sz == 0 || sz % BS)
00152       throw Decoding_Error(name() + ": Ciphertext not a multiple of block size");
00153 
00154    update(buffer, offset);
00155 
00156    const size_t pad_bytes = BS - padding().unpad(&buffer[buffer.size()-BS], BS);
00157    buffer.resize(buffer.size() - pad_bytes); // remove padding
00158    }
00159 
00160 }