aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-10-28 14:14:16 -0400
committerJack Lloyd <[email protected]>2016-10-28 14:14:16 -0400
commit8863848ad3b21ad6e2cf626b75e991484be61a9f (patch)
tree342d79736b971a14413f07a952b349f19e49c9d2 /src
parent9ad816a5d8d74105558640b2f37baec50d8b920f (diff)
Add MAC::start_msg, update GMAC
GMAC needs a per-message nonce specified with `start`, and other MACs are capable of using nonces (Skein-MAC, for instance) so move this API up to MAC class. Change GMAC::clone to clone the owned cipher.
Diffstat (limited to 'src')
-rw-r--r--src/lib/mac/gmac/gmac.cpp14
-rw-r--r--src/lib/mac/gmac/gmac.h4
-rw-r--r--src/lib/mac/mac.h49
-rw-r--r--src/tests/test_mac.cpp39
4 files changed, 59 insertions, 47 deletions
diff --git a/src/lib/mac/gmac/gmac.cpp b/src/lib/mac/gmac/gmac.cpp
index 946e22cf0..4461cf370 100644
--- a/src/lib/mac/gmac/gmac.cpp
+++ b/src/lib/mac/gmac/gmac.cpp
@@ -64,17 +64,7 @@ void GMAC::key_schedule(const byte key[], size_t size)
m_cipher->encrypt(m_H_ad.data(), m_H.data());
}
-void GMAC::start(const std::vector<byte>& nonce)
- {
- start(nonce.data(), nonce.size());
- }
-
-void GMAC::start(const secure_vector<byte>& nonce)
- {
- start(nonce.data(), nonce.size());
- }
-
-void GMAC::start(const byte nonce[], size_t nonce_len)
+void GMAC::start_msg(const byte nonce[], size_t nonce_len)
{
secure_vector<byte> y0(GCM_BS);
@@ -118,6 +108,6 @@ void GMAC::final_result(byte mac[])
MessageAuthenticationCode* GMAC::clone() const
{
- return new GMAC(BlockCipher::create(m_cipher->name()).release());
+ return new GMAC(m_cipher->clone());
}
}
diff --git a/src/lib/mac/gmac/gmac.h b/src/lib/mac/gmac/gmac.h
index b651c2e11..b05c5451f 100644
--- a/src/lib/mac/gmac/gmac.h
+++ b/src/lib/mac/gmac/gmac.h
@@ -53,7 +53,7 @@ class BOTAN_DLL GMAC : public MessageAuthenticationCode,
*/
void start(const std::vector<byte>& nonce);
- Key_Length_Specification key_spec() const
+ Key_Length_Specification key_spec() const override
{
return m_cipher->key_spec();
}
@@ -71,7 +71,7 @@ class BOTAN_DLL GMAC : public MessageAuthenticationCode,
private:
void add_data(const byte[], size_t) override;
void final_result(byte[]) override;
- void start_msg(const byte nonce[], size_t nonce_len);
+ void start_msg(const byte nonce[], size_t nonce_len) override;
void key_schedule(const byte key[], size_t size) override;
static const size_t GCM_BS = 16;
diff --git a/src/lib/mac/mac.h b/src/lib/mac/mac.h
index 9c3614f33..d7808c1bf 100644
--- a/src/lib/mac/mac.h
+++ b/src/lib/mac/mac.h
@@ -51,6 +51,55 @@ class BOTAN_DLL MessageAuthenticationCode : public Buffered_Computation,
virtual ~MessageAuthenticationCode() {}
/**
+ * Prepare for processing a message under the specified nonce
+ *
+ * Most MACs neither require nor support a nonce; for these algorithms
+ * calling `start_msg` is optional and calling it with anything other than
+ * an empty string is an error. One MAC which *requires* a per-message
+ * nonce be specified is GMAC.
+ *
+ * @param nonce the message nonce bytes
+ * @param nonce_len the size of len in bytes
+ * Default implementation simply rejects all non-empty nonces
+ * since most hash/MAC algorithms do not support randomization
+ */
+ virtual void start_msg(const byte nonce[], size_t nonce_len)
+ {
+ BOTAN_UNUSED(nonce);
+ if(nonce_len > 0)
+ throw Invalid_IV_Length(name(), nonce_len);
+ }
+
+ /**
+ * Begin processing a message with a nonce
+ *
+ * @param nonce the per message nonce
+ */
+ template<typename Alloc>
+ void start(const std::vector<byte, Alloc>& nonce)
+ {
+ start_msg(nonce.data(), nonce.size());
+ }
+
+ /**
+ * Begin processing a message.
+ * @param nonce the per message nonce
+ * @param nonce_len length of nonce
+ */
+ void start(const byte nonce[], size_t nonce_len)
+ {
+ start_msg(nonce, nonce_len);
+ }
+
+ /**
+ * Begin processing a message.
+ */
+ void start()
+ {
+ return start_msg(nullptr, 0);
+ }
+
+ /**
* Verify a MAC.
* @param in the MAC to verify as a byte array
* @param length the length of param in
diff --git a/src/tests/test_mac.cpp b/src/tests/test_mac.cpp
index 43b19b14e..33972fabc 100644
--- a/src/tests/test_mac.cpp
+++ b/src/tests/test_mac.cpp
@@ -11,10 +11,6 @@
#include <botan/mac.h>
#endif
-#if defined(BOTAN_HAS_GMAC)
- #include <botan/gmac.h>
-#endif
-
namespace Botan_Tests {
namespace {
@@ -60,14 +56,7 @@ class Message_Auth_Tests : public Text_Based_Test
result.test_eq(provider, mac->name(), algo);
mac->set_key(key);
-
-#if defined(BOTAN_HAS_GMAC)
- // GMAC needs to set an IV
- if(Botan::GMAC* gmac = dynamic_cast<Botan::GMAC*>(mac.get()))
- {
- gmac->start(iv);
- }
-#endif
+ mac->start(iv);
mac->update(input);
@@ -80,13 +69,7 @@ class Message_Auth_Tests : public Text_Based_Test
// do the same to test verify_mac()
mac->set_key(key);
-#if defined(BOTAN_HAS_GMAC)
- // GMAC needs to set an IV
- if(Botan::GMAC* gmac = dynamic_cast<Botan::GMAC*>(mac.get()))
- {
- gmac->start(iv);
- }
-#endif
+ mac->start(iv);
mac->update(input);
result.test_eq(provider + " correct mac", mac->verify_mac(expected.data(), expected.size()), true);
@@ -94,13 +77,8 @@ class Message_Auth_Tests : public Text_Based_Test
if(input.size() > 2)
{
mac->set_key(key); // Poly1305 requires the re-key
-#if defined(BOTAN_HAS_GMAC)
- // GMAC needs to set an IV
- if(Botan::GMAC* gmac = dynamic_cast<Botan::GMAC*>(mac.get()))
- {
- gmac->start(iv);
- }
-#endif
+ mac->start(iv);
+
mac->update(input[0]);
mac->update(&input[1], input.size() - 2);
mac->update(input[input.size()-1]);
@@ -109,13 +87,8 @@ class Message_Auth_Tests : public Text_Based_Test
// do the same to test verify_mac()
mac->set_key(key);
-#if defined(BOTAN_HAS_GMAC)
- // GMAC needs to set an IV
- if(Botan::GMAC* gmac = dynamic_cast<Botan::GMAC*>(mac.get()))
- {
- gmac->start(iv);
- }
-#endif
+ mac->start(iv);
+
mac->update(input[ 0 ]);
mac->update(&input[ 1 ], input.size() - 2);
mac->update(input[ input.size() - 1 ]);