diff options
Diffstat (limited to 'src/modes')
-rw-r--r-- | src/modes/ctr/ctr.cpp | 111 | ||||
-rw-r--r-- | src/modes/ctr/ctr.h | 21 | ||||
-rw-r--r-- | src/modes/eax/eax.h | 2 | ||||
-rw-r--r-- | src/modes/ecb/ecb.cpp | 191 | ||||
-rw-r--r-- | src/modes/ecb/ecb.h | 68 | ||||
-rw-r--r-- | src/modes/modebase.cpp | 2 | ||||
-rw-r--r-- | src/modes/modebase.h | 9 | ||||
-rw-r--r-- | src/modes/xts/xts.h | 8 |
8 files changed, 318 insertions, 94 deletions
diff --git a/src/modes/ctr/ctr.cpp b/src/modes/ctr/ctr.cpp index 9eb42ec5a..d458d7848 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 */ @@ -11,12 +11,21 @@ namespace Botan { +namespace { + +const u32bit PARALLEL_BLOCKS = BOTAN_PARALLEL_BLOCKS_CTR; + +} + /* * 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) { + position = 0; + + counter.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); + enc_buffer.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); } /* @@ -24,39 +33,88 @@ 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) { - set_key(key); + position = 0; + + counter.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); + enc_buffer.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); + + cipher->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) + { + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + if(iv.length() != BLOCK_SIZE) + throw Invalid_IV_Length(name(), iv.length()); + + enc_buffer.clear(); + position = 0; + + counter.copy(0, iv.begin(), iv.length()); + + for(u32bit i = 1; i != PARALLEL_BLOCKS; ++i) + { + counter.copy(i*BLOCK_SIZE, + counter.begin() + (i-1)*BLOCK_SIZE, BLOCK_SIZE); + + for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) + if(++counter[i*BLOCK_SIZE+j]) + break; + } + + cipher->encrypt_n(counter, enc_buffer, PARALLEL_BLOCKS); + } + +/* * 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 +123,23 @@ 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 != PARALLEL_BLOCKS; ++i) + { + byte* this_ctr = counter + i*cipher->BLOCK_SIZE; + + byte last_byte = this_ctr[cipher->BLOCK_SIZE-1]; + last_byte += PARALLEL_BLOCKS; + + if(this_ctr[cipher->BLOCK_SIZE-1] > last_byte) + for(s32bit j = cipher->BLOCK_SIZE - 2; j >= 0; --j) + if(++this_ctr[j]) + break; + + this_ctr[cipher->BLOCK_SIZE-1] = last_byte; + } + + cipher->encrypt_n(counter, enc_buffer, PARALLEL_BLOCKS); + position = 0; } diff --git a/src/modes/ctr/ctr.h b/src/modes/ctr/ctr.h index aa0db5761..1948ffe48 100644 --- a/src/modes/ctr/ctr.h +++ b/src/modes/ctr/ctr.h @@ -8,22 +8,37 @@ #ifndef BOTAN_COUNTER_MODE_H__ #define BOTAN_COUNTER_MODE_H__ -#include <botan/modebase.h> -#include <botan/modebase.h> +#include <botan/key_filt.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&); + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + CTR_BE(BlockCipher*); CTR_BE(BlockCipher*, const SymmetricKey&, const InitializationVector&); + + ~CTR_BE(); private: void write(const byte[], u32bit); void increment_counter(); + + BlockCipher* cipher; + SecureVector<byte> counter, enc_buffer; + u32bit position; }; } diff --git a/src/modes/eax/eax.h b/src/modes/eax/eax.h index 1bb2e510d..f569f2ede 100644 --- a/src/modes/eax/eax.h +++ b/src/modes/eax/eax.h @@ -8,7 +8,7 @@ #ifndef BOTAN_EAX_H__ #define BOTAN_EAX_H__ -#include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/block_cipher.h> #include <botan/mac.h> diff --git a/src/modes/ecb/ecb.cpp b/src/modes/ecb/ecb.cpp index 8da0a4802..988a8b3f2 100644 --- a/src/modes/ecb/ecb.cpp +++ b/src/modes/ecb/ecb.cpp @@ -9,22 +9,60 @@ namespace Botan { +namespace { + +const u32bit PARALLEL_BLOCKS = BOTAN_PARALLEL_BLOCKS_ECB; + +} + /* -* Verify the IV is not set +* ECB_Encryption Constructor */ -bool ECB::valid_iv_size(u32bit iv_size) const +ECB_Encryption::ECB_Encryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad) { - if(iv_size == 0) - return true; - return false; + cipher = ciph; + padder = pad; + + plaintext.create(cipher->BLOCK_SIZE); + ciphertext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + } + +/* +* ECB_Encryption Constructor +*/ +ECB_Encryption::ECB_Encryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad, + const SymmetricKey& key) + { + cipher = ciph; + padder = pad; + + plaintext.create(cipher->BLOCK_SIZE); + ciphertext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + + cipher->set_key(key); + } + +/* +* ECB_Encryption Destructor +*/ +ECB_Encryption::~ECB_Encryption() + { + delete cipher; + delete padder; } /* * Return an ECB mode name */ -std::string ECB::name() const +std::string ECB_Encryption::name() const { - return (cipher->name() + "/" + mode_name + "/" + padder->name()); + return (cipher->name() + "/ECB/" + padder->name()); } /* @@ -32,23 +70,34 @@ std::string ECB::name() const */ void ECB_Encryption::write(const byte input[], u32bit length) { - buffer.copy(position, input, length); - if(position + length >= BLOCK_SIZE) + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + if(position) { - cipher->encrypt(buffer); - send(buffer, BLOCK_SIZE); - input += (BLOCK_SIZE - position); - length -= (BLOCK_SIZE - position); - while(length >= BLOCK_SIZE) + plaintext.copy(position, input, length); + + if(position + length >= BLOCK_SIZE) { - cipher->encrypt(input, buffer); - send(buffer, BLOCK_SIZE); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; + cipher->encrypt(plaintext, ciphertext); + send(ciphertext, BLOCK_SIZE); + input += (BLOCK_SIZE - position); + length -= (BLOCK_SIZE - position); + position = 0; } - buffer.copy(input, length); - 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; } @@ -57,6 +106,8 @@ void ECB_Encryption::write(const byte input[], u32bit length) */ void ECB_Encryption::end_msg() { + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + SecureVector<byte> padding(BLOCK_SIZE); padder->pad(padding, padding.size(), position); write(padding, padder->pad_bytes(BLOCK_SIZE, position)); @@ -65,27 +116,93 @@ void ECB_Encryption::end_msg() } /* +* ECB_Decryption Constructor +*/ +ECB_Decryption::ECB_Decryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad) + { + cipher = ciph; + padder = pad; + + ciphertext.create(cipher->BLOCK_SIZE); + plaintext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + } + +/* +* ECB_Decryption Constructor +*/ +ECB_Decryption::ECB_Decryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad, + const SymmetricKey& key) + { + cipher = ciph; + padder = pad; + + ciphertext.create(cipher->BLOCK_SIZE); + plaintext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + + 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[], u32bit length) { - buffer.copy(position, input, length); - if(position + length > BLOCK_SIZE) + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + if(position) { - cipher->decrypt(buffer); - send(buffer, BLOCK_SIZE); - input += (BLOCK_SIZE - position); - length -= (BLOCK_SIZE - position); - while(length > BLOCK_SIZE) + ciphertext.copy(position, input, length); + + if(position + length > BLOCK_SIZE) { - cipher->decrypt(input, buffer); - send(buffer, BLOCK_SIZE); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; + cipher->decrypt(ciphertext, plaintext); + send(plaintext, BLOCK_SIZE); + input += (BLOCK_SIZE - position); + length -= (BLOCK_SIZE - position); + position = 0; } - buffer.copy(input, length); - position = 0; } + + while(length > BLOCK_SIZE) + { + /* 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; + } + + ciphertext.copy(position, input, length); position += length; } @@ -94,11 +211,11 @@ void ECB_Decryption::write(const byte input[], u32bit length) */ void ECB_Decryption::end_msg() { - if(position != BLOCK_SIZE) + if(position != cipher->BLOCK_SIZE) throw Decoding_Error(name()); - cipher->decrypt(buffer); - send(buffer, padder->unpad(buffer, BLOCK_SIZE)); - state = buffer; + + cipher->decrypt(ciphertext); + send(ciphertext, padder->unpad(ciphertext, cipher->BLOCK_SIZE)); position = 0; } diff --git a/src/modes/ecb/ecb.h b/src/modes/ecb/ecb.h index 5230f9b14..ff9ea9635 100644 --- a/src/modes/ecb/ecb.h +++ b/src/modes/ecb/ecb.h @@ -1,6 +1,6 @@ /* * ECB Mode -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,64 +8,74 @@ #ifndef BOTAN_ECB_H__ #define BOTAN_ECB_H__ -#include <botan/modebase.h> -#include <botan/mode_pad.h> +#include <botan/basefilt.h> #include <botan/block_cipher.h> +#include <botan/mode_pad.h> -namespace Botan { - -/* -* ECB -*/ -class BOTAN_DLL ECB : public BlockCipherMode - { - protected: - ECB(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) : - BlockCipherMode(ciph, "ECB", 0), padder(pad) {} - ~ECB() { delete padder; } +#include <botan/modebase.h> - std::string name() const; - BlockCipherModePaddingMethod* padder; - private: - bool valid_iv_size(u32bit) const; - }; +namespace Botan { /* * ECB Encryption */ -class BOTAN_DLL ECB_Encryption : public ECB +class BOTAN_DLL ECB_Encryption : public Keyed_Filter { public: + std::string name() const; + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + ECB_Encryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) : - ECB(ciph, pad) {} + BlockCipherModePaddingMethod* pad); ECB_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) : - ECB(ciph, pad) { set_key(key); } + const SymmetricKey& key); + + ~ECB_Encryption(); private: void write(const byte[], u32bit); void end_msg(); + + BlockCipher* cipher; + BlockCipherModePaddingMethod* padder; + SecureVector<byte> plaintext, ciphertext; + u32bit position; }; /* * ECB Decryption */ -class BOTAN_DLL ECB_Decryption : public ECB +class BOTAN_DLL ECB_Decryption : public Keyed_Filter { public: + std::string name() const; + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + ECB_Decryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) : - ECB(ciph, pad) {} + BlockCipherModePaddingMethod* pad); ECB_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) : - ECB(ciph, pad) { set_key(key); } + const SymmetricKey& key); + + ~ECB_Decryption(); private: void write(const byte[], u32bit); void end_msg(); + + BlockCipher* cipher; + BlockCipherModePaddingMethod* padder; + SecureVector<byte> plaintext, ciphertext; + u32bit position; }; } diff --git a/src/modes/modebase.cpp b/src/modes/modebase.cpp index 8293acc54..b048862a4 100644 --- a/src/modes/modebase.cpp +++ b/src/modes/modebase.cpp @@ -19,7 +19,7 @@ BlockCipherMode::BlockCipherMode(BlockCipher* cipher_ptr, BLOCK_SIZE(cipher_ptr->BLOCK_SIZE), BUFFER_SIZE(buf_mult * BLOCK_SIZE), IV_METHOD(iv_meth), mode_name(cipher_mode_name) { - base_ptr = cipher = cipher_ptr; + cipher = cipher_ptr; buffer.create(BUFFER_SIZE); state.create(iv_size); position = 0; diff --git a/src/modes/modebase.h b/src/modes/modebase.h index 173fde58c..4a15524b6 100644 --- a/src/modes/modebase.h +++ b/src/modes/modebase.h @@ -8,7 +8,7 @@ #ifndef BOTAN_MODEBASE_H__ #define BOTAN_MODEBASE_H__ -#include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/block_cipher.h> namespace Botan { @@ -21,12 +21,17 @@ class BOTAN_DLL BlockCipherMode : public Keyed_Filter public: std::string name() const; + void set_iv(const InitializationVector&); + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + BlockCipherMode(BlockCipher*, const std::string&, u32bit, u32bit = 0, u32bit = 1); virtual ~BlockCipherMode() { delete cipher; } protected: - void set_iv(const InitializationVector&); const u32bit BLOCK_SIZE, BUFFER_SIZE, IV_METHOD; const std::string mode_name; BlockCipher* cipher; diff --git a/src/modes/xts/xts.h b/src/modes/xts/xts.h index 01558175b..9badd3666 100644 --- a/src/modes/xts/xts.h +++ b/src/modes/xts/xts.h @@ -8,7 +8,7 @@ #ifndef BOTAN_XTS_H__ #define BOTAN_XTS_H__ -#include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/block_cipher.h> namespace Botan { @@ -22,6 +22,9 @@ class BOTAN_DLL XTS_Encryption : public Keyed_Filter void set_key(const SymmetricKey& key); void set_iv(const InitializationVector& iv); + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + std::string name() const; XTS_Encryption(BlockCipher* ciph); @@ -52,6 +55,9 @@ class BOTAN_DLL XTS_Decryption : public Keyed_Filter void set_key(const SymmetricKey& key); void set_iv(const InitializationVector& iv); + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + std::string name() const; XTS_Decryption(BlockCipher* ciph); |