diff options
author | lloyd <[email protected]> | 2009-12-27 05:50:44 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-12-27 05:50:44 +0000 |
commit | f0275263ab0dfcd11a4e193c50b248d291e2d499 (patch) | |
tree | 015f5f456ac5713454a693064f3a48d0cab51cef /src | |
parent | f4072f413e8121e633d6882d439b2b249a535230 (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.cpp | 132 | ||||
-rw-r--r-- | src/filters/buf_filt.h | 38 | ||||
-rw-r--r-- | src/filters/modes/cbc/cbc.cpp | 47 | ||||
-rw-r--r-- | src/filters/modes/cbc/cbc.h | 10 | ||||
-rw-r--r-- | src/filters/modes/xts/xts.cpp | 36 | ||||
-rw-r--r-- | src/filters/modes/xts/xts.h | 12 |
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; }; } |