aboutsummaryrefslogtreecommitdiffstats
path: root/src/modes/ctr
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-08-11 02:31:17 +0000
committerlloyd <[email protected]>2009-08-11 02:31:17 +0000
commitf51841ba5237952dda3e76df643d3ae13bed3df5 (patch)
tree7fd004a107bae55a5f87c4e8bc35b0012334b29b /src/modes/ctr
parent34eb8de4ed014ab8913bdb34b096d60880b1c14a (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.cpp104
-rw-r--r--src/modes/ctr/ctr.h17
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;
};
}