diff options
author | lloyd <[email protected]> | 2009-08-11 02:31:17 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-08-11 02:31:17 +0000 |
commit | f51841ba5237952dda3e76df643d3ae13bed3df5 (patch) | |
tree | 7fd004a107bae55a5f87c4e8bc35b0012334b29b /src/modes/ctr | |
parent | 34eb8de4ed014ab8913bdb34b096d60880b1c14a (diff) |
Change the BlockCipher interface to support multi-block encryption and
decryption. Currently only used for counter mode. Doesn't offer much
advantage as-is (though might help slightly, in terms of cache effects),
but allows for SIMD implementations to process multiple blocks in parallel
when possible. Particularly thinking here of Serpent; TEA/XTEA also seem
promising in this sense, as is Threefish once that is implemented as a
standalone block cipher.
Diffstat (limited to 'src/modes/ctr')
-rw-r--r-- | src/modes/ctr/ctr.cpp | 104 | ||||
-rw-r--r-- | src/modes/ctr/ctr.h | 17 |
2 files changed, 99 insertions, 22 deletions
diff --git a/src/modes/ctr/ctr.cpp b/src/modes/ctr/ctr.cpp index 9eb42ec5a..5c27ca63c 100644 --- a/src/modes/ctr/ctr.cpp +++ b/src/modes/ctr/ctr.cpp @@ -1,6 +1,6 @@ /* * CTR Mode -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -14,9 +14,13 @@ namespace Botan { /* * CTR-BE Constructor */ -CTR_BE::CTR_BE(BlockCipher* ciph) : - BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1) +CTR_BE::CTR_BE(BlockCipher* ciph) : cipher(ciph) { + base_ptr = cipher; + position = 0; + + counter.create(ciph->BLOCK_SIZE * CTR_BLOCKS_PARALLEL); + enc_buffer.create(ciph->BLOCK_SIZE * CTR_BLOCKS_PARALLEL); } /* @@ -24,39 +28,86 @@ CTR_BE::CTR_BE(BlockCipher* ciph) : */ CTR_BE::CTR_BE(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv) : - BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1) + cipher(ciph) { + base_ptr = cipher; + position = 0; + + counter.create(ciph->BLOCK_SIZE * CTR_BLOCKS_PARALLEL); + enc_buffer.create(ciph->BLOCK_SIZE * CTR_BLOCKS_PARALLEL); + set_key(key); set_iv(iv); } /* +* CTR_BE Destructor +*/ +CTR_BE::~CTR_BE() + { + delete cipher; + } + +/* +* Return the name of this type +*/ +std::string CTR_BE::name() const + { + return ("CTR-BE/" + cipher->name()); + } + +/* +* Set CTR-BE IV +*/ +void CTR_BE::set_iv(const InitializationVector& iv) + { + if(iv.length() != cipher->BLOCK_SIZE) + throw Invalid_IV_Length(name(), iv.length()); + + enc_buffer.clear(); + position = 0; + + for(u32bit i = 0; i != CTR_BLOCKS_PARALLEL; ++i) + { + counter.copy(i*cipher->BLOCK_SIZE, iv.begin(), iv.length()); + + // FIXME: this is stupid + for(u32bit j = 0; j != i; ++j) + for(s32bit k = cipher->BLOCK_SIZE - 1; k >= 0; --k) + if(++counter[i*cipher->BLOCK_SIZE+k]) + break; + } + + cipher->encrypt_n(counter, enc_buffer, CTR_BLOCKS_PARALLEL); + } + +/* * CTR-BE Encryption/Decryption */ void CTR_BE::write(const byte input[], u32bit length) { - u32bit copied = std::min(BLOCK_SIZE - position, length); - xor_buf(buffer + position, input, copied); - send(buffer + position, copied); + u32bit copied = std::min(enc_buffer.size() - position, length); + xor_buf(enc_buffer + position, input, copied); + send(enc_buffer + position, copied); input += copied; length -= copied; position += copied; - if(position == BLOCK_SIZE) + if(position == enc_buffer.size()) increment_counter(); - while(length >= BLOCK_SIZE) + while(length >= enc_buffer.size()) { - xor_buf(buffer, input, BLOCK_SIZE); - send(buffer, BLOCK_SIZE); + xor_buf(enc_buffer, input, enc_buffer.size()); + send(enc_buffer, enc_buffer.size()); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; + input += enc_buffer.size(); + length -= enc_buffer.size(); increment_counter(); } - xor_buf(buffer + position, input, length); - send(buffer + position, length); + xor_buf(enc_buffer + position, input, length); + send(enc_buffer + position, length); position += length; } @@ -65,10 +116,25 @@ void CTR_BE::write(const byte input[], u32bit length) */ void CTR_BE::increment_counter() { - for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) - if(++state[j]) - break; - cipher->encrypt(state, buffer); + for(u32bit i = 0; i != CTR_BLOCKS_PARALLEL; ++i) + { + // FIXME: Can do it in a single loop + /* + for(u32bit j = 1; j != cipher->BLOCK_SIZE; ++j) + { + byte carry = 0; + byte z = counter[(i+1)*cipher->BLOCK_SIZE-1] + CTR_BLOCKS_PARALLEL; + + if( + */ + for(u32bit j = 0; j != CTR_BLOCKS_PARALLEL; ++j) + for(s32bit k = cipher->BLOCK_SIZE - 1; k >= 0; --k) + if(++counter[i*cipher->BLOCK_SIZE+k]) + break; + } + + cipher->encrypt_n(counter, enc_buffer, CTR_BLOCKS_PARALLEL); + position = 0; } diff --git a/src/modes/ctr/ctr.h b/src/modes/ctr/ctr.h index aa0db5761..3d509f02c 100644 --- a/src/modes/ctr/ctr.h +++ b/src/modes/ctr/ctr.h @@ -8,22 +8,33 @@ #ifndef BOTAN_COUNTER_MODE_H__ #define BOTAN_COUNTER_MODE_H__ -#include <botan/modebase.h> -#include <botan/modebase.h> +#include <botan/basefilt.h> +#include <botan/block_cipher.h> namespace Botan { /* * CTR-BE Mode */ -class BOTAN_DLL CTR_BE : public BlockCipherMode +class BOTAN_DLL CTR_BE : public Keyed_Filter { public: + std::string name() const; + void set_iv(const InitializationVector&); + CTR_BE(BlockCipher*); CTR_BE(BlockCipher*, const SymmetricKey&, const InitializationVector&); + + ~CTR_BE(); private: + static const u32bit CTR_BLOCKS_PARALLEL = 8; + void write(const byte[], u32bit); void increment_counter(); + + BlockCipher* cipher; + SecureVector<byte> counter, enc_buffer; + u32bit position; }; } |