aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/mac
diff options
context:
space:
mode:
authorMatthias Gierlings <[email protected]>2016-10-27 19:00:23 +0200
committerMatthias Gierlings <[email protected]>2016-10-28 10:49:38 +0200
commit9ad816a5d8d74105558640b2f37baec50d8b920f (patch)
tree8400746b4ce9915244c91aa4dcaa1cfb05b508ff /src/lib/mac
parent425a2c2497387b7b5804738a77c757b93e630322 (diff)
Implements GMAC with GHASH.
Adds support for Galois Message Authentication Code calculation based on GHASH, rather than GCM_Mode.
Diffstat (limited to 'src/lib/mac')
-rw-r--r--src/lib/mac/gmac/gmac.cpp107
-rw-r--r--src/lib/mac/gmac/gmac.h35
-rw-r--r--src/lib/mac/mac.cpp11
3 files changed, 109 insertions, 44 deletions
diff --git a/src/lib/mac/gmac/gmac.cpp b/src/lib/mac/gmac/gmac.cpp
index 5d82456ae..946e22cf0 100644
--- a/src/lib/mac/gmac/gmac.cpp
+++ b/src/lib/mac/gmac/gmac.cpp
@@ -9,27 +9,22 @@
namespace Botan {
-GMAC* GMAC::make(const Spec& spec)
- {
- if(spec.arg_count() == 1)
- {
- if(auto bc = BlockCipher::create(spec.arg(0)))
- return new GMAC(bc.release());
- }
- return nullptr;
- }
-
GMAC::GMAC(BlockCipher* cipher)
- : m_iv(), m_aad(),
- m_gcm(GCM_Encryption(cipher)), m_cipher(cipher->clone())
- {
- }
+ : GHASH(),
+ m_aad_buf(),
+ m_cipher(cipher),
+ m_initialized(false)
+ {}
void GMAC::clear()
{
- m_gcm.clear();
- zeroise(m_iv);
- zeroise(m_aad);
+ GHASH::clear();
+ m_H.resize(GCM_BS);
+ m_H_ad.resize(GCM_BS);
+ m_ghash.resize(GCM_BS);
+ m_cipher->clear();
+ m_aad_buf.clear();
+ m_initialized = false;
}
std::string GMAC::name() const
@@ -39,38 +34,90 @@ std::string GMAC::name() const
size_t GMAC::output_length() const
{
- return m_gcm.tag_size();
+ return GCM_BS;
+ }
+
+void GMAC::add_data(const byte input[], size_t size)
+ {
+ m_ad_len += size;
+
+ // buffer partial blocks till we received a full input block
+ // or final is called.
+ m_aad_buf.insert(m_aad_buf.end(), input, input + size);
+ if(m_aad_buf.size() >= GCM_BS)
+ {
+ // process all complete input blocks.
+ ghash_update(m_ghash,
+ m_aad_buf.data(),
+ m_aad_buf.size() - (m_aad_buf.size() % GCM_BS));
+
+ // remove all processed blocks from buffer.
+ m_aad_buf.erase(m_aad_buf.begin(),
+ m_aad_buf.end() - (m_aad_buf.size() % GCM_BS));
+ }
}
-void GMAC::add_data(const byte input[], size_t length)
+void GMAC::key_schedule(const byte key[], size_t size)
{
- m_aad.insert(m_aad.end(), input, input + length);
+ clear();
+ m_cipher->set_key(key, size);
+ m_cipher->encrypt(m_H_ad.data(), m_H.data());
}
void GMAC::start(const std::vector<byte>& nonce)
{
- m_iv.assign(nonce.begin(), nonce.end());
+ start(nonce.data(), nonce.size());
}
void GMAC::start(const secure_vector<byte>& nonce)
{
- m_iv.assign(nonce.begin(), nonce.end());
+ start(nonce.data(), nonce.size());
+ }
+
+void GMAC::start(const byte nonce[], size_t nonce_len)
+ {
+ secure_vector<byte> y0(GCM_BS);
+
+ if(nonce_len == 12)
+ {
+ copy_mem(y0.data(), nonce, nonce_len);
+ y0[GCM_BS - 1] = 1;
+ }
+ else
+ {
+ ghash_update(y0, nonce, nonce_len);
+ add_final_block(y0, 0, nonce_len);
+ }
+
+ secure_vector<byte> m_enc_y0(GCM_BS);
+ m_cipher->encrypt(y0.data(), m_enc_y0.data());
+ GHASH::start(m_enc_y0.data(), m_enc_y0.size());
+ m_initialized = true;
}
void GMAC::final_result(byte mac[])
{
- secure_vector<byte> result;
- m_gcm.set_associated_data(m_aad.data(), m_aad.size());
- m_gcm.start(m_iv);
- m_gcm.finish(result);
+ // This ensures the GMAC computation has been initialized with a fresh
+ // nonce. The aim of this check is to prevent developers from re-using
+ // nonces (and potential nonce-reuse attacks).
+ BOTAN_ASSERT(m_initialized,
+ "The GMAC computation has not been initialized with a fresh "
+ "nonce.");
+ // process the rest of the aad buffer. Even if it is a partial block only
+ // ghash_update will process it properly.
+ if(m_aad_buf.size() > 0)
+ {
+ ghash_update(m_ghash,
+ m_aad_buf.data(),
+ m_aad_buf.size());
+ }
+ secure_vector<byte> result = GHASH::final();
std::copy(result.begin(), result.end(), mac);
-
- zeroise(m_aad);
- m_aad.clear();
+ clear();
}
MessageAuthenticationCode* GMAC::clone() const
{
- return new GMAC(m_cipher->clone());
+ return new GMAC(BlockCipher::create(m_cipher->name()).release());
}
}
diff --git a/src/lib/mac/gmac/gmac.h b/src/lib/mac/gmac/gmac.h
index d83236b32..b651c2e11 100644
--- a/src/lib/mac/gmac/gmac.h
+++ b/src/lib/mac/gmac/gmac.h
@@ -8,9 +8,9 @@
#ifndef BOTAN_GMAC_H__
#define BOTAN_GMAC_H__
-#include <botan/types.h>
-#include <botan/mac.h>
#include <botan/gcm.h>
+#include <botan/mac.h>
+#include <botan/types.h>
#include <algorithm>
namespace Botan {
@@ -18,7 +18,9 @@ namespace Botan {
/**
* GMAC
*/
-class BOTAN_DLL GMAC : public MessageAuthenticationCode
+class BOTAN_DLL GMAC : public MessageAuthenticationCode,
+ public GHASH
+
{
public:
void clear() override;
@@ -31,6 +33,15 @@ class BOTAN_DLL GMAC : public MessageAuthenticationCode
* calculation.
*
* @param nonce Initialization vector.
+ * @param nonce_len size of initialization vector.
+ */
+ void start(const byte nonce[], size_t nonce_len);
+
+ /**
+ * Must be called to set the initialization vector prior to GMAC
+ * calculation.
+ *
+ * @param nonce Initialization vector.
*/
void start(const secure_vector<byte>& nonce);
@@ -44,7 +55,7 @@ class BOTAN_DLL GMAC : public MessageAuthenticationCode
Key_Length_Specification key_spec() const
{
- return m_gcm.key_spec();
+ return m_cipher->key_spec();
}
/**
@@ -54,23 +65,19 @@ class BOTAN_DLL GMAC : public MessageAuthenticationCode
*/
explicit GMAC(BlockCipher* cipher);
- static GMAC* make(const Spec& spec);
-
GMAC(const GMAC&) = delete;
GMAC& operator=(const GMAC&) = delete;
+
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 key_schedule(const byte key[], size_t size) override;
- void key_schedule(const byte key[], size_t size) override
- {
- m_gcm.set_key(key, size);
- }
-
- secure_vector<byte> m_iv;
- secure_vector<byte> m_aad;
- GCM_Encryption m_gcm;
+ static const size_t GCM_BS = 16;
+ secure_vector<byte> m_aad_buf;
std::unique_ptr<BlockCipher> m_cipher;
+ bool m_initialized;
};
}
diff --git a/src/lib/mac/mac.cpp b/src/lib/mac/mac.cpp
index f2c5557c7..2fa321a67 100644
--- a/src/lib/mac/mac.cpp
+++ b/src/lib/mac/mac.cpp
@@ -45,6 +45,17 @@ MessageAuthenticationCode::create(const std::string& algo_spec,
{
const SCAN_Name req(algo_spec);
+#if defined(BOTAN_HAS_GMAC)
+ if(req.algo_name() == "GMAC" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ if(auto bc = BlockCipher::create(req.arg(0)))
+ return std::unique_ptr<MessageAuthenticationCode>(new GMAC(bc.release()));
+ }
+ }
+#endif
+
#if defined(BOTAN_HAS_HMAC)
if(req.algo_name() == "HMAC" && req.arg_count() == 1)
{