00001
00002
00003
00004
00005
00006
00007
00008 #include <botan/cbc.h>
00009 #include <botan/internal/xor_buf.h>
00010 #include <algorithm>
00011
00012 namespace Botan {
00013
00014
00015
00016
00017 CBC_Encryption::CBC_Encryption(BlockCipher* ciph,
00018 BlockCipherModePaddingMethod* pad) :
00019 Buffered_Filter(ciph->BLOCK_SIZE, 0),
00020 cipher(ciph), padder(pad)
00021 {
00022 if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
00023 throw Invalid_Block_Size(name(), padder->name());
00024
00025 state.resize(cipher->BLOCK_SIZE);
00026 }
00027
00028
00029
00030
00031 CBC_Encryption::CBC_Encryption(BlockCipher* ciph,
00032 BlockCipherModePaddingMethod* pad,
00033 const SymmetricKey& key,
00034 const InitializationVector& iv) :
00035 Buffered_Filter(ciph->BLOCK_SIZE, 0),
00036 cipher(ciph), padder(pad)
00037 {
00038 if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
00039 throw Invalid_Block_Size(name(), padder->name());
00040
00041 state.resize(cipher->BLOCK_SIZE);
00042
00043 set_key(key);
00044 set_iv(iv);
00045 }
00046
00047
00048
00049
00050 void CBC_Encryption::set_iv(const InitializationVector& iv)
00051 {
00052 if(!valid_iv_length(iv.length()))
00053 throw Invalid_IV_Length(name(), iv.length());
00054
00055 state = iv.bits_of();
00056 buffer_reset();
00057 }
00058
00059
00060
00061
00062 void CBC_Encryption::buffered_block(const byte input[], u32bit length)
00063 {
00064 u32bit blocks = length / state.size();
00065
00066 for(u32bit i = 0; i != blocks; ++i)
00067 {
00068 xor_buf(state, input + i * cipher->BLOCK_SIZE, state.size());
00069 cipher->encrypt(state);
00070 send(state, state.size());
00071 }
00072 }
00073
00074
00075
00076
00077 void CBC_Encryption::buffered_final(const byte input[], u32bit length)
00078 {
00079 if(length % cipher->BLOCK_SIZE == 0)
00080 buffered_block(input, length);
00081 else if(length != 0)
00082 throw Encoding_Error(name() + ": Did not pad to full blocksize");
00083 }
00084
00085 void CBC_Encryption::write(const byte input[], u32bit input_length)
00086 {
00087 Buffered_Filter::write(input, input_length);
00088 }
00089
00090 void CBC_Encryption::end_msg()
00091 {
00092 u32bit last_block = current_position() % cipher->BLOCK_SIZE;
00093
00094 SecureVector<byte> padding(cipher->BLOCK_SIZE);
00095 padder->pad(padding, padding.size(), last_block);
00096
00097 u32bit pad_bytes = padder->pad_bytes(cipher->BLOCK_SIZE, last_block);
00098
00099 if(pad_bytes)
00100 Buffered_Filter::write(padding, pad_bytes);
00101 Buffered_Filter::end_msg();
00102 }
00103
00104
00105
00106
00107 std::string CBC_Encryption::name() const
00108 {
00109 return (cipher->name() + "/CBC/" + padder->name());
00110 }
00111
00112
00113
00114
00115 CBC_Decryption::CBC_Decryption(BlockCipher* ciph,
00116 BlockCipherModePaddingMethod* pad) :
00117 Buffered_Filter(ciph->parallel_bytes(), ciph->BLOCK_SIZE),
00118 cipher(ciph), padder(pad)
00119 {
00120 if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
00121 throw Invalid_Block_Size(name(), padder->name());
00122
00123 state.resize(cipher->BLOCK_SIZE);
00124 temp.resize(buffered_block_size());
00125 }
00126
00127
00128
00129
00130 CBC_Decryption::CBC_Decryption(BlockCipher* ciph,
00131 BlockCipherModePaddingMethod* pad,
00132 const SymmetricKey& key,
00133 const InitializationVector& iv) :
00134 Buffered_Filter(ciph->parallel_bytes(), ciph->BLOCK_SIZE),
00135 cipher(ciph), padder(pad)
00136 {
00137 if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
00138 throw Invalid_Block_Size(name(), padder->name());
00139
00140 state.resize(cipher->BLOCK_SIZE);
00141 temp.resize(buffered_block_size());
00142
00143 set_key(key);
00144 set_iv(iv);
00145 }
00146
00147
00148
00149
00150 void CBC_Decryption::set_iv(const InitializationVector& iv)
00151 {
00152 if(!valid_iv_length(iv.length()))
00153 throw Invalid_IV_Length(name(), iv.length());
00154
00155 state = iv.bits_of();
00156 buffer_reset();
00157 }
00158
00159
00160
00161
00162 void CBC_Decryption::buffered_block(const byte input[], u32bit length)
00163 {
00164 const u32bit blocks_in_temp = temp.size() / cipher->BLOCK_SIZE;
00165 u32bit blocks = length / cipher->BLOCK_SIZE;
00166
00167 while(blocks)
00168 {
00169 u32bit to_proc = std::min<u32bit>(blocks, blocks_in_temp);
00170
00171 cipher->decrypt_n(input, &temp[0], to_proc);
00172
00173 xor_buf(temp, state, cipher->BLOCK_SIZE);
00174
00175 for(u32bit i = 1; i < to_proc; ++i)
00176 xor_buf(temp + i * cipher->BLOCK_SIZE,
00177 input + (i-1) * cipher->BLOCK_SIZE,
00178 cipher->BLOCK_SIZE);
00179
00180 state.set(input + (to_proc - 1) * cipher->BLOCK_SIZE, cipher->BLOCK_SIZE);
00181
00182 send(temp, to_proc * cipher->BLOCK_SIZE);
00183
00184 input += to_proc * cipher->BLOCK_SIZE;
00185 blocks -= to_proc;
00186 }
00187 }
00188
00189
00190
00191
00192 void CBC_Decryption::buffered_final(const byte input[], u32bit length)
00193 {
00194 if(length == 0 || length % cipher->BLOCK_SIZE != 0)
00195 throw Decoding_Error(name() + ": Ciphertext not multiple of block size");
00196
00197 size_t extra_blocks = (length - 1) / cipher->BLOCK_SIZE;
00198
00199 buffered_block(input, extra_blocks * cipher->BLOCK_SIZE);
00200
00201 input += extra_blocks * cipher->BLOCK_SIZE;
00202
00203 cipher->decrypt(input, temp);
00204 xor_buf(temp, state, cipher->BLOCK_SIZE);
00205 send(temp, padder->unpad(temp, cipher->BLOCK_SIZE));
00206
00207 state.set(input, state.size());
00208 }
00209
00210
00211
00212
00213 void CBC_Decryption::write(const byte input[], u32bit length)
00214 {
00215 Buffered_Filter::write(input, length);
00216 }
00217
00218
00219
00220
00221 void CBC_Decryption::end_msg()
00222 {
00223 Buffered_Filter::end_msg();
00224 }
00225
00226
00227
00228
00229 std::string CBC_Decryption::name() const
00230 {
00231 return (cipher->name() + "/CBC/" + padder->name());
00232 }
00233
00234 }