Botan 1.10.17
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
12namespace 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();
57 }
58
59/*
60* Encrypt in CBC mode
61*/
62void 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*/
77void 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
85void CBC_Encryption::write(const byte input[], size_t input_length)
86 {
87 Buffered_Filter::write(input, input_length);
88 }
89
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*/
107std::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*/
162void 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*/
194void 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*/
215void 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*/
224 {
226 }
227
228/*
229* Return a CBC mode name
230*/
231std::string CBC_Decryption::name() const
232 {
233 return (cipher->name() + "/CBC/" + padder->name());
234 }
235
236}
virtual void decrypt_n(const byte in[], byte out[], size_t blocks) const =0
void encrypt(const byte in[], byte out[]) const
virtual size_t block_size() const =0
size_t current_position() const
Definition buf_filt.h:72
Buffered_Filter(size_t block_size, size_t final_minimum)
Definition buf_filt.cpp:18
void write(const byte in[], size_t length)
Definition buf_filt.cpp:34
size_t buffered_block_size() const
Definition buf_filt.h:67
void set_iv(const InitializationVector &iv)
Definition cbc.cpp:150
std::string name() const
Definition cbc.cpp:231
void set_key(const SymmetricKey &key)
Definition cbc.h:69
bool valid_iv_length(size_t iv_len) const
Definition cbc.h:74
CBC_Decryption(BlockCipher *cipher, BlockCipherModePaddingMethod *padding)
Definition cbc.cpp:115
void set_iv(const InitializationVector &iv)
Definition cbc.cpp:50
CBC_Encryption(BlockCipher *cipher, BlockCipherModePaddingMethod *padding)
Definition cbc.cpp:17
bool valid_iv_length(size_t iv_len) const
Definition cbc.h:34
void set_key(const SymmetricKey &key)
Definition cbc.h:29
std::string name() const
Definition cbc.cpp:107
void send(const byte in[], size_t length)
Definition filter.cpp:28
size_t size() const
Definition secmem.h:29
SecureVector< byte > bits_of() const
Definition symkey.h:30
size_t length() const
Definition symkey.h:25
OctetString SymmetricKey
Definition symkey.h:147
void xor_buf(byte out[], const byte in[], size_t length)
Definition xor_buf.h:21
void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:22
OctetString InitializationVector
Definition symkey.h:152
Decoding_Error(const std::string &name)
Definition exceptn.h:140
Encoding_Error(const std::string &name)
Definition exceptn.h:131
Invalid_IV_Length(const std::string &mode, size_t bad_len)
Definition exceptn.h:80