aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-03-16 19:12:25 +0000
committerlloyd <[email protected]>2013-03-16 19:12:25 +0000
commitaeb997bca6f6ce2856d1d346514f6e41167db957 (patch)
treec14735a2cce52e57dd69b74b46b4af889b3c3ad5
parente139778872b8e6be9725f8540a6dab846e93e657 (diff)
Convert EAX to using Buffered_Filter and new AEAD interface
-rw-r--r--src/filters/modes/eax/eax.cpp110
-rw-r--r--src/filters/modes/eax/eax.h94
-rw-r--r--src/filters/modes/eax/eax_dec.cpp112
-rw-r--r--src/filters/modes/ocb/ocb.cpp3
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)