aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2010-01-25 14:12:19 +0000
committerlloyd <[email protected]>2010-01-25 14:12:19 +0000
commit9a75697edcf97b16c98cc03446553616e8ddcde1 (patch)
tree10fbf6c0aa839c3b669295fea5f8a193ab6aa1b7 /src
parentc7ea08323594f22ac9b98fd9c6cdb7bb5fffb0d4 (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')
-rw-r--r--src/filters/modes/xts/xts.cpp40
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();