Botan
1.11.15
|
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 }