9 #include <botan/internal/xor_buf.h>
17 void poly_double(
byte tweak[],
size_t size)
19 const byte polynomial = (size == 16) ? 0x87 : 0x1B;
22 for(
size_t i = 0; i != size; ++i)
24 byte carry2 = (tweak[i] >> 7);
25 tweak[i] = (tweak[i] << 1) | carry;
30 tweak[0] ^= polynomial;
36 size_t xts_parallelism(BlockCipher* cipher)
38 return std::max<size_t>(cipher->parallel_bytes(),
39 2 * cipher->block_size());
42 Key_Length_Specification xts_key_spec(
const BlockCipher& cipher)
44 const Key_Length_Specification& spec = cipher.key_spec();
46 return Key_Length_Specification(2*spec.minimum_keylength(),
47 2*spec.maximum_keylength(),
48 2*spec.keylength_multiple());
60 if(cipher->block_size() != 8 && cipher->block_size() != 16)
61 throw std::invalid_argument(
"Bad cipher for XTS: " + cipher->name());
63 cipher2 = cipher->
clone();
76 if(cipher->block_size() != 8 && cipher->block_size() != 16)
77 throw std::invalid_argument(
"Bad cipher for XTS: " + cipher->name());
79 cipher2 = cipher->
clone();
91 return (cipher->name() +
"/XTS");
96 return xts_key_spec(*cipher);
107 const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
112 for(
size_t i = 1; i < blocks_in_tweak; ++i)
115 &tweak[(i-1)*cipher->block_size()],
116 cipher->block_size());
118 poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
124 size_t key_half = key.
length() / 2;
126 if(key.
length() % 2 == 1 || !cipher->valid_keylength(key_half))
129 cipher->set_key(key.
begin(), key_half);
136 void XTS_Encryption::write(
const byte input[],
size_t length)
143 void XTS_Encryption::end_msg()
148 void XTS_Encryption::buffered_block(
const byte input[],
size_t length)
150 const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
151 size_t blocks = length / cipher->block_size();
153 secure_vector<byte> temp(tweak.size());
157 size_t to_proc = std::min(blocks, blocks_in_tweak);
158 size_t to_proc_bytes = to_proc * cipher->block_size();
160 xor_buf(temp, input, tweak, to_proc_bytes);
162 cipher->encrypt_n(&temp[0], &temp[0], to_proc);
164 xor_buf(temp, tweak, to_proc_bytes);
166 send(temp, to_proc_bytes);
169 &tweak[(to_proc-1)*cipher->block_size()],
170 cipher->block_size());
172 poly_double(&tweak[0], cipher->block_size());
174 for(
size_t i = 1; i < blocks_in_tweak; ++i)
177 &tweak[(i-1)*cipher->block_size()],
178 cipher->block_size());
180 poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
183 input += to_proc * cipher->block_size();
191 void XTS_Encryption::buffered_final(
const byte input[],
size_t length)
193 if(length <= cipher->block_size())
194 throw Encoding_Error(
"XTS_Encryption: insufficient data to encrypt");
196 if(length % cipher->block_size() == 0)
198 buffered_block(input, length);
203 size_t leftover_blocks =
204 ((length / cipher->block_size()) - 1) * cipher->block_size();
206 buffered_block(input, leftover_blocks);
208 input += leftover_blocks;
209 length -= leftover_blocks;
211 secure_vector<byte> temp(input, input + length);
213 xor_buf(temp, tweak, cipher->block_size());
214 cipher->encrypt(temp);
215 xor_buf(temp, tweak, cipher->block_size());
217 poly_double(&tweak[0], cipher->block_size());
219 for(
size_t i = 0; i != length - cipher->block_size(); ++i)
220 std::swap(temp[i], temp[i + cipher->block_size()]);
222 xor_buf(temp, tweak, cipher->block_size());
223 cipher->encrypt(temp);
224 xor_buf(temp, tweak, cipher->block_size());
226 send(temp, temp.size());
239 if(cipher->block_size() != 8 && cipher->block_size() != 16)
240 throw std::invalid_argument(
"Bad cipher for XTS: " + cipher->name());
242 cipher2 = ciph->
clone();
255 if(cipher->block_size() != 8 && cipher->block_size() != 16)
256 throw std::invalid_argument(
"Bad cipher for XTS: " + cipher->name());
258 cipher2 = ciph->
clone();
270 return (cipher->name() +
"/XTS");
275 return xts_key_spec(*cipher);
286 const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
291 for(
size_t i = 1; i < blocks_in_tweak; ++i)
294 &tweak[(i-1)*cipher->block_size()],
295 cipher->block_size());
297 poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
303 size_t key_half = key.
length() / 2;
305 if(key.
length() % 2 == 1 || !cipher->valid_keylength(key_half))
308 cipher->set_key(key.
begin(), key_half);
315 void XTS_Decryption::write(
const byte input[],
size_t length)
323 void XTS_Decryption::end_msg()
328 void XTS_Decryption::buffered_block(
const byte input[],
size_t input_length)
330 const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
331 size_t blocks = input_length / cipher->block_size();
333 secure_vector<byte> temp(tweak.size());
337 size_t to_proc = std::min(blocks, blocks_in_tweak);
338 size_t to_proc_bytes = to_proc * cipher->block_size();
340 xor_buf(temp, input, tweak, to_proc_bytes);
342 cipher->decrypt_n(&temp[0], &temp[0], to_proc);
344 xor_buf(temp, tweak, to_proc_bytes);
346 send(temp, to_proc_bytes);
349 &tweak[(to_proc-1)*cipher->block_size()],
350 cipher->block_size());
352 poly_double(&tweak[0], cipher->block_size());
354 for(
size_t i = 1; i < blocks_in_tweak; ++i)
357 &tweak[(i-1)*cipher->block_size()],
358 cipher->block_size());
360 poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
363 input += to_proc * cipher->block_size();
368 void XTS_Decryption::buffered_final(
const byte input[],
size_t length)
370 if(length <= cipher->block_size())
371 throw Decoding_Error(
"XTS_Decryption: insufficient data to decrypt");
373 if(length % cipher->block_size() == 0)
375 buffered_block(input, length);
379 size_t leftover_blocks =
380 ((length / cipher->block_size()) - 1) * cipher->block_size();
382 buffered_block(input, leftover_blocks);
384 input += leftover_blocks;
385 length -= leftover_blocks;
387 secure_vector<byte> temp(input, input + length);
388 secure_vector<byte> tweak_copy(&tweak[0], &tweak[cipher->block_size()]);
390 poly_double(&tweak_copy[0], cipher->block_size());
392 xor_buf(temp, tweak_copy, cipher->block_size());
393 cipher->decrypt(temp);
394 xor_buf(temp, tweak_copy, cipher->block_size());
396 for(
size_t i = 0; i != length - cipher->block_size(); ++i)
397 std::swap(temp[i], temp[i + cipher->block_size()]);
399 xor_buf(temp, tweak, cipher->block_size());
400 cipher->decrypt(temp);
401 xor_buf(temp, tweak, cipher->block_size());