diff options
author | lloyd <[email protected]> | 2013-08-15 16:34:53 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2013-08-15 16:34:53 +0000 |
commit | 16955224c8f1c5c035fccb8ce037513d086e3f1a (patch) | |
tree | ca1fc5d342449e415ef9f19176e617fa18d74f5c | |
parent | 523d4cb4a11039ff2ab4e6772e4ef67c75023278 (diff) |
Move ECB to Transformation API
-rw-r--r-- | checks/bench.cpp | 5 | ||||
-rw-r--r-- | src/engine/core_engine/core_modes.cpp | 18 | ||||
-rw-r--r-- | src/filters/modes/ecb/ecb.cpp | 210 | ||||
-rw-r--r-- | src/filters/modes/ecb/ecb.h | 86 | ||||
-rw-r--r-- | src/filters/transform_filter.cpp | 3 | ||||
-rw-r--r-- | src/filters/transform_filter.h | 5 | ||||
-rw-r--r-- | src/modes/cbc/cbc.cpp | 2 | ||||
-rw-r--r-- | src/modes/cbc/cbc.h | 2 | ||||
-rw-r--r-- | src/modes/cbc/info.txt | 4 | ||||
-rw-r--r-- | src/modes/ecb/ecb.cpp | 163 | ||||
-rw-r--r-- | src/modes/ecb/ecb.h | 89 | ||||
-rw-r--r-- | src/modes/ecb/info.txt (renamed from src/filters/modes/ecb/info.txt) | 3 |
12 files changed, 278 insertions, 312 deletions
diff --git a/checks/bench.cpp b/checks/bench.cpp index 3deff5136..b5e8e82f8 100644 --- a/checks/bench.cpp +++ b/checks/bench.cpp @@ -176,11 +176,14 @@ bool bench_algo(const std::string& algo, size_t cipher_keylen = proto_cipher->maximum_keylength(); size_t cipher_ivlen = proto_cipher->block_size(); - // hacks! + // hacks! (cipher_ivlen = transform->default_nonce_size()) + if(algo_parts[1] == "XTS") cipher_keylen *= 2; if(algo_parts[1] == "OCB") cipher_ivlen -= 1; + if(algo_parts[1] == "ECB") + cipher_ivlen = 0; std::vector<byte> buf(16 * 1024); rng.randomize(&buf[0], buf.size()); diff --git a/src/engine/core_engine/core_modes.cpp b/src/engine/core_engine/core_modes.cpp index a7f004df7..c2c34234f 100644 --- a/src/engine/core_engine/core_modes.cpp +++ b/src/engine/core_engine/core_modes.cpp @@ -12,10 +12,6 @@ #include <botan/mode_pad.h> #include <memory> -#if defined(BOTAN_HAS_ECB) - #include <botan/ecb.h> -#endif - #if defined(BOTAN_HAS_CTS) #include <botan/cts.h> #endif @@ -24,6 +20,10 @@ #include <botan/cfb.h> #endif +#if defined(BOTAN_HAS_MODE_ECB) + #include <botan/ecb.h> +#endif + #if defined(BOTAN_HAS_MODE_CBC) #include <botan/cbc.h> #endif @@ -103,15 +103,15 @@ Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, return new StreamCipher_Filter(new CTR_BE(block_cipher->clone())); #endif -#if defined(BOTAN_HAS_ECB) +#if defined(BOTAN_HAS_MODE_ECB) if(mode == "ECB" || mode == "") { if(direction == ENCRYPTION) - return new ECB_Encryption(block_cipher->clone(), - get_bc_pad(padding, "NoPadding")); + return new Transformation_Filter( + new ECB_Encryption(block_cipher->clone(), get_bc_pad(padding, "NoPadding"))); else - return new ECB_Decryption(block_cipher->clone(), - get_bc_pad(padding, "NoPadding")); + return new Transformation_Filter( + new ECB_Decryption(block_cipher->clone(), get_bc_pad(padding, "NoPadding"))); } #endif diff --git a/src/filters/modes/ecb/ecb.cpp b/src/filters/modes/ecb/ecb.cpp deleted file mode 100644 index d36d2350b..000000000 --- a/src/filters/modes/ecb/ecb.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* -* ECB Mode -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/ecb.h> - -namespace Botan { - -/* -* ECB_Encryption Constructor -*/ -ECB_Encryption::ECB_Encryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) : - Buffered_Filter(ciph->parallel_bytes(), 0) - { - cipher = ciph; - padder = pad; - - temp.resize(buffered_block_size()); - } - -/* -* ECB_Encryption Constructor -*/ -ECB_Encryption::ECB_Encryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) : - Buffered_Filter(ciph->parallel_bytes(), 0) - { - cipher = ciph; - padder = pad; - - temp.resize(buffered_block_size()); - - cipher->set_key(key); - } - -/* -* ECB_Encryption Destructor -*/ -ECB_Encryption::~ECB_Encryption() - { - delete cipher; - delete padder; - } - -/* -* Return an ECB mode name -*/ -std::string ECB_Encryption::name() const - { - return (cipher->name() + "/ECB/" + padder->name()); - } - -/* -* Encrypt in ECB mode -*/ -void ECB_Encryption::write(const byte input[], size_t length) - { - Buffered_Filter::write(input, length); - } - -/* -* Finish encrypting in ECB mode -*/ -void ECB_Encryption::end_msg() - { - size_t last_block = current_position() % cipher->block_size(); - - secure_vector<byte> padding(cipher->block_size()); - padder->pad(&padding[0], padding.size(), last_block); - - size_t pad_bytes = padder->pad_bytes(cipher->block_size(), last_block); - - if(pad_bytes) - Buffered_Filter::write(padding, pad_bytes); - Buffered_Filter::end_msg(); - } - -void ECB_Encryption::buffered_block(const byte input[], size_t input_length) - { - const size_t blocks_in_temp = temp.size() / cipher->block_size(); - size_t blocks = input_length / cipher->block_size(); - - while(blocks) - { - size_t to_proc = std::min(blocks, blocks_in_temp); - - cipher->encrypt_n(input, &temp[0], to_proc); - - send(temp, to_proc * cipher->block_size()); - - input += to_proc * cipher->block_size(); - blocks -= to_proc; - } - } - -void ECB_Encryption::buffered_final(const byte input[], size_t input_length) - { - if(input_length % cipher->block_size() == 0) - buffered_block(input, input_length); - else if(input_length != 0) - throw Encoding_Error(name() + ": Did not pad to full blocksize"); - } - -/* -* ECB_Decryption Constructor -*/ -ECB_Decryption::ECB_Decryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) : - Buffered_Filter(ciph->parallel_bytes(), 1) - { - cipher = ciph; - padder = pad; - - temp.resize(buffered_block_size()); - } - -/* -* ECB_Decryption Constructor -*/ -ECB_Decryption::ECB_Decryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) : - Buffered_Filter(ciph->parallel_bytes(), 1) - { - cipher = ciph; - padder = pad; - - temp.resize(buffered_block_size()); - - cipher->set_key(key); - } - -/* -* ECB_Decryption Destructor -*/ -ECB_Decryption::~ECB_Decryption() - { - delete cipher; - delete padder; - } - -/* -* Return an ECB mode name -*/ -std::string ECB_Decryption::name() const - { - return (cipher->name() + "/ECB/" + padder->name()); - } - -/* -* Decrypt in ECB mode -*/ -void ECB_Decryption::write(const byte input[], size_t length) - { - Buffered_Filter::write(input, length); - } - -/* -* Finish decrypting in ECB mode -*/ -void ECB_Decryption::end_msg() - { - Buffered_Filter::end_msg(); - } - -/* -* Decrypt in ECB mode -*/ -void ECB_Decryption::buffered_block(const byte input[], size_t length) - { - const size_t blocks_in_temp = temp.size() / cipher->block_size(); - size_t blocks = length / cipher->block_size(); - - while(blocks) - { - size_t to_proc = std::min(blocks, blocks_in_temp); - - cipher->decrypt_n(input, &temp[0], to_proc); - - send(temp, to_proc * cipher->block_size()); - - input += to_proc * cipher->block_size(); - blocks -= to_proc; - } - } - -/* -* Finish encrypting in ECB mode -*/ -void ECB_Decryption::buffered_final(const byte input[], size_t length) - { - if(length == 0 || length % cipher->block_size() != 0) - throw Decoding_Error(name() + ": Ciphertext not multiple of block size"); - - size_t extra_blocks = (length - 1) / cipher->block_size(); - - buffered_block(input, extra_blocks * cipher->block_size()); - - input += extra_blocks * cipher->block_size(); - - cipher->decrypt(input, &temp[0]); - send(&temp[0], padder->unpad(&temp[0], cipher->block_size())); - } - -} diff --git a/src/filters/modes/ecb/ecb.h b/src/filters/modes/ecb/ecb.h deleted file mode 100644 index 8f4e6f1b5..000000000 --- a/src/filters/modes/ecb/ecb.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -* ECB Mode -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_ECB_H__ -#define BOTAN_ECB_H__ - -#include <botan/block_cipher.h> -#include <botan/mode_pad.h> -#include <botan/key_filt.h> -#include <botan/buf_filt.h> - -namespace Botan { - -/** -* ECB Encryption -*/ -class BOTAN_DLL ECB_Encryption : public Keyed_Filter, - private Buffered_Filter - { - public: - std::string name() const; - - void set_key(const SymmetricKey& key) { cipher->set_key(key); } - - Key_Length_Specification key_spec() const override { return cipher->key_spec(); } - - ECB_Encryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad); - - ECB_Encryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad, - const SymmetricKey& key); - - ~ECB_Encryption(); - private: - void buffered_block(const byte input[], size_t input_length); - void buffered_final(const byte input[], size_t input_length); - - void write(const byte input[], size_t input_length); - void end_msg(); - - BlockCipher* cipher; - BlockCipherModePaddingMethod* padder; - secure_vector<byte> temp; - }; - -/** -* ECB Decryption -*/ -class BOTAN_DLL ECB_Decryption : public Keyed_Filter, - public Buffered_Filter - { - public: - std::string name() const; - - void set_key(const SymmetricKey& key) { cipher->set_key(key); } - - Key_Length_Specification key_spec() const override { return cipher->key_spec(); } - - ECB_Decryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad); - - ECB_Decryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad, - const SymmetricKey& key); - - ~ECB_Decryption(); - private: - void buffered_block(const byte input[], size_t input_length); - void buffered_final(const byte input[], size_t input_length); - - void write(const byte input[], size_t input_length); - void end_msg(); - - BlockCipher* cipher; - BlockCipherModePaddingMethod* padder; - secure_vector<byte> temp; - }; - -} - -#endif diff --git a/src/filters/transform_filter.cpp b/src/filters/transform_filter.cpp index e12328af8..c6a52a257 100644 --- a/src/filters/transform_filter.cpp +++ b/src/filters/transform_filter.cpp @@ -6,12 +6,15 @@ */ #include <botan/transform_filter.h> +#include <iostream> +#include <botan/hex.h> namespace Botan { Transformation_Filter::Transformation_Filter(Transformation* transform) : Buffered_Filter(transform->update_granularity(), transform->minimum_final_size()), + m_nonce(transform->default_nonce_size() == 0), m_transform(transform) { } diff --git a/src/filters/transform_filter.h b/src/filters/transform_filter.h index 5ad66ba96..7cbc2eccb 100644 --- a/src/filters/transform_filter.h +++ b/src/filters/transform_filter.h @@ -50,16 +50,17 @@ class BOTAN_DLL Transformation_Filter : public Keyed_Filter, class Nonce_State { public: + Nonce_State(bool allow_null_nonce) : m_fresh_nonce(allow_null_nonce) {} + void update(const InitializationVector& iv); std::vector<byte> get(); private: - bool m_fresh_nonce = false; + bool m_fresh_nonce; std::vector<byte> m_nonce; }; Nonce_State m_nonce; std::unique_ptr<Transformation> m_transform; - }; } diff --git a/src/modes/cbc/cbc.cpp b/src/modes/cbc/cbc.cpp index 832f3af4d..65b78fbc5 100644 --- a/src/modes/cbc/cbc.cpp +++ b/src/modes/cbc/cbc.cpp @@ -31,7 +31,7 @@ void CBC_Mode::clear() std::string CBC_Mode::name() const { - return cipher().name() + "/CBC"; + return cipher().name() + "/CBC/" + padding().name(); } size_t CBC_Mode::update_granularity() const diff --git a/src/modes/cbc/cbc.h b/src/modes/cbc/cbc.h index d8b3d818d..8e3a72fd0 100644 --- a/src/modes/cbc/cbc.h +++ b/src/modes/cbc/cbc.h @@ -16,7 +16,7 @@ namespace Botan { /** -* CBC Mode. Only handles full blocks, padding is handled higher up +* CBC Mode */ class CBC_Mode : public Transformation { diff --git a/src/modes/cbc/info.txt b/src/modes/cbc/info.txt index 767d907b3..9bf948f02 100644 --- a/src/modes/cbc/info.txt +++ b/src/modes/cbc/info.txt @@ -1 +1,5 @@ define MODE_CBC + +<requires> +mode_pad +</requires> diff --git a/src/modes/ecb/ecb.cpp b/src/modes/ecb/ecb.cpp new file mode 100644 index 000000000..8abf76433 --- /dev/null +++ b/src/modes/ecb/ecb.cpp @@ -0,0 +1,163 @@ +/* +* ECB Mode +* (C) 1999-2009,2013 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/ecb.h> +#include <botan/loadstor.h> +#include <botan/internal/xor_buf.h> +#include <botan/internal/rounding.h> + +namespace Botan { + +ECB_Mode::ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : + m_cipher(cipher), + m_padding(padding) + { + if(!m_padding->valid_blocksize(cipher->block_size())) + throw std::invalid_argument("Padding " + m_padding->name() + + " cannot be used with " + + cipher->name() + "/ECB"); + } + +void ECB_Mode::clear() + { + m_cipher->clear(); + } + +std::string ECB_Mode::name() const + { + return cipher().name() + "/ECB/" + padding().name(); + } + +size_t ECB_Mode::update_granularity() const + { + return cipher().parallel_bytes(); + } + +Key_Length_Specification ECB_Mode::key_spec() const + { + return cipher().key_spec(); + } + +size_t ECB_Mode::default_nonce_size() const + { + return 0; + } + +bool ECB_Mode::valid_nonce_length(size_t n) const + { + return (n == 0); + } + +void ECB_Mode::key_schedule(const byte key[], size_t length) + { + m_cipher->set_key(key, length); + } + +secure_vector<byte> ECB_Mode::start(const byte nonce[], size_t nonce_len) + { + if(!valid_nonce_length(nonce_len)) + throw Invalid_IV_Length(name(), nonce_len); + + return secure_vector<byte>(); + } + +size_t ECB_Encryption::minimum_final_size() const + { + return 0; + } + +size_t ECB_Encryption::output_length(size_t input_length) const + { + return round_up(input_length, cipher().block_size()); + } + +void ECB_Encryption::update(secure_vector<byte>& buffer, size_t offset) + { + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + const size_t BS = cipher().block_size(); + + BOTAN_ASSERT(sz % BS == 0, "ECB input is full blocks"); + const size_t blocks = sz / BS; + + cipher().encrypt_n(&buf[0], &buf[0], blocks); + } + +void ECB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) + { + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + //byte* buf = &buffer[offset]; + + const size_t BS = cipher().block_size(); + + const size_t bytes_in_final_block = sz % BS; + + const size_t pad_bytes = padding().pad_bytes(BS, bytes_in_final_block); + + if((pad_bytes + bytes_in_final_block) % BS) + throw std::runtime_error("Did not pad to full block size in " + name()); + +#if 0 + const size_t pad_offset = buffer.size(); + //buffer.resize(checked_add(buffer.size() + pad_bytes)); + buffer.resize(buffer.size() + pad_bytes); + + padder().pad(&buffer[pad_offset], BS, bytes_in_final_block); +#else + std::vector<byte> pad(BS); + padding().pad(&pad[0], BS, bytes_in_final_block); + + buffer.insert(buffer.end(), pad.begin(), pad.begin() + pad_bytes); +#endif + + update(buffer, offset); + } + +size_t ECB_Decryption::output_length(size_t input_length) const + { + return input_length; + } + +size_t ECB_Decryption::minimum_final_size() const + { + return cipher().block_size(); + } + +void ECB_Decryption::update(secure_vector<byte>& buffer, size_t offset) + { + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + const size_t BS = cipher().block_size(); + + BOTAN_ASSERT(sz % BS == 0, "Input is full blocks"); + size_t blocks = sz / BS; + + cipher().decrypt_n(&buf[0], &buf[0], blocks); + } + +void ECB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) + { + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + + const size_t BS = cipher().block_size(); + + if(sz == 0 || sz % BS) + throw Decoding_Error(name() + ": Ciphertext not a multiple of block size"); + + update(buffer, offset); + + const size_t pad_bytes = BS - padding().unpad(&buffer[buffer.size()-BS], BS); + buffer.resize(buffer.size() - pad_bytes); // remove padding + } + +} diff --git a/src/modes/ecb/ecb.h b/src/modes/ecb/ecb.h new file mode 100644 index 000000000..459ac939a --- /dev/null +++ b/src/modes/ecb/ecb.h @@ -0,0 +1,89 @@ +/* +* ECB Mode +* (C) 1999-2009,2013 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_MODE_ECB_H__ +#define BOTAN_MODE_ECB_H__ + +#include <botan/transform.h> +#include <botan/block_cipher.h> +#include <botan/mode_pad.h> +#include <memory> + +namespace Botan { + +/** +* ECB Mode. Only handles full blocks, padding is handled higher up +*/ +class ECB_Mode : public Transformation + { + public: + secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; + + std::string name() const override; + + size_t update_granularity() const override; + + Key_Length_Specification key_spec() const override; + + size_t default_nonce_size() const override; + + bool valid_nonce_length(size_t n) const override; + + void clear(); + protected: + ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding); + + const BlockCipher& cipher() const { return *m_cipher; } + + const BlockCipherModePaddingMethod& padding() const { return *m_padding; } + + private: + void key_schedule(const byte key[], size_t length) override; + + std::unique_ptr<BlockCipher> m_cipher; + std::unique_ptr<BlockCipherModePaddingMethod> m_padding; + }; + +/** +* ECB Encryption +*/ +class BOTAN_DLL ECB_Encryption : public ECB_Mode + { + public: + ECB_Encryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : + ECB_Mode(cipher, padding) {} + + void update(secure_vector<byte>& blocks, size_t offset) override; + + void finish(secure_vector<byte>& final_block, size_t offset) override; + + size_t output_length(size_t input_length) const override; + + size_t minimum_final_size() const override; + }; + +/** +* ECB Decryption +*/ +class BOTAN_DLL ECB_Decryption : public ECB_Mode + { + public: + ECB_Decryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : + ECB_Mode(cipher, padding) {} + + void update(secure_vector<byte>& blocks, size_t offset) override; + + void finish(secure_vector<byte>& final_block, size_t offset) override; + + size_t output_length(size_t input_length) const override; + + size_t minimum_final_size() const override; + }; + +} + +#endif diff --git a/src/filters/modes/ecb/info.txt b/src/modes/ecb/info.txt index 38a56040c..03a5130b2 100644 --- a/src/filters/modes/ecb/info.txt +++ b/src/modes/ecb/info.txt @@ -1,6 +1,5 @@ -define ECB +define MODE_ECB <requires> -block mode_pad </requires> |