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());
51 if(cipher->block_size() != 8 && cipher->block_size() != 16)
52 throw std::invalid_argument(
"Bad cipher for XTS: " + cipher->name());
54 cipher2 = cipher->
clone();
67 if(cipher->block_size() != 8 && cipher->block_size() != 16)
68 throw std::invalid_argument(
"Bad cipher for XTS: " + cipher->name());
70 cipher2 = cipher->
clone();
82 return (cipher->name() +
"/XTS");
93 const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
98 for(
size_t i = 1; i < blocks_in_tweak; ++i)
100 tweak.copy(i*cipher->block_size(),
101 &tweak[(i-1)*cipher->block_size()],
102 cipher->block_size());
104 poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
110 size_t key_half = key.
length() / 2;
112 if(key.
length() % 2 == 1 || !cipher->valid_keylength(key_half))
115 cipher->set_key(key.
begin(), key_half);
122 void XTS_Encryption::write(
const byte input[],
size_t length)
129 void XTS_Encryption::end_msg()
134 void XTS_Encryption::buffered_block(
const byte input[],
size_t length)
136 const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
137 size_t blocks = length / cipher->block_size();
139 SecureVector<byte> temp(tweak.size());
143 size_t to_proc = std::min(blocks, blocks_in_tweak);
144 size_t to_proc_bytes = to_proc * cipher->block_size();
146 xor_buf(temp, input, tweak, to_proc_bytes);
148 cipher->encrypt_n(&temp[0], &temp[0], to_proc);
150 xor_buf(temp, tweak, to_proc_bytes);
152 send(temp, to_proc_bytes);
154 tweak.copy(&tweak[(to_proc-1)*cipher->block_size()],
155 cipher->block_size());
156 poly_double(&tweak[0], cipher->block_size());
158 for(
size_t i = 1; i < blocks_in_tweak; ++i)
160 tweak.copy(i*cipher->block_size(),
161 &tweak[(i-1)*cipher->block_size()],
162 cipher->block_size());
164 poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
167 input += to_proc * cipher->block_size();
175 void XTS_Encryption::buffered_final(
const byte input[],
size_t length)
178 throw Encoding_Error(
"XTS_Encryption: insufficient data to encrypt");
180 if(length % cipher->block_size() == 0)
182 buffered_block(input, length);
187 size_t leftover_blocks =
188 ((length / cipher->block_size()) - 1) * cipher->block_size();
190 buffered_block(input, leftover_blocks);
192 input += leftover_blocks;
193 length -= leftover_blocks;
195 SecureVector<byte> temp(input, length);
197 xor_buf(temp, tweak, cipher->block_size());
198 cipher->encrypt(temp);
199 xor_buf(temp, tweak, cipher->block_size());
201 poly_double(&tweak[0], cipher->block_size());
203 for(
size_t i = 0; i != length - cipher->block_size(); ++i)
204 std::swap(temp[i], temp[i + cipher->block_size()]);
206 xor_buf(temp, tweak, cipher->block_size());
207 cipher->encrypt(temp);
208 xor_buf(temp, tweak, cipher->block_size());
210 send(temp, temp.size());
223 if(cipher->block_size() != 8 && cipher->block_size() != 16)
224 throw std::invalid_argument(
"Bad cipher for XTS: " + cipher->name());
226 cipher2 = ciph->
clone();
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();
254 return (cipher->name() +
"/XTS");
265 const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
270 for(
size_t i = 1; i < blocks_in_tweak; ++i)
272 tweak.copy(i*cipher->block_size(),
273 &tweak[(i-1)*cipher->block_size()],
274 cipher->block_size());
276 poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
282 size_t key_half = key.
length() / 2;
284 if(key.
length() % 2 == 1 || !cipher->valid_keylength(key_half))
287 cipher->set_key(key.
begin(), key_half);
294 void XTS_Decryption::write(
const byte input[],
size_t length)
302 void XTS_Decryption::end_msg()
307 void XTS_Decryption::buffered_block(
const byte input[],
size_t input_length)
309 const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
310 size_t blocks = input_length / cipher->block_size();
312 SecureVector<byte> temp(tweak.size());
316 size_t to_proc = std::min(blocks, blocks_in_tweak);
317 size_t to_proc_bytes = to_proc * cipher->block_size();
319 xor_buf(temp, input, tweak, to_proc_bytes);
321 cipher->decrypt_n(&temp[0], &temp[0], to_proc);
323 xor_buf(temp, tweak, to_proc_bytes);
325 send(temp, to_proc_bytes);
327 tweak.copy(&tweak[(to_proc-1)*cipher->block_size()],
328 cipher->block_size());
329 poly_double(&tweak[0], cipher->block_size());
331 for(
size_t i = 1; i < blocks_in_tweak; ++i)
333 tweak.copy(i*cipher->block_size(),
334 &tweak[(i-1)*cipher->block_size()],
335 cipher->block_size());
337 poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
340 input += to_proc * cipher->block_size();
345 void XTS_Decryption::buffered_final(
const byte input[],
size_t length)
348 throw Decoding_Error(
"XTS_Decryption: insufficient data to decrypt");
350 if(length % cipher->block_size() == 0)
352 buffered_block(input, length);
356 size_t leftover_blocks =
357 ((length / cipher->block_size()) - 1) * cipher->block_size();
359 buffered_block(input, leftover_blocks);
361 input += leftover_blocks;
362 length -= leftover_blocks;
364 SecureVector<byte> temp(input, length);
365 SecureVector<byte> tweak_copy(&tweak[0], cipher->block_size());
367 poly_double(&tweak_copy[0], cipher->block_size());
369 xor_buf(temp, tweak_copy, cipher->block_size());
370 cipher->decrypt(temp);
371 xor_buf(temp, tweak_copy, cipher->block_size());
373 for(
size_t i = 0; i != length - cipher->block_size(); ++i)
374 std::swap(temp[i], temp[i + cipher->block_size()]);
376 xor_buf(temp, tweak, cipher->block_size());
377 cipher->decrypt(temp);
378 xor_buf(temp, tweak, cipher->block_size());
virtual BlockCipher * clone() const =0
XTS_Encryption(BlockCipher *ciph)
void write(const byte in[], size_t length)
void send(const byte in[], size_t length)
void set_key(const SymmetricKey &key)
const byte * begin() const
void set_iv(const InitializationVector &iv)
bool valid_iv_length(size_t iv_len) const
bool valid_iv_length(size_t iv_len) const
void set_iv(const InitializationVector &iv)
XTS_Decryption(BlockCipher *ciph)
void encrypt(const byte in[], byte out[]) const
void swap(Botan::MemoryRegion< T > &x, Botan::MemoryRegion< T > &y)
void xor_buf(byte out[], const byte in[], size_t length)
void set_key(const SymmetricKey &key)
size_t buffered_block_size() const
void set_key(const SymmetricKey &key)