diff options
-rw-r--r-- | src/filters/modes/xts/xts.cpp | 128 | ||||
-rw-r--r-- | src/filters/modes/xts/xts.h | 11 |
2 files changed, 62 insertions, 77 deletions
diff --git a/src/filters/modes/xts/xts.cpp b/src/filters/modes/xts/xts.cpp index c9b77e1eb..67746d554 100644 --- a/src/filters/modes/xts/xts.cpp +++ b/src/filters/modes/xts/xts.cpp @@ -10,6 +10,8 @@ #include <algorithm> #include <stdexcept> +using namespace std::tr1::placeholders; + namespace Botan { namespace { @@ -35,15 +37,17 @@ void poly_double(byte tweak[], u32bit size) /* * XTS_Encryption constructor */ -XTS_Encryption::XTS_Encryption(BlockCipher* ciph) : cipher(ciph) +XTS_Encryption::XTS_Encryption(BlockCipher* ciph) : + cipher(ciph), + buf_op(std::tr1::bind(&XTS_Encryption::xts_encrypt, this, _1, _2), + std::tr1::bind(&XTS_Encryption::xts_final, this, _1, _2), + 2 * cipher->BLOCK_SIZE, 1) { if(cipher->BLOCK_SIZE != 16) throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); cipher2 = cipher->clone(); - tweak.resize(cipher->BLOCK_SIZE); - buffer.resize(2 * cipher->BLOCK_SIZE); - position = 0; + tweak.resize(BOTAN_PARALLEL_BLOCKS_XTS * cipher->BLOCK_SIZE); } /* @@ -51,15 +55,17 @@ XTS_Encryption::XTS_Encryption(BlockCipher* ciph) : cipher(ciph) */ XTS_Encryption::XTS_Encryption(BlockCipher* ciph, const SymmetricKey& key, - const InitializationVector& iv) : cipher(ciph) + const InitializationVector& iv) : + cipher(ciph), + buf_op(std::tr1::bind(&XTS_Encryption::xts_encrypt, this, _1, _2), + std::tr1::bind(&XTS_Encryption::xts_final, this, _1, _2), + 2 * cipher->BLOCK_SIZE, cipher->BLOCK_SIZE + 1) { if(cipher->BLOCK_SIZE != 16) throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); cipher2 = cipher->clone(); - tweak.resize(cipher->BLOCK_SIZE); - buffer.resize(2 * cipher->BLOCK_SIZE); - position = 0; + tweak.resize(BOTAN_PARALLEL_BLOCKS_XTS * cipher->BLOCK_SIZE); set_key(key); set_iv(iv); @@ -78,7 +84,7 @@ std::string XTS_Encryption::name() const */ void XTS_Encryption::set_iv(const InitializationVector& iv) { - if(iv.length() != tweak.size()) + if(iv.length() != cipher->BLOCK_SIZE) throw Invalid_IV_Length(name(), iv.length()); tweak = iv.bits_of(); @@ -96,98 +102,74 @@ void XTS_Encryption::set_key(const SymmetricKey& key) cipher2->set_key(key.begin() + key_half, key_half); } -void XTS_Encryption::encrypt(const byte block[]) - { - /* - * We can always use the first 16 bytes of buffer as temp space, - * since either the input block is buffer (in which case this is - * just buffer ^= tweak) or it not, in which case we already read - * and used the data there and are processing new input. Kind of - * subtle/nasty, but saves allocating a distinct temp buf. - */ - - xor_buf(buffer, block, tweak, cipher->BLOCK_SIZE); - cipher->encrypt(buffer); - xor_buf(buffer, tweak, cipher->BLOCK_SIZE); - - poly_double(tweak, cipher->BLOCK_SIZE); - - send(buffer, cipher->BLOCK_SIZE); - } - /* * Encrypt in XTS mode */ void XTS_Encryption::write(const byte input[], u32bit length) { - const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + buf_op.write(input, length); + } +/* +* Finish encrypting in XTS mode +*/ +void XTS_Encryption::end_msg() + { + buf_op.final(); + } - u32bit copied = std::min(buffer.size() - position, length); - buffer.copy(position, input, copied); - length -= copied; - input += copied; - position += copied; +void XTS_Encryption::xts_encrypt(const byte input[], u32bit length) + { + u32bit blocks = length / cipher->BLOCK_SIZE; - if(length == 0) return; + SecureVector<byte> temp(cipher->BLOCK_SIZE); - encrypt(buffer); - if(length > BLOCK_SIZE) + for(u32bit i = 0; i != blocks; ++i) { - encrypt(buffer + BLOCK_SIZE); - while(length > buffer.size()) - { - encrypt(input); - length -= BLOCK_SIZE; - input += BLOCK_SIZE; - } - position = 0; - } - else - { - copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE); - position = BLOCK_SIZE; + xor_buf(temp, input + i * cipher->BLOCK_SIZE, tweak, + cipher->BLOCK_SIZE); + + cipher->encrypt(temp); + xor_buf(temp, tweak, cipher->BLOCK_SIZE); + + poly_double(tweak, cipher->BLOCK_SIZE); + + send(temp, cipher->BLOCK_SIZE); } - buffer.copy(position, input, length); - position += length; } /* * Finish encrypting in XTS mode */ -void XTS_Encryption::end_msg() +void XTS_Encryption::xts_final(const byte input[], u32bit length) { - const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; - - if(position < BLOCK_SIZE) + if(length < cipher->BLOCK_SIZE) throw Exception("XTS_Encryption: insufficient data to encrypt"); - else if(position == BLOCK_SIZE) - { - encrypt(buffer); - } - else if(position == 2*BLOCK_SIZE) + + if(length % cipher->BLOCK_SIZE == 0) { - encrypt(buffer); - encrypt(buffer + BLOCK_SIZE); + xts_encrypt(input, length); } else { // steal ciphertext - xor_buf(buffer, tweak, cipher->BLOCK_SIZE); - cipher->encrypt(buffer); - xor_buf(buffer, tweak, cipher->BLOCK_SIZE); + SecureVector<byte> temp(input, length); + + xor_buf(temp, tweak, cipher->BLOCK_SIZE); + cipher->encrypt(temp); + xor_buf(temp, tweak, cipher->BLOCK_SIZE); poly_double(tweak, cipher->BLOCK_SIZE); - for(u32bit i = 0; i != position - cipher->BLOCK_SIZE; ++i) - std::swap(buffer[i], buffer[i + cipher->BLOCK_SIZE]); + for(u32bit i = 0; i != length - cipher->BLOCK_SIZE; ++i) + std::swap(temp[i], temp[i + cipher->BLOCK_SIZE]); - xor_buf(buffer, tweak, cipher->BLOCK_SIZE); - cipher->encrypt(buffer); - xor_buf(buffer, tweak, cipher->BLOCK_SIZE); + xor_buf(temp, tweak, cipher->BLOCK_SIZE); + cipher->encrypt(temp); + xor_buf(temp, tweak, cipher->BLOCK_SIZE); - send(buffer, position); + send(temp, temp.size()); } - position = 0; + buf_op.reset(); } /* diff --git a/src/filters/modes/xts/xts.h b/src/filters/modes/xts/xts.h index 9badd3666..3abe6be3e 100644 --- a/src/filters/modes/xts/xts.h +++ b/src/filters/modes/xts/xts.h @@ -8,8 +8,9 @@ #ifndef BOTAN_XTS_H__ #define BOTAN_XTS_H__ -#include <botan/key_filt.h> #include <botan/block_cipher.h> +#include <botan/key_filt.h> +#include <botan/buf_op.h> namespace Botan { @@ -37,13 +38,15 @@ class BOTAN_DLL XTS_Encryption : public Keyed_Filter private: void write(const byte[], u32bit); void end_msg(); - void encrypt(const byte block[]); + + void xts_encrypt(const byte input[], u32bit input_length); + void xts_final(const byte input[], u32bit input_length); BlockCipher* cipher; BlockCipher* cipher2; SecureVector<byte> tweak; - SecureVector<byte> buffer; - u32bit position; + + Buffered_Operation buf_op; }; /* |