diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/filters/modes/ecb/ecb.cpp | 180 | ||||
-rw-r--r-- | src/filters/modes/ecb/ecb.h | 23 |
2 files changed, 102 insertions, 101 deletions
diff --git a/src/filters/modes/ecb/ecb.cpp b/src/filters/modes/ecb/ecb.cpp index 3c11669ef..c13d0fd37 100644 --- a/src/filters/modes/ecb/ecb.cpp +++ b/src/filters/modes/ecb/ecb.cpp @@ -1,6 +1,6 @@ /* * ECB Mode -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -13,15 +13,13 @@ namespace Botan { * ECB_Encryption Constructor */ ECB_Encryption::ECB_Encryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) + BlockCipherModePaddingMethod* pad) : + Buffered_Filter(ciph->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB, 0) { cipher = ciph; padder = pad; - plaintext.resize(cipher->BLOCK_SIZE); - ciphertext.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB); - - position = 0; + temp.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB); } /* @@ -29,15 +27,13 @@ ECB_Encryption::ECB_Encryption(BlockCipher* ciph, */ ECB_Encryption::ECB_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) + const SymmetricKey& key) : + Buffered_Filter(ciph->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB, 0) { cipher = ciph; padder = pad; - plaintext.resize(cipher->BLOCK_SIZE); - ciphertext.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB); - - position = 0; + temp.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB); cipher->set_key(key); } @@ -64,35 +60,7 @@ std::string ECB_Encryption::name() const */ void ECB_Encryption::write(const byte input[], u32bit length) { - const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; - - if(position) - { - plaintext.copy(position, input, length); - - if(position + length >= BLOCK_SIZE) - { - cipher->encrypt(plaintext, ciphertext); - send(ciphertext, BLOCK_SIZE); - input += (BLOCK_SIZE - position); - length -= (BLOCK_SIZE - position); - position = 0; - } - } - - while(length >= BLOCK_SIZE) - { - const u32bit to_proc = - std::min<u32bit>(length, ciphertext.size()) / BLOCK_SIZE; - - cipher->encrypt_n(input, ciphertext, to_proc); - send(ciphertext, to_proc * BLOCK_SIZE); - input += to_proc * BLOCK_SIZE; - length -= to_proc * BLOCK_SIZE; - } - - plaintext.copy(position, input, length); - position += length; + Buffered_Filter::write(input, length); } /* @@ -100,28 +68,55 @@ void ECB_Encryption::write(const byte input[], u32bit length) */ void ECB_Encryption::end_msg() { - const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + u32bit last_block = current_position() % cipher->BLOCK_SIZE; - SecureVector<byte> padding(BLOCK_SIZE); - padder->pad(padding, padding.size(), position); - write(padding, padder->pad_bytes(BLOCK_SIZE, position)); - if(position != 0) - throw Encoding_Error(name() + ": Did not pad to full blocksize"); + SecureVector<byte> padding(cipher->BLOCK_SIZE); + padder->pad(padding, padding.size(), last_block); + + u32bit 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[], u32bit input_length) + { + const u32bit blocks_in_temp = temp.size() / cipher->BLOCK_SIZE; + u32bit blocks = input_length / cipher->BLOCK_SIZE; + + while(blocks) + { + u32bit to_proc = std::min<u32bit>(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[], u32bit input_length) + { + if(input_length % cipher->BLOCK_SIZE == 0) + buffered_block(input, input_length); + else if(input_length != 0) + throw Exception(name() + ": Did not pad to full blocksize"); } /* * ECB_Decryption Constructor */ ECB_Decryption::ECB_Decryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) + BlockCipherModePaddingMethod* pad) : + Buffered_Filter(ciph->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB, 1) { cipher = ciph; padder = pad; - ciphertext.resize(cipher->BLOCK_SIZE); - plaintext.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB); - - position = 0; + temp.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB); } /* @@ -129,15 +124,13 @@ ECB_Decryption::ECB_Decryption(BlockCipher* ciph, */ ECB_Decryption::ECB_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) + const SymmetricKey& key) : + Buffered_Filter(ciph->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB, 1) { cipher = ciph; padder = pad; - ciphertext.resize(cipher->BLOCK_SIZE); - plaintext.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB); - - position = 0; + temp.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB); cipher->set_key(key); } @@ -164,53 +157,54 @@ std::string ECB_Decryption::name() const */ void ECB_Decryption::write(const byte input[], u32bit length) { - const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + Buffered_Filter::write(input, length); + } - if(position) - { - ciphertext.copy(position, input, length); - - if(position + length > BLOCK_SIZE) - { - cipher->decrypt(ciphertext, plaintext); - send(plaintext, BLOCK_SIZE); - input += (BLOCK_SIZE - position); - length -= (BLOCK_SIZE - position); - position = 0; - } - } +/* +* Finish decrypting in ECB mode +*/ +void ECB_Decryption::end_msg() + { + Buffered_Filter::end_msg(); + } - while(length > BLOCK_SIZE) +/* +* Decrypt in ECB mode +*/ +void ECB_Decryption::buffered_block(const byte input[], u32bit length) + { + const u32bit blocks_in_temp = temp.size() / cipher->BLOCK_SIZE; + u32bit blocks = length / cipher->BLOCK_SIZE; + + while(blocks) { - /* Always leave at least 1 byte left over, to ensure that (as long - as the input message actually is a multiple of the block size) - we will have the full final block left over in end_msg so as - to remove the padding - */ - const u32bit to_proc = - std::min<u32bit>(length - 1, plaintext.size()) / BLOCK_SIZE; - - cipher->decrypt_n(input, plaintext, to_proc); - send(plaintext, to_proc * BLOCK_SIZE); - input += to_proc * BLOCK_SIZE; - length -= to_proc * BLOCK_SIZE; - } + u32bit to_proc = std::min<u32bit>(blocks, blocks_in_temp); - ciphertext.copy(position, input, length); - position += length; + 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 decrypting in ECB mode +* Finish encrypting in ECB mode */ -void ECB_Decryption::end_msg() +void ECB_Decryption::buffered_final(const byte input[], u32bit length) { - if(position != cipher->BLOCK_SIZE) - throw Decoding_Error(name()); + 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(ciphertext); - send(ciphertext, padder->unpad(ciphertext, cipher->BLOCK_SIZE)); - position = 0; + cipher->decrypt(input, temp); + send(temp, padder->unpad(temp, cipher->BLOCK_SIZE)); } } diff --git a/src/filters/modes/ecb/ecb.h b/src/filters/modes/ecb/ecb.h index 2b3b3fe83..2b88191c7 100644 --- a/src/filters/modes/ecb/ecb.h +++ b/src/filters/modes/ecb/ecb.h @@ -11,13 +11,15 @@ #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 +class BOTAN_DLL ECB_Encryption : public Keyed_Filter, + private Buffered_Filter { public: std::string name() const; @@ -36,19 +38,22 @@ class BOTAN_DLL ECB_Encryption : public Keyed_Filter ~ECB_Encryption(); private: - void write(const byte[], u32bit); + void buffered_block(const byte input[], u32bit input_length); + void buffered_final(const byte input[], u32bit input_length); + + void write(const byte input[], u32bit input_length); void end_msg(); BlockCipher* cipher; BlockCipherModePaddingMethod* padder; - SecureVector<byte> plaintext, ciphertext; - u32bit position; + SecureVector<byte> temp; }; /* * ECB Decryption */ -class BOTAN_DLL ECB_Decryption : public Keyed_Filter +class BOTAN_DLL ECB_Decryption : public Keyed_Filter, + public Buffered_Filter { public: std::string name() const; @@ -67,13 +72,15 @@ class BOTAN_DLL ECB_Decryption : public Keyed_Filter ~ECB_Decryption(); private: - void write(const byte[], u32bit); + void buffered_block(const byte input[], u32bit input_length); + void buffered_final(const byte input[], u32bit input_length); + + void write(const byte input[], u32bit input_length); void end_msg(); BlockCipher* cipher; BlockCipherModePaddingMethod* padder; - SecureVector<byte> plaintext, ciphertext; - u32bit position; + SecureVector<byte> temp; }; } |