Botan
1.11.15
|
00001 /* 00002 * CBC Mode 00003 * (C) 1999-2007,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/cbc.h> 00010 #include <botan/mode_pad.h> 00011 00012 namespace Botan { 00013 00014 template<typename CBC_T, typename CTS_T> 00015 Transform* make_cbc_mode(const Transform::Spec& spec) 00016 { 00017 std::unique_ptr<BlockCipher> bc(Algo_Registry<BlockCipher>::global_registry().make(spec.arg(0))); 00018 00019 if(bc) 00020 { 00021 const std::string padding = spec.arg(1, "PKCS7"); 00022 00023 if(padding == "CTS") 00024 return new CTS_T(bc.release()); 00025 else 00026 return new CBC_T(bc.release(), get_bc_pad(padding)); 00027 } 00028 00029 return nullptr; 00030 } 00031 00032 BOTAN_REGISTER_TRANSFORM(CBC_Encryption, (make_cbc_mode<CBC_Encryption,CTS_Encryption>)); 00033 BOTAN_REGISTER_TRANSFORM(CBC_Decryption, (make_cbc_mode<CBC_Decryption,CTS_Decryption>)); 00034 00035 CBC_Mode::CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : 00036 m_cipher(cipher), 00037 m_padding(padding), 00038 m_state(m_cipher->block_size()) 00039 { 00040 if(m_padding && !m_padding->valid_blocksize(cipher->block_size())) 00041 throw std::invalid_argument("Padding " + m_padding->name() + 00042 " cannot be used with " + 00043 cipher->name() + "/CBC"); 00044 } 00045 00046 void CBC_Mode::clear() 00047 { 00048 m_cipher->clear(); 00049 m_state.clear(); 00050 } 00051 00052 std::string CBC_Mode::name() const 00053 { 00054 if(m_padding) 00055 return cipher().name() + "/CBC/" + padding().name(); 00056 else 00057 return cipher().name() + "/CBC/CTS"; 00058 } 00059 00060 size_t CBC_Mode::update_granularity() const 00061 { 00062 return cipher().parallel_bytes(); 00063 } 00064 00065 Key_Length_Specification CBC_Mode::key_spec() const 00066 { 00067 return cipher().key_spec(); 00068 } 00069 00070 size_t CBC_Mode::default_nonce_length() const 00071 { 00072 return cipher().block_size(); 00073 } 00074 00075 bool CBC_Mode::valid_nonce_length(size_t n) const 00076 { 00077 return (n == 0 || n == cipher().block_size()); 00078 } 00079 00080 void CBC_Mode::key_schedule(const byte key[], size_t length) 00081 { 00082 m_cipher->set_key(key, length); 00083 } 00084 00085 secure_vector<byte> CBC_Mode::start_raw(const byte nonce[], size_t nonce_len) 00086 { 00087 if(!valid_nonce_length(nonce_len)) 00088 throw Invalid_IV_Length(name(), nonce_len); 00089 00090 /* 00091 * A nonce of zero length means carry the last ciphertext value over 00092 * as the new IV, as unfortunately some protocols require this. If 00093 * this is the first message then we use an IV of all zeros. 00094 */ 00095 if(nonce_len) 00096 m_state.assign(nonce, nonce + nonce_len); 00097 00098 return secure_vector<byte>(); 00099 } 00100 00101 size_t CBC_Encryption::minimum_final_size() const 00102 { 00103 return 0; 00104 } 00105 00106 size_t CBC_Encryption::output_length(size_t input_length) const 00107 { 00108 return round_up(input_length, cipher().block_size()); 00109 } 00110 00111 void CBC_Encryption::update(secure_vector<byte>& buffer, size_t offset) 00112 { 00113 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00114 const size_t sz = buffer.size() - offset; 00115 byte* buf = &buffer[offset]; 00116 00117 const size_t BS = cipher().block_size(); 00118 00119 BOTAN_ASSERT(sz % BS == 0, "CBC input is full blocks"); 00120 const size_t blocks = sz / BS; 00121 00122 const byte* prev_block = state_ptr(); 00123 00124 if(blocks) 00125 { 00126 for(size_t i = 0; i != blocks; ++i) 00127 { 00128 xor_buf(&buf[BS*i], prev_block, BS); 00129 cipher().encrypt(&buf[BS*i]); 00130 prev_block = &buf[BS*i]; 00131 } 00132 00133 state().assign(&buf[BS*(blocks-1)], &buf[BS*blocks]); 00134 } 00135 } 00136 00137 void CBC_Encryption::finish(secure_vector<byte>& buffer, size_t offset) 00138 { 00139 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00140 00141 const size_t BS = cipher().block_size(); 00142 00143 const size_t bytes_in_final_block = (buffer.size()-offset) % BS; 00144 00145 padding().add_padding(buffer, bytes_in_final_block, BS); 00146 00147 if((buffer.size()-offset) % BS) 00148 throw std::runtime_error("Did not pad to full block size in " + name()); 00149 00150 update(buffer, offset); 00151 } 00152 00153 bool CTS_Encryption::valid_nonce_length(size_t n) const 00154 { 00155 return (n == cipher().block_size()); 00156 } 00157 00158 size_t CTS_Encryption::minimum_final_size() const 00159 { 00160 return cipher().block_size() + 1; 00161 } 00162 00163 size_t CTS_Encryption::output_length(size_t input_length) const 00164 { 00165 return input_length; // no ciphertext expansion in CTS 00166 } 00167 00168 void CTS_Encryption::finish(secure_vector<byte>& buffer, size_t offset) 00169 { 00170 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00171 byte* buf = &buffer[offset]; 00172 const size_t sz = buffer.size() - offset; 00173 00174 const size_t BS = cipher().block_size(); 00175 00176 if(sz < BS + 1) 00177 throw Encoding_Error(name() + ": insufficient data to encrypt"); 00178 00179 if(sz % BS == 0) 00180 { 00181 update(buffer, offset); 00182 00183 // swap last two blocks 00184 for(size_t i = 0; i != BS; ++i) 00185 std::swap(buffer[buffer.size()-BS+i], buffer[buffer.size()-2*BS+i]); 00186 } 00187 else 00188 { 00189 const size_t full_blocks = ((sz / BS) - 1) * BS; 00190 const size_t final_bytes = sz - full_blocks; 00191 BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range"); 00192 00193 secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes); 00194 buffer.resize(full_blocks + offset); 00195 update(buffer, offset); 00196 00197 xor_buf(&last[0], state_ptr(), BS); 00198 cipher().encrypt(&last[0]); 00199 00200 for(size_t i = 0; i != final_bytes - BS; ++i) 00201 { 00202 last[i] ^= last[i + BS]; 00203 last[i + BS] ^= last[i]; 00204 } 00205 00206 cipher().encrypt(&last[0]); 00207 00208 buffer += last; 00209 } 00210 } 00211 00212 size_t CBC_Decryption::output_length(size_t input_length) const 00213 { 00214 return input_length; // precise for CTS, worst case otherwise 00215 } 00216 00217 size_t CBC_Decryption::minimum_final_size() const 00218 { 00219 return cipher().block_size(); 00220 } 00221 00222 void CBC_Decryption::update(secure_vector<byte>& buffer, size_t offset) 00223 { 00224 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00225 const size_t sz = buffer.size() - offset; 00226 byte* buf = &buffer[offset]; 00227 00228 const size_t BS = cipher().block_size(); 00229 00230 BOTAN_ASSERT(sz % BS == 0, "Input is full blocks"); 00231 size_t blocks = sz / BS; 00232 00233 while(blocks) 00234 { 00235 const size_t to_proc = std::min(BS * blocks, m_tempbuf.size()); 00236 00237 cipher().decrypt_n(buf, &m_tempbuf[0], to_proc / BS); 00238 00239 xor_buf(&m_tempbuf[0], state_ptr(), BS); 00240 xor_buf(&m_tempbuf[BS], buf, to_proc - BS); 00241 copy_mem(state_ptr(), buf + (to_proc - BS), BS); 00242 00243 copy_mem(buf, &m_tempbuf[0], to_proc); 00244 00245 buf += to_proc; 00246 blocks -= to_proc / BS; 00247 } 00248 } 00249 00250 void CBC_Decryption::finish(secure_vector<byte>& buffer, size_t offset) 00251 { 00252 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00253 const size_t sz = buffer.size() - offset; 00254 00255 const size_t BS = cipher().block_size(); 00256 00257 if(sz == 0 || sz % BS) 00258 throw Decoding_Error(name() + ": Ciphertext not a multiple of block size"); 00259 00260 update(buffer, offset); 00261 00262 const size_t pad_bytes = BS - padding().unpad(&buffer[buffer.size()-BS], BS); 00263 buffer.resize(buffer.size() - pad_bytes); // remove padding 00264 } 00265 00266 bool CTS_Decryption::valid_nonce_length(size_t n) const 00267 { 00268 return (n == cipher().block_size()); 00269 } 00270 00271 size_t CTS_Decryption::minimum_final_size() const 00272 { 00273 return cipher().block_size() + 1; 00274 } 00275 00276 void CTS_Decryption::finish(secure_vector<byte>& buffer, size_t offset) 00277 { 00278 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00279 const size_t sz = buffer.size() - offset; 00280 byte* buf = &buffer[offset]; 00281 00282 const size_t BS = cipher().block_size(); 00283 00284 if(sz < BS + 1) 00285 throw Encoding_Error(name() + ": insufficient data to decrypt"); 00286 00287 if(sz % BS == 0) 00288 { 00289 // swap last two blocks 00290 00291 for(size_t i = 0; i != BS; ++i) 00292 std::swap(buffer[buffer.size()-BS+i], buffer[buffer.size()-2*BS+i]); 00293 00294 update(buffer, offset); 00295 } 00296 else 00297 { 00298 const size_t full_blocks = ((sz / BS) - 1) * BS; 00299 const size_t final_bytes = sz - full_blocks; 00300 BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range"); 00301 00302 secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes); 00303 buffer.resize(full_blocks + offset); 00304 update(buffer, offset); 00305 00306 cipher().decrypt(&last[0]); 00307 00308 xor_buf(&last[0], &last[BS], final_bytes - BS); 00309 00310 for(size_t i = 0; i != final_bytes - BS; ++i) 00311 std::swap(last[i], last[i + BS]); 00312 00313 cipher().decrypt(&last[0]); 00314 xor_buf(&last[0], state_ptr(), BS); 00315 00316 buffer += last; 00317 } 00318 } 00319 00320 }