aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-12-27 05:50:44 +0000
committerlloyd <[email protected]>2009-12-27 05:50:44 +0000
commitf0275263ab0dfcd11a4e193c50b248d291e2d499 (patch)
tree015f5f456ac5713454a693064f3a48d0cab51cef /src
parentf4072f413e8121e633d6882d439b2b249a535230 (diff)
Make Buffered_Filter a Filter mixin basically the same as Buffered_Operation
but using inheritence instead of std::tr1::function-based callbacks. Convert CBC and XTS modes to use it.
Diffstat (limited to 'src')
-rw-r--r--src/filters/buf_filt.cpp132
-rw-r--r--src/filters/buf_filt.h38
-rw-r--r--src/filters/modes/cbc/cbc.cpp47
-rw-r--r--src/filters/modes/cbc/cbc.h10
-rw-r--r--src/filters/modes/xts/xts.cpp36
-rw-r--r--src/filters/modes/xts/xts.h12
6 files changed, 154 insertions, 121 deletions
diff --git a/src/filters/buf_filt.cpp b/src/filters/buf_filt.cpp
index 0509e76e2..7c12cf072 100644
--- a/src/filters/buf_filt.cpp
+++ b/src/filters/buf_filt.cpp
@@ -1,71 +1,121 @@
/*
-* Buffering Filter
+* Buffered Filter
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
#include <botan/buf_filt.h>
-#include <botan/exceptn.h>
-#include <algorithm>
+#include <botan/mem_ops.h>
+#include <botan/internal/rounding.h>
+#include <stdexcept>
+
+#include <assert.h>
namespace Botan {
+namespace {
+
+const size_t BUFFER_MULTIPLE = 2;
+
+//static_assert(BUFFER_MULTIPLE >= 2, "BUFFER_MULTIPLE must be >= 2");
+
+}
+
/*
-* Buffering_Filter Constructor
+* Buffered_Filter Constructor
*/
-Buffering_Filter::Buffering_Filter(u32bit b, u32bit i) : INITIAL_BLOCK_SIZE(i),
- BLOCK_SIZE(b)
+Buffered_Filter::Buffered_Filter(u32bit b, u32bit f) :
+ main_block_mod(b), final_minimum(f)
{
- initial_block_pos = block_pos = 0;
- initial.resize(INITIAL_BLOCK_SIZE);
- block.resize(BLOCK_SIZE);
+ if(main_block_mod == 0)
+ throw std::invalid_argument("main_block_mod == 0");
+
+ if(final_minimum > main_block_mod)
+ throw std::invalid_argument("final_minimum > main_block_mod");
+
+ buffer.resize(BUFFER_MULTIPLE * main_block_mod);
+ buffer_pos = 0;
}
/*
-* Reset the Buffering Filter
+* Buffer input into blocks, trying to minimize copying
*/
-void Buffering_Filter::end_msg()
+void Buffered_Filter::write(const byte input[], u32bit input_size)
{
- if(initial_block_pos != INITIAL_BLOCK_SIZE)
- throw Exception("Buffering_Filter: Not enough data for first block");
- final_block(block, block_pos);
- initial_block_pos = block_pos = 0;
- initial.clear();
- block.clear();
+ if(!input_size)
+ return;
+
+ if(buffer_pos + input_size >= main_block_mod + final_minimum)
+ {
+ u32bit to_copy = std::min<u32bit>(buffer.size() - buffer_pos, input_size);
+
+ copy_mem(&buffer[buffer_pos], input, to_copy);
+ buffer_pos += to_copy;
+
+ input += to_copy;
+ input_size -= to_copy;
+
+ if(input_size >= final_minimum)
+ {
+ u32bit to_proc_blocks = buffer_pos / main_block_mod;
+ u32bit to_proc_bytes = to_proc_blocks * main_block_mod;
+
+ buffered_block(&buffer[0], to_proc_bytes);
+
+ buffer_pos -= to_proc_bytes;
+
+ copy_mem(&buffer[0], &buffer[to_proc_bytes], buffer_pos);
+ }
+ }
+
+ if(input_size >= final_minimum)
+ {
+ u32bit full_blocks = (input_size - final_minimum) / buffer.size();
+ u32bit to_copy = full_blocks * buffer.size();
+
+ if(to_copy)
+ {
+ buffered_block(input, to_copy);
+
+ input += to_copy;
+ input_size -= to_copy;
+ }
+ }
+
+ assert(input_size + buffer_pos <= buffer.size());
+
+ copy_mem(&buffer[buffer_pos], input, input_size);
+ buffer_pos += input_size;
}
/*
-* Buffer input into blocks
+* Finish/flush operation
*/
-void Buffering_Filter::write(const byte input[], u32bit length)
+void Buffered_Filter::end_msg()
{
- if(initial_block_pos != INITIAL_BLOCK_SIZE)
+ assert(buffer_pos >= final_minimum);
+
+ if(buffer_pos < final_minimum)
+ throw std::runtime_error("Buffered_Operation::final - not enough input");
+
+ u32bit spare_blocks = (buffer_pos - final_minimum) / main_block_mod;
+
+ if(spare_blocks)
{
- u32bit copied = std::min(INITIAL_BLOCK_SIZE - initial_block_pos, length);
- initial.copy(initial_block_pos, input, copied);
- input += copied;
- length -= copied;
- initial_block_pos += copied;
- if(initial_block_pos == INITIAL_BLOCK_SIZE)
- initial_block(initial);
+ u32bit spare_bytes = main_block_mod * spare_blocks;
+
+ assert(spare_bytes <= buffer_pos);
+
+ buffered_block(&buffer[0], spare_bytes);
+
+ assert(buffer_pos - spare_bytes >= final_minimum);
+ buffered_final(&buffer[spare_bytes], buffer_pos - spare_bytes);
}
- block.copy(block_pos, input, length);
- if(block_pos + length >= BLOCK_SIZE)
+ else
{
- main_block(block);
- input += (BLOCK_SIZE - block_pos);
- length -= (BLOCK_SIZE - block_pos);
- while(length >= BLOCK_SIZE)
- {
- main_block(input);
- input += BLOCK_SIZE;
- length -= BLOCK_SIZE;
- }
- block.copy(input, length);
- block_pos = 0;
+ buffered_final(&buffer[0], buffer_pos);
}
- block_pos += length;
}
}
diff --git a/src/filters/buf_filt.h b/src/filters/buf_filt.h
index ce3dbc926..836fa22b6 100644
--- a/src/filters/buf_filt.h
+++ b/src/filters/buf_filt.h
@@ -1,37 +1,37 @@
/*
-* Buffering Filter
+* Buffered Filter
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_BUFFERING_FILTER_H__
-#define BOTAN_BUFFERING_FILTER_H__
+#ifndef BOTAN_BUFFERED_FILTER_H__
+#define BOTAN_BUFFERED_FILTER_H__
-#include <botan/filter.h>
+#include <botan/secmem.h>
namespace Botan {
-/**
-* Buffering_Filter: This class represents filters for operations that
-* maintain an internal state.
-*/
-
-class BOTAN_DLL Buffering_Filter : public Filter
+class BOTAN_DLL Buffered_Filter
{
public:
void write(const byte[], u32bit);
- virtual void end_msg();
- Buffering_Filter(u32bit, u32bit = 0);
- virtual ~Buffering_Filter() {}
+ void end_msg();
+
+ Buffered_Filter(u32bit block_size, u32bit final_minimum);
protected:
- virtual void initial_block(const byte[]) {}
- virtual void main_block(const byte[]) = 0;
- virtual void final_block(const byte[], u32bit) = 0;
+ virtual std::string name() const = 0;
+
+ virtual void buffered_block(const byte input[], u32bit length) = 0;
+ virtual void buffered_final(const byte input[], u32bit length) = 0;
+
+ u32bit current_position() const { return buffer_pos; }
+ void buffer_reset() { buffer_pos = 0; }
private:
- const u32bit INITIAL_BLOCK_SIZE, BLOCK_SIZE;
- SecureVector<byte> initial, block;
- u32bit initial_block_pos, block_pos;
+ u32bit main_block_mod, final_minimum;
+
+ SecureVector<byte> buffer;
+ u32bit buffer_pos;
};
}
diff --git a/src/filters/modes/cbc/cbc.cpp b/src/filters/modes/cbc/cbc.cpp
index 299db1c37..352a0c60a 100644
--- a/src/filters/modes/cbc/cbc.cpp
+++ b/src/filters/modes/cbc/cbc.cpp
@@ -9,7 +9,7 @@
#include <botan/internal/xor_buf.h>
#include <algorithm>
-using namespace std::tr1::placeholders;
+#include <stdio.h>
namespace Botan {
@@ -18,10 +18,8 @@ namespace Botan {
*/
CBC_Encryption::CBC_Encryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad) :
- cipher(ciph), padder(pad),
- buf_op(std::tr1::bind(&CBC_Encryption::buffered_block, this, _1, _2),
- std::tr1::bind(&CBC_Encryption::buffered_final, this, _1, _2),
- 2 * cipher->BLOCK_SIZE)
+ Buffered_Filter(ciph->BLOCK_SIZE, 0),
+ cipher(ciph), padder(pad)
{
if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
throw Invalid_Block_Size(name(), padder->name());
@@ -36,10 +34,8 @@ CBC_Encryption::CBC_Encryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
const SymmetricKey& key,
const InitializationVector& iv) :
- cipher(ciph), padder(pad),
- buf_op(std::tr1::bind(&CBC_Encryption::buffered_block, this, _1, _2),
- std::tr1::bind(&CBC_Encryption::buffered_final, this, _1, _2),
- 2 * cipher->BLOCK_SIZE)
+ Buffered_Filter(ciph->BLOCK_SIZE, 0),
+ cipher(ciph), padder(pad)
{
if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
throw Invalid_Block_Size(name(), padder->name());
@@ -59,7 +55,7 @@ void CBC_Encryption::set_iv(const InitializationVector& iv)
throw Invalid_IV_Length(name(), iv.length());
state = iv.bits_of();
- buf_op.reset();
+ buffer_reset();
}
/*
@@ -90,20 +86,21 @@ void CBC_Encryption::buffered_final(const byte input[], u32bit length)
void CBC_Encryption::write(const byte input[], u32bit input_length)
{
- buf_op.write(input, input_length);
+ Buffered_Filter::write(input, input_length);
}
void CBC_Encryption::end_msg()
{
- u32bit last_block = buf_op.current_position() % cipher->BLOCK_SIZE;
+ u32bit last_block = current_position() % cipher->BLOCK_SIZE;
SecureVector<byte> padding(cipher->BLOCK_SIZE);
padder->pad(padding, padding.size(), last_block);
u32bit pad_bytes = padder->pad_bytes(cipher->BLOCK_SIZE, last_block);
- buf_op.write(padding, pad_bytes);
- buf_op.final();
+ if(pad_bytes)
+ Buffered_Filter::write(padding, pad_bytes);
+ Buffered_Filter::end_msg();
}
/*
@@ -119,11 +116,9 @@ std::string CBC_Encryption::name() const
*/
CBC_Decryption::CBC_Decryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad) :
- cipher(ciph), padder(pad),
- buf_op(std::tr1::bind(&CBC_Decryption::buffered_block, this, _1, _2),
- std::tr1::bind(&CBC_Decryption::buffered_final, this, _1, _2),
- BOTAN_PARALLEL_BLOCKS_CBC * cipher->BLOCK_SIZE,
- cipher->BLOCK_SIZE)
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_CBC * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE),
+ cipher(ciph), padder(pad)
{
if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
throw Invalid_Block_Size(name(), padder->name());
@@ -139,11 +134,9 @@ CBC_Decryption::CBC_Decryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
const SymmetricKey& key,
const InitializationVector& iv) :
- cipher(ciph), padder(pad),
- buf_op(std::tr1::bind(&CBC_Decryption::buffered_block, this, _1, _2),
- std::tr1::bind(&CBC_Decryption::buffered_final, this, _1, _2),
- BOTAN_PARALLEL_BLOCKS_CBC * cipher->BLOCK_SIZE,
- cipher->BLOCK_SIZE)
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_CBC * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE),
+ cipher(ciph), padder(pad)
{
if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
throw Invalid_Block_Size(name(), padder->name());
@@ -164,7 +157,7 @@ void CBC_Decryption::set_iv(const InitializationVector& iv)
throw Invalid_IV_Length(name(), iv.length());
state = iv.bits_of();
- buf_op.reset();
+ buffer_reset();
}
/*
@@ -223,7 +216,7 @@ void CBC_Decryption::buffered_final(const byte input[], u32bit length)
*/
void CBC_Decryption::write(const byte input[], u32bit length)
{
- buf_op.write(input, length);
+ Buffered_Filter::write(input, length);
}
/*
@@ -231,7 +224,7 @@ void CBC_Decryption::write(const byte input[], u32bit length)
*/
void CBC_Decryption::end_msg()
{
- buf_op.final();
+ Buffered_Filter::end_msg();
}
/*
diff --git a/src/filters/modes/cbc/cbc.h b/src/filters/modes/cbc/cbc.h
index 9faf35605..b303a841f 100644
--- a/src/filters/modes/cbc/cbc.h
+++ b/src/filters/modes/cbc/cbc.h
@@ -11,14 +11,15 @@
#include <botan/block_cipher.h>
#include <botan/key_filt.h>
#include <botan/mode_pad.h>
-#include <botan/buf_op.h>
+#include <botan/buf_filt.h>
namespace Botan {
/*
* CBC Encryption
*/
-class BOTAN_DLL CBC_Encryption : public Keyed_Filter
+class BOTAN_DLL CBC_Encryption : public Keyed_Filter,
+ private Buffered_Filter
{
public:
std::string name() const;
@@ -48,14 +49,14 @@ class BOTAN_DLL CBC_Encryption : public Keyed_Filter
BlockCipher* cipher;
const BlockCipherModePaddingMethod* padder;
- Buffered_Operation buf_op;
SecureVector<byte> state;
};
/*
* CBC Decryption
*/
-class BOTAN_DLL CBC_Decryption : public Keyed_Filter
+class BOTAN_DLL CBC_Decryption : public Keyed_Filter,
+ private Buffered_Filter
{
public:
std::string name() const;
@@ -85,7 +86,6 @@ class BOTAN_DLL CBC_Decryption : public Keyed_Filter
BlockCipher* cipher;
const BlockCipherModePaddingMethod* padder;
- Buffered_Operation buf_op;
SecureVector<byte> state, temp;
};
diff --git a/src/filters/modes/xts/xts.cpp b/src/filters/modes/xts/xts.cpp
index 09614d0b4..0bb46dcc9 100644
--- a/src/filters/modes/xts/xts.cpp
+++ b/src/filters/modes/xts/xts.cpp
@@ -12,8 +12,6 @@
#include <stdio.h>
-using namespace std::tr1::placeholders;
-
namespace Botan {
namespace {
@@ -40,10 +38,9 @@ void poly_double(byte tweak[], u32bit size)
* XTS_Encryption constructor
*/
XTS_Encryption::XTS_Encryption(BlockCipher* ciph) :
- cipher(ciph),
- buf_op(std::tr1::bind(&XTS_Encryption::buffered_block, this, _1, _2),
- std::tr1::bind(&XTS_Encryption::buffered_final, this, _1, _2),
- 2 * cipher->BLOCK_SIZE, cipher->BLOCK_SIZE + 1)
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE + 1),
+ cipher(ciph)
{
if(cipher->BLOCK_SIZE != 8 && cipher->BLOCK_SIZE != 16)
throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
@@ -58,10 +55,9 @@ XTS_Encryption::XTS_Encryption(BlockCipher* ciph) :
XTS_Encryption::XTS_Encryption(BlockCipher* ciph,
const SymmetricKey& key,
const InitializationVector& iv) :
- cipher(ciph),
- buf_op(std::tr1::bind(&XTS_Encryption::buffered_block, this, _1, _2),
- std::tr1::bind(&XTS_Encryption::buffered_final, this, _1, _2),
- 2 * cipher->BLOCK_SIZE, cipher->BLOCK_SIZE + 1)
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE + 1),
+ cipher(ciph)
{
if(cipher->BLOCK_SIZE != 8 && cipher->BLOCK_SIZE != 16)
throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
@@ -120,14 +116,14 @@ void XTS_Encryption::set_key(const SymmetricKey& key)
*/
void XTS_Encryption::write(const byte input[], u32bit length)
{
- buf_op.write(input, length);
+ Buffered_Filter::write(input, length);
}
/*
* Finish encrypting in XTS mode
*/
void XTS_Encryption::end_msg()
{
- buf_op.final();
+ Buffered_Filter::end_msg();
}
void XTS_Encryption::buffered_block(const byte input[], u32bit length)
@@ -200,16 +196,14 @@ void XTS_Encryption::buffered_final(const byte input[], u32bit length)
send(temp, temp.size());
}
- buf_op.reset();
+ buffer_reset();
}
/*
* XTS_Decryption constructor
*/
XTS_Decryption::XTS_Decryption(BlockCipher* ciph) :
- buf_op(std::tr1::bind(&XTS_Decryption::buffered_block, this, _1, _2),
- std::tr1::bind(&XTS_Decryption::buffered_final, this, _1, _2),
- 2 * ciph->BLOCK_SIZE, 1)
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE, 1)
{
cipher = ciph;
cipher2 = ciph->clone();
@@ -222,9 +216,7 @@ XTS_Decryption::XTS_Decryption(BlockCipher* ciph) :
XTS_Decryption::XTS_Decryption(BlockCipher* ciph,
const SymmetricKey& key,
const InitializationVector& iv) :
- buf_op(std::tr1::bind(&XTS_Decryption::buffered_block, this, _1, _2),
- std::tr1::bind(&XTS_Decryption::buffered_final, this, _1, _2),
- 2 * ciph->BLOCK_SIZE, 1)
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE, 1)
{
cipher = ciph;
cipher2 = ciph->clone();
@@ -281,7 +273,7 @@ void XTS_Decryption::set_key(const SymmetricKey& key)
*/
void XTS_Decryption::write(const byte input[], u32bit length)
{
- buf_op.write(input, length);
+ Buffered_Filter::write(input, length);
}
/*
@@ -289,7 +281,7 @@ void XTS_Decryption::write(const byte input[], u32bit length)
*/
void XTS_Decryption::end_msg()
{
- buf_op.final();
+ Buffered_Filter::end_msg();
}
void XTS_Decryption::buffered_block(const byte input[], u32bit input_length)
@@ -360,7 +352,7 @@ void XTS_Decryption::buffered_final(const byte input[], u32bit input_length)
send(temp, input_length);
}
- buf_op.reset();
+ buffer_reset();
}
}
diff --git a/src/filters/modes/xts/xts.h b/src/filters/modes/xts/xts.h
index bf580c44d..724085d9d 100644
--- a/src/filters/modes/xts/xts.h
+++ b/src/filters/modes/xts/xts.h
@@ -10,14 +10,15 @@
#include <botan/block_cipher.h>
#include <botan/key_filt.h>
-#include <botan/buf_op.h>
+#include <botan/buf_filt.h>
namespace Botan {
/*
* XTS Encryption
*/
-class BOTAN_DLL XTS_Encryption : public Keyed_Filter
+class BOTAN_DLL XTS_Encryption : public Keyed_Filter,
+ private Buffered_Filter
{
public:
void set_key(const SymmetricKey& key);
@@ -45,14 +46,13 @@ class BOTAN_DLL XTS_Encryption : public Keyed_Filter
BlockCipher* cipher;
BlockCipher* cipher2;
SecureVector<byte> tweak;
-
- Buffered_Operation buf_op;
};
/*
* XTS Decryption
*/
-class BOTAN_DLL XTS_Decryption : public Keyed_Filter
+class BOTAN_DLL XTS_Decryption : public Keyed_Filter,
+ private Buffered_Filter
{
public:
void set_key(const SymmetricKey& key);
@@ -78,8 +78,6 @@ class BOTAN_DLL XTS_Decryption : public Keyed_Filter
BlockCipher* cipher;
BlockCipher* cipher2;
SecureVector<byte> tweak;
-
- Buffered_Operation buf_op;
};
}