aboutsummaryrefslogtreecommitdiffstats
path: root/src/modes
diff options
context:
space:
mode:
Diffstat (limited to 'src/modes')
-rw-r--r--src/modes/ctr/ctr.cpp111
-rw-r--r--src/modes/ctr/ctr.h21
-rw-r--r--src/modes/eax/eax.h2
-rw-r--r--src/modes/ecb/ecb.cpp191
-rw-r--r--src/modes/ecb/ecb.h68
-rw-r--r--src/modes/modebase.cpp2
-rw-r--r--src/modes/modebase.h9
-rw-r--r--src/modes/xts/xts.h8
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);