aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-12-23 20:25:01 +0000
committerlloyd <[email protected]>2009-12-23 20:25:01 +0000
commit882dd7d7f723e05ecf2c3b2d40d9ac0538b743a5 (patch)
tree0b373528d0c2f04ee680c5d2243d890135d8963a
parent4043de7bbe0785556201925c047a28e1fa3e30f1 (diff)
Define EAX in terms of CTR mode instead of implementing it within EAX_Base.
This is somewhat faster, especially with SIMD-ed ciphers. The ceiling on performance looks to be CMAC, which is iterative and thus can't take advantage of them. Remove BOTAN_PARALLEL_BLOCKS_EAX, since it implicitly is whatever CTR is doing. Bump CTR's default parallel blocks to 16.
-rw-r--r--src/build-data/buildh.in3
-rw-r--r--src/filters/modes/eax/eax.cpp99
-rw-r--r--src/filters/modes/eax/eax.h18
-rw-r--r--src/filters/modes/eax/eax_dec.cpp41
-rw-r--r--src/filters/modes/eax/info.txt1
5 files changed, 60 insertions, 102 deletions
diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in
index 427184b9d..7588dc99b 100644
--- a/src/build-data/buildh.in
+++ b/src/build-data/buildh.in
@@ -30,8 +30,7 @@
#define BOTAN_PARALLEL_BLOCKS_ECB 8
#define BOTAN_PARALLEL_BLOCKS_CBC 8
#define BOTAN_PARALLEL_BLOCKS_CFB 8
-#define BOTAN_PARALLEL_BLOCKS_CTR 8
-#define BOTAN_PARALLEL_BLOCKS_EAX 8
+#define BOTAN_PARALLEL_BLOCKS_CTR 16
#define BOTAN_PARALLEL_BLOCKS_XTS 8
/* PK key consistency checking toggles */
diff --git a/src/filters/modes/eax/eax.cpp b/src/filters/modes/eax/eax.cpp
index 7893ce258..2cb700daa 100644
--- a/src/filters/modes/eax/eax.cpp
+++ b/src/filters/modes/eax/eax.cpp
@@ -7,8 +7,9 @@
#include <botan/eax.h>
#include <botan/cmac.h>
-#include <botan/internal/xor_buf.h>
+#include <botan/ctr.h>
#include <botan/parsing.h>
+#include <botan/internal/xor_buf.h>
#include <algorithm>
namespace Botan {
@@ -34,20 +35,17 @@ SecureVector<byte> eax_prf(byte tag, u32bit BLOCK_SIZE,
/*
* EAX_Base Constructor
*/
-EAX_Base::EAX_Base(BlockCipher* ciph,
- u32bit tag_size) :
- TAG_SIZE(tag_size ? tag_size / 8 : ciph->BLOCK_SIZE),
- BLOCK_SIZE(ciph->BLOCK_SIZE)
+EAX_Base::EAX_Base(BlockCipher* cipher, u32bit tag_size) :
+ BLOCK_SIZE(cipher->BLOCK_SIZE),
+ TAG_SIZE(tag_size ? tag_size / 8 : BLOCK_SIZE),
+ cipher_name(cipher->name()),
+ ctr_buf(DEFAULT_BUFFERSIZE)
{
- cipher = ciph;
- mac = new CMAC(cipher->clone());
+ cmac = new CMAC(cipher->clone());
+ ctr = new CTR_BE(cipher); // takes ownership
- if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > mac->OUTPUT_LENGTH)
+ if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > cmac->OUTPUT_LENGTH)
throw Invalid_Argument(name() + ": Bad tag size " + to_string(tag_size));
-
- state.resize(BLOCK_SIZE);
- buffer.resize(BLOCK_SIZE);
- position = 0;
}
/*
@@ -55,9 +53,7 @@ EAX_Base::EAX_Base(BlockCipher* ciph,
*/
bool EAX_Base::valid_keylength(u32bit n) const
{
- if(!cipher->valid_keylength(n))
- return false;
- if(!mac->valid_keylength(n))
+ if(!ctr->valid_keylength(n))
return false;
return true;
}
@@ -67,9 +63,14 @@ bool EAX_Base::valid_keylength(u32bit n) const
*/
void EAX_Base::set_key(const SymmetricKey& key)
{
- cipher->set_key(key);
- mac->set_key(key);
- header_mac = eax_prf(1, BLOCK_SIZE, mac, 0, 0);
+ /*
+ * These could share the key schedule, which is one nice part of EAX,
+ * but it's much easier to ignore that here...
+ */
+ ctr->set_key(key);
+ cmac->set_key(key);
+
+ header_mac = eax_prf(1, BLOCK_SIZE, cmac, 0, 0);
}
/*
@@ -78,8 +79,8 @@ void EAX_Base::set_key(const SymmetricKey& key)
void EAX_Base::start_msg()
{
for(u32bit j = 0; j != BLOCK_SIZE - 1; ++j)
- mac->update(0);
- mac->update(2);
+ cmac->update(0);
+ cmac->update(2);
}
/*
@@ -87,9 +88,8 @@ void EAX_Base::start_msg()
*/
void EAX_Base::set_iv(const InitializationVector& iv)
{
- nonce_mac = eax_prf(0, BLOCK_SIZE, mac, iv.begin(), iv.length());
- state = nonce_mac;
- cipher->encrypt(state, buffer);
+ nonce_mac = eax_prf(0, BLOCK_SIZE, cmac, iv.begin(), iv.length());
+ ctr->set_iv(&nonce_mac[0], nonce_mac.size());
}
/*
@@ -97,7 +97,7 @@ void EAX_Base::set_iv(const InitializationVector& iv)
*/
void EAX_Base::set_header(const byte header[], u32bit length)
{
- header_mac = eax_prf(1, BLOCK_SIZE, mac, header, length);
+ header_mac = eax_prf(1, BLOCK_SIZE, cmac, header, length);
}
/*
@@ -105,19 +105,7 @@ void EAX_Base::set_header(const byte header[], u32bit length)
*/
std::string EAX_Base::name() const
{
- return (cipher->name() + "/EAX");
- }
-
-/*
-* Increment the counter and update the buffer
-*/
-void EAX_Base::increment_counter()
- {
- for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j)
- if(++state[j])
- break;
- cipher->encrypt(state, buffer);
- position = 0;
+ return (cipher_name + "/EAX");
}
/*
@@ -125,32 +113,17 @@ void EAX_Base::increment_counter()
*/
void EAX_Encryption::write(const byte input[], u32bit length)
{
- u32bit copied = std::min(BLOCK_SIZE - position, length);
- xor_buf(buffer + position, input, copied);
- send(buffer + position, copied);
- mac->update(buffer + position, copied);
- input += copied;
- length -= copied;
- position += copied;
-
- if(position == BLOCK_SIZE)
- increment_counter();
-
- while(length >= BLOCK_SIZE)
+ while(length)
{
- xor_buf(buffer, input, BLOCK_SIZE);
- send(buffer, BLOCK_SIZE);
- mac->update(buffer, BLOCK_SIZE);
+ u32bit copied = std::min(length, ctr_buf.size());
- input += BLOCK_SIZE;
- length -= BLOCK_SIZE;
- increment_counter();
- }
+ ctr->cipher(input, ctr_buf, copied);
+ cmac->update(ctr_buf, copied);
- xor_buf(buffer + position, input, length);
- send(buffer + position, length);
- mac->update(buffer + position, length);
- position += length;
+ send(ctr_buf, copied);
+ input += copied;
+ length -= copied;
+ }
}
/*
@@ -158,15 +131,11 @@ void EAX_Encryption::write(const byte input[], u32bit length)
*/
void EAX_Encryption::end_msg()
{
- SecureVector<byte> data_mac = mac->final();
+ SecureVector<byte> data_mac = cmac->final();
xor_buf(data_mac, nonce_mac, data_mac.size());
xor_buf(data_mac, header_mac, data_mac.size());
send(data_mac, TAG_SIZE);
-
- state.clear();
- buffer.clear();
- position = 0;
}
}
diff --git a/src/filters/modes/eax/eax.h b/src/filters/modes/eax/eax.h
index f569f2ede..e45e29ba8 100644
--- a/src/filters/modes/eax/eax.h
+++ b/src/filters/modes/eax/eax.h
@@ -10,6 +10,7 @@
#include <botan/key_filt.h>
#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
#include <botan/mac.h>
namespace Botan {
@@ -27,17 +28,19 @@ class BOTAN_DLL EAX_Base : public Keyed_Filter
bool valid_keylength(u32bit) const;
- ~EAX_Base() { delete cipher; delete mac; }
+ ~EAX_Base() { delete ctr; delete cmac; }
protected:
EAX_Base(BlockCipher*, u32bit);
void start_msg();
- void increment_counter();
- const u32bit TAG_SIZE, BLOCK_SIZE;
- BlockCipher* cipher;
- MessageAuthenticationCode* mac;
- SecureVector<byte> nonce_mac, header_mac, state, buffer;
- u32bit position;
+ const u32bit BLOCK_SIZE, TAG_SIZE;
+ std::string cipher_name;
+
+ StreamCipher* ctr;
+ MessageAuthenticationCode* cmac;
+
+ SecureVector<byte> nonce_mac, header_mac;
+ SecureVector<byte> ctr_buf;
};
/*
@@ -76,6 +79,7 @@ class BOTAN_DLL EAX_Decryption : public EAX_Base
void write(const byte[], u32bit);
void do_write(const byte[], u32bit);
void end_msg();
+
SecureVector<byte> queue;
u32bit queue_start, queue_end;
};
diff --git a/src/filters/modes/eax/eax_dec.cpp b/src/filters/modes/eax/eax_dec.cpp
index 24b68f3b7..f41327ffc 100644
--- a/src/filters/modes/eax/eax_dec.cpp
+++ b/src/filters/modes/eax/eax_dec.cpp
@@ -52,7 +52,6 @@ void EAX_Decryption::write(const byte input[], u32bit length)
length -= copied;
queue_end += copied;
- SecureVector<byte> block_buf(cipher->BLOCK_SIZE);
while((queue_end - queue_start) > TAG_SIZE)
{
u32bit removed = (queue_end - queue_start) - TAG_SIZE;
@@ -77,31 +76,20 @@ void EAX_Decryption::write(const byte input[], u32bit length)
*/
void EAX_Decryption::do_write(const byte input[], u32bit length)
{
- mac->update(input, length);
-
- u32bit copied = std::min(BLOCK_SIZE - position, length);
- xor_buf(buffer + position, input, copied);
- send(buffer + position, copied);
- input += copied;
- length -= copied;
- position += copied;
-
- if(position == BLOCK_SIZE)
- increment_counter();
-
- while(length >= BLOCK_SIZE)
+ while(length)
{
- xor_buf(buffer, input, BLOCK_SIZE);
- send(buffer, BLOCK_SIZE);
-
- input += BLOCK_SIZE;
- length -= BLOCK_SIZE;
- increment_counter();
+ u32bit copied = std::min(length, ctr_buf.size());
+
+ /*
+ Process same block with cmac and ctr at the same time to
+ help cache locality.
+ */
+ cmac->update(input, copied);
+ ctr->cipher(input, ctr_buf, copied);
+ send(ctr_buf, copied);
+ input += copied;
+ length -= copied;
}
-
- xor_buf(buffer + position, input, length);
- send(buffer + position, length);
- position += length;
}
/*
@@ -112,15 +100,12 @@ void EAX_Decryption::end_msg()
if((queue_end - queue_start) != TAG_SIZE)
throw Integrity_Failure(name() + ": Message authentication failure");
- SecureVector<byte> data_mac = mac->final();
+ SecureVector<byte> data_mac = cmac->final();
for(u32bit j = 0; j != TAG_SIZE; ++j)
if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j]))
throw Integrity_Failure(name() + ": Message authentication failure");
- state.clear();
- buffer.clear();
- position = 0;
queue_start = queue_end = 0;
}
diff --git a/src/filters/modes/eax/info.txt b/src/filters/modes/eax/info.txt
index 4c91318d6..689414e3a 100644
--- a/src/filters/modes/eax/info.txt
+++ b/src/filters/modes/eax/info.txt
@@ -2,4 +2,5 @@ define EAX
<requires>
cmac
+ctr
</requires>