diff options
author | lloyd <[email protected]> | 2013-03-16 19:12:25 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2013-03-16 19:12:25 +0000 |
commit | aeb997bca6f6ce2856d1d346514f6e41167db957 (patch) | |
tree | c14735a2cce52e57dd69b74b46b4af889b3c3ad5 | |
parent | e139778872b8e6be9725f8540a6dab846e93e657 (diff) |
Convert EAX to using Buffered_Filter and new AEAD interface
-rw-r--r-- | src/filters/modes/eax/eax.cpp | 110 | ||||
-rw-r--r-- | src/filters/modes/eax/eax.h | 94 | ||||
-rw-r--r-- | src/filters/modes/eax/eax_dec.cpp | 112 | ||||
-rw-r--r-- | src/filters/modes/ocb/ocb.cpp | 3 |
4 files changed, 114 insertions, 205 deletions
diff --git a/src/filters/modes/eax/eax.cpp b/src/filters/modes/eax/eax.cpp index e67f03f68..57f62833b 100644 --- a/src/filters/modes/eax/eax.cpp +++ b/src/filters/modes/eax/eax.cpp @@ -20,29 +20,38 @@ namespace { * EAX MAC-based PRF */ secure_vector<byte> eax_prf(byte tag, size_t BLOCK_SIZE, - MessageAuthenticationCode* mac, + MessageAuthenticationCode& mac, const byte in[], size_t length) { for(size_t i = 0; i != BLOCK_SIZE - 1; ++i) - mac->update(0); - mac->update(tag); - mac->update(in, length); - return mac->final(); + mac.update(0); + mac.update(tag); + mac.update(in, length); + return mac.final(); + } + +size_t eax_tag_size(size_t tag_size, const BlockCipher& cipher) + { + if(tag_size == 0) + return cipher.block_size(); + return (tag_size / 8); } } /* -* EAX_Base Constructor +* EAX_Mode Constructor */ -EAX_Base::EAX_Base(BlockCipher* cipher, size_t tag_size) : +EAX_Mode::EAX_Mode(BlockCipher* cipher, size_t tag_size, bool decrypting) : + Buffered_Filter(cipher->parallel_bytes(), + decrypting ? eax_tag_size(tag_size, *cipher) : 0), BLOCK_SIZE(cipher->block_size()), - TAG_SIZE(tag_size ? tag_size / 8 : BLOCK_SIZE), + TAG_SIZE(eax_tag_size(tag_size, *cipher)), cipher_name(cipher->name()), ctr_buf(DEFAULT_BUFFERSIZE) { - cmac = new CMAC(cipher->clone()); - ctr = new CTR_BE(cipher); // takes ownership + cmac.reset(new CMAC(cipher->clone())); + ctr.reset(new CTR_BE(cipher)); // CTR_BE takes ownership of cipher if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > cmac->output_length()) throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(tag_size)); @@ -51,7 +60,7 @@ EAX_Base::EAX_Base(BlockCipher* cipher, size_t tag_size) : /* * Check if a keylength is valid for EAX */ -bool EAX_Base::valid_keylength(size_t n) const +bool EAX_Mode::valid_keylength(size_t n) const { if(!ctr->valid_keylength(n)) return false; @@ -61,7 +70,7 @@ bool EAX_Base::valid_keylength(size_t n) const /* * Set the EAX key */ -void EAX_Base::set_key(const SymmetricKey& key) +void EAX_Mode::set_key(const SymmetricKey& key) { /* * These could share the key schedule, which is one nice part of EAX, @@ -70,13 +79,13 @@ void EAX_Base::set_key(const SymmetricKey& key) ctr->set_key(key); cmac->set_key(key); - header_mac = eax_prf(1, BLOCK_SIZE, cmac, nullptr, 0); + ad_mac = eax_prf(1, BLOCK_SIZE, *cmac, nullptr, 0); } /* * Do setup at the start of each message */ -void EAX_Base::start_msg() +void EAX_Mode::start_msg() { for(size_t i = 0; i != BLOCK_SIZE - 1; ++i) cmac->update(0); @@ -86,32 +95,39 @@ void EAX_Base::start_msg() /* * Set the EAX nonce */ -void EAX_Base::set_iv(const InitializationVector& iv) +void EAX_Mode::set_nonce(const byte nonce[], size_t nonce_len) { - nonce_mac = eax_prf(0, BLOCK_SIZE, cmac, iv.begin(), iv.length()); + nonce_mac = eax_prf(0, BLOCK_SIZE, *cmac, nonce, nonce_len); ctr->set_iv(&nonce_mac[0], nonce_mac.size()); } /* -* Set the EAX header +* Set the EAX associated data */ -void EAX_Base::set_header(const byte header[], size_t length) +void EAX_Mode::set_associated_data(const byte ad[], size_t length) { - header_mac = eax_prf(1, BLOCK_SIZE, cmac, header, length); + ad_mac = eax_prf(1, BLOCK_SIZE, *cmac, ad, length); } /* * Return the name of this cipher mode */ -std::string EAX_Base::name() const +std::string EAX_Mode::name() const { return (cipher_name + "/EAX"); } -/* -* Encrypt in EAX mode -*/ -void EAX_Encryption::write(const byte input[], size_t length) +void EAX_Mode::write(const byte input[], size_t length) + { + Buffered_Filter::write(input, length); + } + +void EAX_Mode::end_msg() + { + Buffered_Filter::end_msg(); + } + +void EAX_Encryption::buffered_block(const byte input[], size_t length) { while(length) { @@ -121,21 +137,57 @@ void EAX_Encryption::write(const byte input[], size_t length) cmac->update(&ctr_buf[0], copied); send(ctr_buf, copied); + input += copied; length -= copied; } } -/* -* Finish encrypting in EAX mode -*/ -void EAX_Encryption::end_msg() +void EAX_Encryption::buffered_final(const byte input[], size_t input_length) { + buffered_block(input, input_length); + secure_vector<byte> data_mac = cmac->final(); xor_buf(data_mac, nonce_mac, data_mac.size()); - xor_buf(data_mac, header_mac, data_mac.size()); + xor_buf(data_mac, ad_mac, data_mac.size()); send(data_mac, TAG_SIZE); } +void EAX_Decryption::buffered_block(const byte input[], size_t length) + { + cmac->update(&input[0], length); + + while(length) + { + size_t copied = std::min<size_t>(length, ctr_buf.size()); + + ctr->cipher(input, &ctr_buf[0], copied); + + send(ctr_buf, copied); + + input += copied; + length -= copied; + } + } + +void EAX_Decryption::buffered_final(const byte input[], size_t input_length) + { + BOTAN_ASSERT(input_length >= TAG_SIZE, "Have the tag as part of final input"); + + const byte* included_tag = &input[input_length - TAG_SIZE]; + input_length -= TAG_SIZE; + + if(input_length) // handle any remaining input + buffered_block(input, input_length); + + secure_vector<byte> mac = cmac->final(); + mac ^= nonce_mac; + mac ^= ad_mac; + + if(!same_mem(&mac[0], included_tag, TAG_SIZE)) + throw Integrity_Failure("EAX tag check failed"); + } + + } diff --git a/src/filters/modes/eax/eax.h b/src/filters/modes/eax/eax.h index d78287521..e219487cb 100644 --- a/src/filters/modes/eax/eax.h +++ b/src/filters/modes/eax/eax.h @@ -1,6 +1,6 @@ /* * EAX Mode -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2007,2013 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,49 +8,41 @@ #ifndef BOTAN_EAX_H__ #define BOTAN_EAX_H__ -#include <botan/key_filt.h> +#include <botan/aead.h> +#include <botan/buf_filt.h> #include <botan/block_cipher.h> #include <botan/stream_cipher.h> #include <botan/mac.h> +#include <memory> namespace Botan { /** -* EAX Base Class +* EAX Mode */ -class BOTAN_DLL EAX_Base : public Keyed_Filter +class BOTAN_DLL EAX_Mode : public AEAD_Mode, + private Buffered_Filter { public: - void set_key(const SymmetricKey& key); - void set_iv(const InitializationVector& iv); + void set_key(const SymmetricKey& key) override; - /** - * Set some additional data that is not included in the - * ciphertext but that will be authenticated. - * @param header the header contents - * @param header_len length of header in bytes - */ - void set_header(const byte header[], size_t header_len); + void set_nonce(const byte nonce[], size_t nonce_len) override; - /** - * @return name of this mode - */ - std::string name() const; + void set_associated_data(const byte ad[], size_t ad_len) override; - bool valid_keylength(size_t key_len) const; + std::string name() const override; - /** - * EAX supports arbitrary IV lengths - */ - bool valid_iv_length(size_t) const { return true; } + bool valid_keylength(size_t key_len) const override; - ~EAX_Base() { delete ctr; delete cmac; } + // EAX supports arbitrary IV lengths + bool valid_iv_length(size_t) const override { return true; } protected: /** * @param cipher the cipher to use * @param tag_size is how big the auth tag will be */ - EAX_Base(BlockCipher* cipher, size_t tag_size); + EAX_Mode(BlockCipher* cipher, size_t tag_size, bool decrypting); + void start_msg(); /** @@ -71,12 +63,12 @@ class BOTAN_DLL EAX_Base : public Keyed_Filter /** * The stream cipher (CTR mode) */ - StreamCipher* ctr; + std::unique_ptr<StreamCipher> ctr; /** * The MAC (CMAC) */ - MessageAuthenticationCode* cmac; + std::unique_ptr<MessageAuthenticationCode> cmac; /** * The MAC of the nonce @@ -84,20 +76,23 @@ class BOTAN_DLL EAX_Base : public Keyed_Filter secure_vector<byte> nonce_mac; /** - * The MAC of the header + * The MAC of the associated data */ - secure_vector<byte> header_mac; + secure_vector<byte> ad_mac; /** * A buffer for CTR mode encryption */ secure_vector<byte> ctr_buf; + private: + void write(const byte[], size_t); + void end_msg(); }; /** * EAX Encryption */ -class BOTAN_DLL EAX_Encryption : public EAX_Base +class BOTAN_DLL EAX_Encryption : public EAX_Mode { public: /** @@ -105,54 +100,29 @@ class BOTAN_DLL EAX_Encryption : public EAX_Base * @param tag_size is how big the auth tag will be */ EAX_Encryption(BlockCipher* ciph, size_t tag_size = 0) : - EAX_Base(ciph, tag_size) {} + EAX_Mode(ciph, tag_size, false) {} - /** - * @param ciph the cipher to use - * @param key the key to use - * @param iv the initially set IV - * @param tag_size is how big the auth tag will be - */ - EAX_Encryption(BlockCipher* ciph, const SymmetricKey& key, - const InitializationVector& iv, - size_t tag_size) : EAX_Base(ciph, tag_size) - { - set_key(key); - set_iv(iv); - } private: - void write(const byte[], size_t); - void end_msg(); + void buffered_block(const byte input[], size_t input_length) override; + void buffered_final(const byte input[], size_t input_length) override; }; /** * EAX Decryption */ -class BOTAN_DLL EAX_Decryption : public EAX_Base +class BOTAN_DLL EAX_Decryption : public EAX_Mode { public: /** * @param ciph the cipher to use * @param tag_size is how big the auth tag will be */ - EAX_Decryption(BlockCipher* ciph, size_t tag_size = 0); + EAX_Decryption(BlockCipher* cipher, size_t tag_size = 0) : + EAX_Mode(cipher, tag_size, true) {} - /** - * @param ciph the cipher to use - * @param key the key to use - * @param iv the initially set IV - * @param tag_size is how big the auth tag will be - */ - EAX_Decryption(BlockCipher* ciph, const SymmetricKey& key, - const InitializationVector& iv, - size_t tag_size = 0); private: - void write(const byte[], size_t); - void do_write(const byte[], size_t); - void end_msg(); - - secure_vector<byte> queue; - size_t queue_start, queue_end; + void buffered_block(const byte input[], size_t input_length) override; + void buffered_final(const byte input[], size_t input_length) override; }; } diff --git a/src/filters/modes/eax/eax_dec.cpp b/src/filters/modes/eax/eax_dec.cpp deleted file mode 100644 index a2675cac0..000000000 --- a/src/filters/modes/eax/eax_dec.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -* EAX Mode Encryption -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/eax.h> -#include <botan/internal/xor_buf.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* EAX_Decryption Constructor -*/ -EAX_Decryption::EAX_Decryption(BlockCipher* ciph, - size_t tag_size) : - EAX_Base(ciph, tag_size) - { - queue.resize(2*TAG_SIZE + DEFAULT_BUFFERSIZE); - queue_start = queue_end = 0; - } - -/* -* EAX_Decryption Constructor -*/ -EAX_Decryption::EAX_Decryption(BlockCipher* ciph, - const SymmetricKey& key, - const InitializationVector& iv, - size_t tag_size) : - EAX_Base(ciph, tag_size) - { - set_key(key); - set_iv(iv); - queue.resize(2*TAG_SIZE + DEFAULT_BUFFERSIZE); - queue_start = queue_end = 0; - } - -/* -* Decrypt in EAX mode -*/ -void EAX_Decryption::write(const byte input[], size_t length) - { - while(length) - { - const size_t copied = std::min<size_t>(length, queue.size() - queue_end); - - buffer_insert(queue, queue_end, input, copied); - input += copied; - length -= copied; - queue_end += copied; - - while((queue_end - queue_start) > TAG_SIZE) - { - size_t removed = (queue_end - queue_start) - TAG_SIZE; - do_write(&queue[queue_start], removed); - queue_start += removed; - } - - if(queue_start + TAG_SIZE == queue_end && - queue_start >= queue.size() / 2) - { - secure_vector<byte> queue_data(TAG_SIZE); - copy_mem(&queue_data[0], &queue[queue_start], TAG_SIZE); - copy_mem(&queue[0], &queue_data[0], TAG_SIZE); - queue_start = 0; - queue_end = TAG_SIZE; - } - } - } - -/* -* Decrypt in EAX mode -*/ -void EAX_Decryption::do_write(const byte input[], size_t length) - { - while(length) - { - size_t copied = std::min<size_t>(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[0], copied); - send(ctr_buf, copied); - input += copied; - length -= copied; - } - } - -/* -* Finish decrypting in EAX mode -*/ -void EAX_Decryption::end_msg() - { - if((queue_end - queue_start) != TAG_SIZE) - throw Decoding_Error(name() + ": Message authentication failure"); - - secure_vector<byte> data_mac = cmac->final(); - - for(size_t j = 0; j != TAG_SIZE; ++j) - if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j])) - throw Decoding_Error(name() + ": Message authentication failure"); - - queue_start = queue_end = 0; - } - -} diff --git a/src/filters/modes/ocb/ocb.cpp b/src/filters/modes/ocb/ocb.cpp index 24f7d3d9c..ebf440d32 100644 --- a/src/filters/modes/ocb/ocb.cpp +++ b/src/filters/modes/ocb/ocb.cpp @@ -113,7 +113,6 @@ Nonce_State::update_nonce(const byte nonce[], size_t nonce_len) return offset; } - namespace { /* @@ -375,7 +374,7 @@ void OCB_Decryption::buffered_final(const byte input[], size_t input_length) { BOTAN_ASSERT(input_length >= m_tag_size, "We have the tag"); - const byte* included_tag = &input[input_length-m_tag_size]; + const byte* included_tag = &input[input_length - m_tag_size]; input_length -= m_tag_size; if(input_length >= BS) |