diff options
author | lloyd <[email protected]> | 2009-12-23 20:25:01 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-12-23 20:25:01 +0000 |
commit | 882dd7d7f723e05ecf2c3b2d40d9ac0538b743a5 (patch) | |
tree | 0b373528d0c2f04ee680c5d2243d890135d8963a | |
parent | 4043de7bbe0785556201925c047a28e1fa3e30f1 (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.in | 3 | ||||
-rw-r--r-- | src/filters/modes/eax/eax.cpp | 99 | ||||
-rw-r--r-- | src/filters/modes/eax/eax.h | 18 | ||||
-rw-r--r-- | src/filters/modes/eax/eax_dec.cpp | 41 | ||||
-rw-r--r-- | src/filters/modes/eax/info.txt | 1 |
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> |