diff options
author | lloyd <[email protected]> | 2010-01-25 14:12:19 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2010-01-25 14:12:19 +0000 |
commit | 9a75697edcf97b16c98cc03446553616e8ddcde1 (patch) | |
tree | 10fbf6c0aa839c3b669295fea5f8a193ab6aa1b7 /src/filters/modes | |
parent | c7ea08323594f22ac9b98fd9c6cdb7bb5fffb0d4 (diff) |
Fix several buffering problems in the XTS implementation that would
cause bad results if the input was not an even multiple of the block
size.
No released version was broken because the changes which caused the
problem were related to using Buffered_Filter, which was introduced
after 1.9.3 was released.
Add more XTS test vectors using AES, Serpent, and Twofish. The AES
tests come from Brian Gladman's XTS implementation. The Serpent and
Twofish tests were generated by botan.
Diffstat (limited to 'src/filters/modes')
-rw-r--r-- | src/filters/modes/xts/xts.cpp | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/src/filters/modes/xts/xts.cpp b/src/filters/modes/xts/xts.cpp index cfea0b34b..68eb0c482 100644 --- a/src/filters/modes/xts/xts.cpp +++ b/src/filters/modes/xts/xts.cpp @@ -176,6 +176,18 @@ void XTS_Encryption::buffered_final(const byte input[], u32bit length) } else { // steal ciphertext + + u32bit leftover_blocks = + ((length / cipher->BLOCK_SIZE) - 1) * cipher->BLOCK_SIZE; + + buffered_block(input, leftover_blocks); + + input += leftover_blocks; + length -= leftover_blocks; + + if(length >= 2*cipher->BLOCK_SIZE) + throw std::runtime_error("Die vampire die"); + SecureVector<byte> temp(input, length); xor_buf(temp, tweak, cipher->BLOCK_SIZE); @@ -201,7 +213,8 @@ void XTS_Encryption::buffered_final(const byte input[], u32bit length) * XTS_Decryption constructor */ XTS_Decryption::XTS_Decryption(BlockCipher* ciph) : - Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE, 1) + Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE, + ciph->BLOCK_SIZE + 1) { cipher = ciph; cipher2 = ciph->clone(); @@ -214,7 +227,8 @@ XTS_Decryption::XTS_Decryption(BlockCipher* ciph) : XTS_Decryption::XTS_Decryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv) : - Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE, 1) + Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE, + ciph->BLOCK_SIZE + 1) { cipher = ciph; cipher2 = ciph->clone(); @@ -320,18 +334,26 @@ void XTS_Decryption::buffered_block(const byte input[], u32bit input_length) } } -void XTS_Decryption::buffered_final(const byte input[], u32bit input_length) +void XTS_Decryption::buffered_final(const byte input[], u32bit length) { - if(input_length <= cipher->BLOCK_SIZE) + if(length <= cipher->BLOCK_SIZE) throw Decoding_Error("XTS_Decryption: insufficient data to decrypt"); - if(input_length % cipher->BLOCK_SIZE == 0) + if(length % cipher->BLOCK_SIZE == 0) { - buffered_block(input, input_length); + buffered_block(input, length); } else { - SecureVector<byte> temp(input, input_length); + u32bit leftover_blocks = + ((length / cipher->BLOCK_SIZE) - 1) * cipher->BLOCK_SIZE; + + buffered_block(input, leftover_blocks); + + input += leftover_blocks; + length -= leftover_blocks; + + SecureVector<byte> temp(input, length); SecureVector<byte> tweak_copy(&tweak[0], cipher->BLOCK_SIZE); poly_double(tweak_copy, cipher->BLOCK_SIZE); @@ -340,14 +362,14 @@ void XTS_Decryption::buffered_final(const byte input[], u32bit input_length) cipher->decrypt(temp); xor_buf(temp, tweak_copy, cipher->BLOCK_SIZE); - for(u32bit i = 0; i != input_length - cipher->BLOCK_SIZE; ++i) + for(u32bit i = 0; i != length - cipher->BLOCK_SIZE; ++i) std::swap(temp[i], temp[i + cipher->BLOCK_SIZE]); xor_buf(temp, tweak, cipher->BLOCK_SIZE); cipher->decrypt(temp); xor_buf(temp, tweak, cipher->BLOCK_SIZE); - send(temp, input_length); + send(temp, length); } buffer_reset(); |