Botan  1.10.9
cbc.cpp
Go to the documentation of this file.
1 /*
2 * CBC Mode
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/cbc.h>
9 #include <botan/internal/xor_buf.h>
10 #include <algorithm>
11 
12 namespace Botan {
13 
14 /*
15 * CBC Encryption Constructor
16 */
19  Buffered_Filter(ciph->block_size(), 0),
20  cipher(ciph), padder(pad)
21  {
22  if(!padder->valid_blocksize(cipher->block_size()))
23  throw Invalid_Block_Size(name(), padder->name());
24 
25  state.resize(cipher->block_size());
26  }
27 
28 /*
29 * CBC Encryption Constructor
30 */
33  const SymmetricKey& key,
34  const InitializationVector& iv) :
35  Buffered_Filter(ciph->block_size(), 0),
36  cipher(ciph), padder(pad)
37  {
38  if(!padder->valid_blocksize(cipher->block_size()))
39  throw Invalid_Block_Size(name(), padder->name());
40 
41  state.resize(cipher->block_size());
42 
43  set_key(key);
44  set_iv(iv);
45  }
46 
47 /*
48 * Set the IV
49 */
51  {
52  if(!valid_iv_length(iv.length()))
53  throw Invalid_IV_Length(name(), iv.length());
54 
55  state = iv.bits_of();
56  buffer_reset();
57  }
58 
59 /*
60 * Encrypt in CBC mode
61 */
62 void CBC_Encryption::buffered_block(const byte input[], size_t length)
63  {
64  size_t blocks = length / state.size();
65 
66  for(size_t i = 0; i != blocks; ++i)
67  {
68  xor_buf(state, input + i * cipher->block_size(), state.size());
69  cipher->encrypt(state);
70  send(state, state.size());
71  }
72  }
73 
74 /*
75 * Finish encrypting in CBC mode
76 */
77 void CBC_Encryption::buffered_final(const byte input[], size_t length)
78  {
79  if(length % cipher->block_size() == 0)
80  buffered_block(input, length);
81  else if(length != 0)
82  throw Encoding_Error(name() + ": Did not pad to full blocksize");
83  }
84 
85 void CBC_Encryption::write(const byte input[], size_t input_length)
86  {
87  Buffered_Filter::write(input, input_length);
88  }
89 
90 void CBC_Encryption::end_msg()
91  {
92  size_t last_block = current_position() % cipher->block_size();
93 
94  SecureVector<byte> padding(cipher->block_size());
95  padder->pad(padding, padding.size(), last_block);
96 
97  size_t pad_bytes = padder->pad_bytes(cipher->block_size(), last_block);
98 
99  if(pad_bytes)
100  Buffered_Filter::write(padding, pad_bytes);
102  }
103 
104 /*
105 * Return a CBC mode name
106 */
107 std::string CBC_Encryption::name() const
108  {
109  return (cipher->name() + "/CBC/" + padder->name());
110  }
111 
112 /*
113 * CBC Decryption Constructor
114 */
117  Buffered_Filter(ciph->parallel_bytes(), ciph->block_size()),
118  cipher(ciph), padder(pad)
119  {
120  if(!padder->valid_blocksize(cipher->block_size()))
121  throw Invalid_Block_Size(name(), padder->name());
122 
123  state.resize(cipher->block_size());
124  temp.resize(buffered_block_size());
125  }
126 
127 /*
128 * CBC Decryption Constructor
129 */
132  const SymmetricKey& key,
133  const InitializationVector& iv) :
134  Buffered_Filter(ciph->parallel_bytes(), ciph->block_size()),
135  cipher(ciph), padder(pad)
136  {
137  if(!padder->valid_blocksize(cipher->block_size()))
138  throw Invalid_Block_Size(name(), padder->name());
139 
140  state.resize(cipher->block_size());
141  temp.resize(buffered_block_size());
142 
143  set_key(key);
144  set_iv(iv);
145  }
146 
147 /*
148 * Set the IV
149 */
151  {
152  if(!valid_iv_length(iv.length()))
153  throw Invalid_IV_Length(name(), iv.length());
154 
155  state = iv.bits_of();
156  buffer_reset();
157  }
158 
159 /*
160 * Decrypt in CBC mode
161 */
162 void CBC_Decryption::buffered_block(const byte input[], size_t length)
163  {
164  const size_t blocks_in_temp = temp.size() / cipher->block_size();
165  size_t blocks = length / cipher->block_size();
166 
167  while(blocks)
168  {
169  size_t to_proc = std::min<size_t>(blocks, blocks_in_temp);
170 
171  cipher->decrypt_n(input, &temp[0], to_proc);
172 
173  xor_buf(temp, state, cipher->block_size());
174 
175  for(size_t i = 1; i < to_proc; ++i)
176  xor_buf(&temp[i * cipher->block_size()],
177  input + (i-1) * cipher->block_size(),
178  cipher->block_size());
179 
180  copy_mem(&state[0],
181  input + (to_proc - 1) * cipher->block_size(),
182  cipher->block_size());
183 
184  send(temp, to_proc * cipher->block_size());
185 
186  input += to_proc * cipher->block_size();
187  blocks -= to_proc;
188  }
189  }
190 
191 /*
192 * Finish encrypting in CBC mode
193 */
194 void CBC_Decryption::buffered_final(const byte input[], size_t length)
195  {
196  if(length == 0 || length % cipher->block_size() != 0)
197  throw Decoding_Error(name() + ": Ciphertext not multiple of block size");
198 
199  size_t extra_blocks = (length - 1) / cipher->block_size();
200 
201  buffered_block(input, extra_blocks * cipher->block_size());
202 
203  input += extra_blocks * cipher->block_size();
204 
205  cipher->decrypt(input, temp);
206  xor_buf(temp, state, cipher->block_size());
207  send(temp, padder->unpad(temp, cipher->block_size()));
208 
209  copy_mem(&state[0], input, state.size()); // save for IV chaining
210  }
211 
212 /*
213 * Decrypt in CBC mode
214 */
215 void CBC_Decryption::write(const byte input[], size_t length)
216  {
217  Buffered_Filter::write(input, length);
218  }
219 
220 /*
221 * Finish decrypting in CBC mode
222 */
223 void CBC_Decryption::end_msg()
224  {
226  }
227 
228 /*
229 * Return a CBC mode name
230 */
231 std::string CBC_Decryption::name() const
232  {
233  return (cipher->name() + "/CBC/" + padder->name());
234  }
235 
236 }
void resize(size_t n)
Definition: secmem.h:211
void decrypt(const byte in[], byte out[]) const
Definition: block_cipher.h:57
size_t block_size
Definition: ossl_md.cpp:41
virtual bool valid_blocksize(size_t block_size) const =0
std::string name() const
Definition: cbc.cpp:231
size_t length() const
Definition: symkey.h:25
void set_iv(const InitializationVector &iv)
Definition: cbc.cpp:150
CBC_Encryption(BlockCipher *cipher, BlockCipherModePaddingMethod *padding)
Definition: cbc.cpp:17
void write(const byte in[], size_t length)
Definition: buf_filt.cpp:34
unsigned char byte
Definition: types.h:22
SecureVector< byte > bits_of() const
Definition: symkey.h:30
void send(const byte in[], size_t length)
Definition: filter.cpp:28
bool valid_iv_length(size_t iv_len) const
Definition: cbc.h:34
std::string name() const
Definition: cbc.cpp:107
size_t size() const
Definition: secmem.h:29
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:22
virtual std::string name() const =0
CBC_Decryption(BlockCipher *cipher, BlockCipherModePaddingMethod *padding)
Definition: cbc.cpp:115
void set_key(const SymmetricKey &key)
Definition: cbc.h:29
void set_key(const SymmetricKey &key)
Definition: cbc.h:69
void encrypt(const byte in[], byte out[]) const
Definition: block_cipher.h:47
size_t current_position() const
Definition: buf_filt.h:72
virtual size_t pad_bytes(size_t block_size, size_t position) const
Definition: mode_pad.cpp:17
void xor_buf(byte out[], const byte in[], size_t length)
Definition: xor_buf.h:21
bool valid_iv_length(size_t iv_len) const
Definition: cbc.h:74
virtual void decrypt_n(const byte in[], byte out[], size_t blocks) const =0
virtual std::string name() const =0
virtual size_t block_size() const =0
virtual size_t unpad(const byte block[], size_t size) const =0
virtual void pad(byte block[], size_t size, size_t current_position) const =0
size_t buffered_block_size() const
Definition: buf_filt.h:67
void set_iv(const InitializationVector &iv)
Definition: cbc.cpp:50