aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-03-20 03:49:02 +0000
committerlloyd <[email protected]>2013-03-20 03:49:02 +0000
commit0dfd29109aa7ce3665aeca3cc95afbafcf2b7be2 (patch)
tree68d92921139da36a1e44ccc9d52c51fa62a59e55 /src
parent1d4b469ecd0499559a463f90bd8553ef075061d9 (diff)
Move EAX to new AEAD_Mode interface
Diffstat (limited to 'src')
-rw-r--r--src/aead/aead.h81
-rw-r--r--src/aead/eax/eax.cpp143
-rw-r--r--src/aead/eax/eax.h102
-rw-r--r--src/aead/eax/info.txt (renamed from src/filters/aead/eax/info.txt)0
-rw-r--r--src/aead/info.txt1
-rw-r--r--src/filters/aead/eax/eax.cpp183
-rw-r--r--src/filters/aead/eax/eax.h130
7 files changed, 327 insertions, 313 deletions
diff --git a/src/aead/aead.h b/src/aead/aead.h
new file mode 100644
index 000000000..af6f0e76a
--- /dev/null
+++ b/src/aead/aead.h
@@ -0,0 +1,81 @@
+/*
+* Interface for AEAD modes
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AEAD_MODE_H__
+#define BOTAN_AEAD_MODE_H__
+
+#include <botan/sym_algo.h>
+
+namespace Botan {
+
+/**
+* Interface for AEAD (Authenticated Encryption with Associated Data)
+* modes. These modes provide both encryption and message
+* authentication, and can authenticate additional per-message data
+* which is not included in the ciphertext (for instance a sequence
+* number).
+*/
+class AEAD_Mode : public SymmetricAlgorithm
+ {
+ public:
+ /**
+ * @return size of required blocks to update
+ */
+ virtual size_t update_granularity() const = 0;
+
+ /**
+ * @return required minimium size to finalize() - may be any
+ * length larger than this.
+ */
+ virtual size_t minimum_final_size() const = 0;
+
+ /**
+ * Set associated data that is not included in the ciphertext but
+ * that should be authenticated. Must be called after set_key
+ * and before end_msg.
+ *
+ * Unless reset by another call, the associated data is kept
+ * between messages. Thus, if the AD does not change, calling
+ * once (after set_key) is the optimum.
+ *
+ * @param ad the associated data
+ * @param ad_len length of add in bytes
+ */
+ virtual void set_associated_data(const byte ad[], size_t ad_len) = 0;
+
+ virtual bool valid_nonce_length(size_t) const = 0;
+
+ /**
+ * Begin processing a message.
+ *
+ * @param nonce the per message nonce
+ * @param nonce_len length of nonce
+ */
+ virtual secure_vector<byte> start(const byte nonce[], size_t nonce_len) = 0;
+
+ /**
+ * Update (encrypt or decrypt) some data. Input must be in size
+ * update_granularity() byte blocks.
+ * @param blocks in/out paramter which will possibly be resized
+ */
+ virtual void update(secure_vector<byte>& blocks) = 0;
+
+ /**
+ * Complete processing of a message. For decryption, may throw an exception
+ * due to authentication failure.
+ *
+ * @param final_block in/out parameter which must be at least
+ * minimum_final_size() bytes, and will be set to any final output
+ */
+ virtual void finish(secure_vector<byte>& final_block) = 0;
+
+ virtual ~AEAD_Mode() {}
+ };
+
+}
+
+#endif
diff --git a/src/aead/eax/eax.cpp b/src/aead/eax/eax.cpp
new file mode 100644
index 000000000..d03d6ec5e
--- /dev/null
+++ b/src/aead/eax/eax.cpp
@@ -0,0 +1,143 @@
+/*
+* EAX Mode Encryption
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eax.h>
+#include <botan/cmac.h>
+#include <botan/ctr.h>
+#include <botan/parsing.h>
+#include <botan/internal/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/*
+* EAX MAC-based PRF
+*/
+secure_vector<byte> eax_prf(byte tag, size_t block_size,
+ 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();
+ }
+
+}
+
+/*
+* EAX_Mode Constructor
+*/
+EAX_Mode::EAX_Mode(BlockCipher* cipher, size_t tag_size) :
+ m_tag_size(tag_size),
+ m_cipher(cipher),
+ m_ctr(new CTR_BE(m_cipher->clone())),
+ m_cmac(new CMAC(m_cipher->clone()))
+ {
+ if(tag_size < 8 || tag_size > m_cmac->output_length())
+ throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(tag_size));
+ }
+
+size_t EAX_Mode::update_granularity() const
+ {
+ return 8 * m_cipher->parallel_bytes();
+ }
+
+/*
+* Set the EAX key
+*/
+void EAX_Mode::key_schedule(const byte key[], size_t length)
+ {
+ /*
+ * These could share the key schedule, which is one nice part of EAX,
+ * but it's much easier to ignore that here...
+ */
+ m_ctr->set_key(key, length);
+ m_cmac->set_key(key, length);
+
+ m_ad_mac = eax_prf(1, block_size(), *m_cmac, nullptr, 0);
+ }
+
+/*
+* Set the EAX associated data
+*/
+void EAX_Mode::set_associated_data(const byte ad[], size_t length)
+ {
+ m_ad_mac = eax_prf(1, block_size(), *m_cmac, ad, length);
+ }
+
+secure_vector<byte> EAX_Mode::start(const byte nonce[], size_t nonce_len)
+ {
+ m_nonce_mac = eax_prf(0, block_size(), *m_cmac, nonce, nonce_len);
+
+ m_ctr->set_iv(&m_nonce_mac[0], m_nonce_mac.size());
+
+ for(size_t i = 0; i != block_size() - 1; ++i)
+ m_cmac->update(0);
+ m_cmac->update(2);
+
+ return secure_vector<byte>();
+ }
+
+/*
+* Return the name of this cipher mode
+*/
+std::string EAX_Mode::name() const
+ {
+ return (m_cipher->name() + "/EAX");
+ }
+
+void EAX_Encryption::update(secure_vector<byte>& buffer)
+ {
+ m_ctr->cipher(&buffer[0], &buffer[0], buffer.size());
+ m_cmac->update(&buffer[0], buffer.size());
+ }
+
+void EAX_Encryption::finish(secure_vector<byte>& buffer)
+ {
+ update(buffer);
+
+ secure_vector<byte> data_mac = m_cmac->final();
+ xor_buf(data_mac, m_nonce_mac, data_mac.size());
+ xor_buf(data_mac, m_ad_mac, data_mac.size());
+
+ buffer += data_mac;
+ }
+
+void EAX_Decryption::update(secure_vector<byte>& buffer)
+ {
+ m_cmac->update(&buffer[0], buffer.size());
+ m_ctr->cipher(&buffer[0], &buffer[0], buffer.size());
+ }
+
+void EAX_Decryption::finish(secure_vector<byte>& buffer)
+ {
+ BOTAN_ASSERT(buffer.size() >= tag_size(),
+ "Have the tag as part of final input");
+
+ const size_t input_length = buffer.size() - tag_size();
+
+ if(input_length) // handle any remaining input
+ {
+ m_cmac->update(&buffer[0], buffer.size());
+ m_ctr->cipher(&buffer[0], &buffer[0], buffer.size());
+ }
+
+ const byte* included_tag = &buffer[input_length];
+
+ secure_vector<byte> mac = m_cmac->final();
+ mac ^= m_nonce_mac;
+ mac ^= m_ad_mac;
+
+ if(!same_mem(&mac[0], included_tag, tag_size()))
+ throw Integrity_Failure("EAX tag check failed");
+ }
+
+}
diff --git a/src/aead/eax/eax.h b/src/aead/eax/eax.h
new file mode 100644
index 000000000..f7e1c6387
--- /dev/null
+++ b/src/aead/eax/eax.h
@@ -0,0 +1,102 @@
+/*
+* EAX Mode
+* (C) 1999-2007,2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAX_H__
+#define BOTAN_EAX_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 Mode
+*/
+class BOTAN_DLL EAX_Mode : public AEAD_Mode
+ {
+ public:
+ size_t update_granularity() const;
+
+ secure_vector<byte> start(const byte nonce[], size_t nonce_len) override;
+
+ void set_associated_data(const byte ad[], size_t ad_len) override;
+
+ std::string name() const override;
+
+ Key_Length_Specification key_spec() const override { return m_cipher->key_spec(); }
+
+ // EAX supports arbitrary nonce lengths
+ bool valid_nonce_length(size_t) const override { return true; }
+ protected:
+ void key_schedule(const byte key[], size_t length) override;
+
+ /**
+ * @param cipher the cipher to use
+ * @param tag_size is how big the auth tag will be
+ */
+ EAX_Mode(BlockCipher* cipher, size_t tag_size);
+
+ size_t tag_size() const { return m_tag_size; }
+
+ size_t block_size() const { return m_cipher->block_size(); }
+
+ size_t m_tag_size;
+
+ std::unique_ptr<BlockCipher> m_cipher;
+ std::unique_ptr<StreamCipher> m_ctr;
+ std::unique_ptr<MessageAuthenticationCode> m_cmac;
+
+ secure_vector<byte> m_ad_mac;
+
+ secure_vector<byte> m_nonce_mac;
+ };
+
+/**
+* EAX Encryption
+*/
+class BOTAN_DLL EAX_Encryption : public EAX_Mode
+ {
+ public:
+ /**
+ * @param cipher a 128-bit block cipher
+ * @param tag_size is how big the auth tag will be
+ */
+ EAX_Encryption(BlockCipher* cipher, size_t tag_size = 16) :
+ EAX_Mode(cipher, tag_size) {}
+
+ void update(secure_vector<byte>& blocks) override;
+
+ void finish(secure_vector<byte>& final_block) override;
+ };
+
+/**
+* EAX Decryption
+*/
+class BOTAN_DLL EAX_Decryption : public EAX_Mode
+ {
+ public:
+ /**
+ * @param cipher a 128-bit block cipher
+ * @param tag_size is how big the auth tag will be
+ */
+ EAX_Decryption(BlockCipher* cipher, size_t tag_size = 16) :
+ EAX_Mode(cipher, tag_size) {}
+
+ size_t minimum_final_size() const override { return tag_size(); }
+
+ void update(secure_vector<byte>& blocks) override;
+
+ void finish(secure_vector<byte>& final_block) override;
+ };
+
+}
+
+#endif
diff --git a/src/filters/aead/eax/info.txt b/src/aead/eax/info.txt
index 09d92e724..09d92e724 100644
--- a/src/filters/aead/eax/info.txt
+++ b/src/aead/eax/info.txt
diff --git a/src/aead/info.txt b/src/aead/info.txt
new file mode 100644
index 000000000..eae4b4340
--- /dev/null
+++ b/src/aead/info.txt
@@ -0,0 +1 @@
+define AEAD_MODE
diff --git a/src/filters/aead/eax/eax.cpp b/src/filters/aead/eax/eax.cpp
deleted file mode 100644
index d4a982aaf..000000000
--- a/src/filters/aead/eax/eax.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
-* EAX Mode Encryption
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/eax.h>
-#include <botan/cmac.h>
-#include <botan/ctr.h>
-#include <botan/parsing.h>
-#include <botan/internal/xor_buf.h>
-#include <algorithm>
-
-namespace Botan {
-
-namespace {
-
-/*
-* EAX MAC-based PRF
-*/
-secure_vector<byte> eax_prf(byte tag, size_t BLOCK_SIZE,
- 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();
- }
-
-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_Mode Constructor
-*/
-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(eax_tag_size(tag_size, *cipher)),
- cipher_name(cipher->name()),
- ctr_buf(DEFAULT_BUFFERSIZE)
- {
- 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));
- }
-
-/*
-* Set the EAX key
-*/
-void EAX_Mode::set_key(const SymmetricKey& key)
- {
- /*
- * 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);
-
- ad_mac = eax_prf(1, BLOCK_SIZE, *cmac, nullptr, 0);
- }
-
-/*
-* Do setup at the start of each message
-*/
-void EAX_Mode::start_msg()
- {
- for(size_t i = 0; i != BLOCK_SIZE - 1; ++i)
- cmac->update(0);
- cmac->update(2);
- }
-
-/*
-* Set the EAX nonce
-*/
-void EAX_Mode::set_nonce(const byte nonce[], size_t nonce_len)
- {
- nonce_mac = eax_prf(0, BLOCK_SIZE, *cmac, nonce, nonce_len);
- ctr->set_iv(&nonce_mac[0], nonce_mac.size());
- }
-
-/*
-* Set the EAX associated data
-*/
-void EAX_Mode::set_associated_data(const byte ad[], size_t length)
- {
- ad_mac = eax_prf(1, BLOCK_SIZE, *cmac, ad, length);
- }
-
-/*
-* Return the name of this cipher mode
-*/
-std::string EAX_Mode::name() const
- {
- return (cipher_name + "/EAX");
- }
-
-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)
- {
- size_t copied = std::min<size_t>(length, ctr_buf.size());
-
- ctr->cipher(input, &ctr_buf[0], copied);
- cmac->update(&ctr_buf[0], copied);
-
- send(ctr_buf, copied);
-
- input += copied;
- length -= copied;
- }
- }
-
-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, 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/aead/eax/eax.h b/src/filters/aead/eax/eax.h
deleted file mode 100644
index cf99622a1..000000000
--- a/src/filters/aead/eax/eax.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
-* EAX Mode
-* (C) 1999-2007,2013 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_EAX_H__
-#define BOTAN_EAX_H__
-
-#include <botan/aead_filt.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 Mode
-*/
-class BOTAN_DLL EAX_Mode : public AEAD_Filter,
- private Buffered_Filter
- {
- public:
- void set_key(const SymmetricKey& key) override;
-
- void set_nonce(const byte nonce[], size_t nonce_len) override;
-
- void set_associated_data(const byte ad[], size_t ad_len) override;
-
- std::string name() const override;
-
- Key_Length_Specification key_spec() const override { return ctr->key_spec(); }
-
- // 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_Mode(BlockCipher* cipher, size_t tag_size, bool decrypting);
-
- void start_msg();
-
- /**
- * The block size of the underlying cipher
- */
- const size_t BLOCK_SIZE;
-
- /**
- * The requested tag name
- */
- const size_t TAG_SIZE;
-
- /**
- * The name of the cipher
- */
- std::string cipher_name;
-
- /**
- * The stream cipher (CTR mode)
- */
- std::unique_ptr<StreamCipher> ctr;
-
- /**
- * The MAC (CMAC)
- */
- std::unique_ptr<MessageAuthenticationCode> cmac;
-
- /**
- * The MAC of the nonce
- */
- secure_vector<byte> nonce_mac;
-
- /**
- * The MAC of the associated data
- */
- 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_Mode
- {
- public:
- /**
- * @param ciph the cipher to use
- * @param tag_size is how big the auth tag will be
- */
- EAX_Encryption(BlockCipher* ciph, size_t tag_size = 0) :
- EAX_Mode(ciph, tag_size, false) {}
-
- private:
- 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_Mode
- {
- public:
- /**
- * @param ciph the cipher to use
- * @param tag_size is how big the auth tag will be
- */
- EAX_Decryption(BlockCipher* cipher, size_t tag_size = 0) :
- EAX_Mode(cipher, tag_size, true) {}
-
- private:
- void buffered_block(const byte input[], size_t input_length) override;
- void buffered_final(const byte input[], size_t input_length) override;
- };
-
-}
-
-#endif