aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/mac
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-10-13 12:08:30 -0400
committerJack Lloyd <[email protected]>2017-10-13 12:16:39 -0400
commit577828a93755549f0e9d8413488e3e4485c67263 (patch)
treedbb1d6284914e0aa89212bfd33016e1a1a2c45c5 /src/lib/mac
parent742420b4b631d6d9139fe5f63ca5650f4fb56b9d (diff)
Optimize GCM
By allowing multiple blocks for clmul, slight speedup there though still far behind optimum. Precompute a table of multiples of H, 3-4x faster on systems without clmul (and still no secret indexes). Refactor GMAC to not derive from GHASH
Diffstat (limited to 'src/lib/mac')
-rw-r--r--src/lib/mac/gmac/gmac.cpp46
-rw-r--r--src/lib/mac/gmac/gmac.h4
2 files changed, 27 insertions, 23 deletions
diff --git a/src/lib/mac/gmac/gmac.cpp b/src/lib/mac/gmac/gmac.cpp
index 7ce546ad5..af5d245ba 100644
--- a/src/lib/mac/gmac/gmac.cpp
+++ b/src/lib/mac/gmac/gmac.cpp
@@ -1,6 +1,7 @@
/*
* GMAC
* (C) 2016 Matthias Gierlings, René Korthaus
+ * (C) 2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -9,20 +10,17 @@
namespace Botan {
-GMAC::GMAC(BlockCipher* cipher)
- : GHASH(),
- m_aad_buf(),
- m_cipher(cipher),
- m_initialized(false)
+GMAC::GMAC(BlockCipher* cipher) :
+ m_aad_buf(),
+ m_cipher(cipher),
+ m_ghash(new GHASH),
+ m_initialized(false)
{}
void GMAC::clear()
{
- GHASH::clear();
- m_H.resize(GCM_BS);
- m_H_ad.resize(GCM_BS);
- m_ghash.resize(GCM_BS);
m_cipher->clear();
+ m_ghash->clear();
m_aad_buf.clear();
m_initialized = false;
}
@@ -39,7 +37,10 @@ size_t GMAC::output_length() const
void GMAC::add_data(const uint8_t input[], size_t size)
{
- m_ad_len += size;
+ /*
+ FIXME this could be much more efficient, and only buffer leftovers
+ as needed, instead of inserting everything into the buffer
+ */
// buffer partial blocks till we received a full input block
// or final is called.
@@ -47,9 +48,8 @@ void GMAC::add_data(const uint8_t input[], size_t 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));
+ m_ghash->update_associated_data(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(),
@@ -61,7 +61,10 @@ void GMAC::key_schedule(const uint8_t key[], size_t size)
{
clear();
m_cipher->set_key(key, size);
- m_cipher->encrypt(m_H_ad.data(), m_H.data());
+
+ secure_vector<uint8_t> H(GCM_BS);
+ m_cipher->encrypt(H);
+ m_ghash->set_key(H);
}
void GMAC::start_msg(const uint8_t nonce[], size_t nonce_len)
@@ -75,13 +78,13 @@ void GMAC::start_msg(const uint8_t nonce[], size_t nonce_len)
}
else
{
- ghash_update(y0, nonce, nonce_len);
- add_final_block(y0, 0, nonce_len);
+ m_ghash->ghash_update(y0, nonce, nonce_len);
+ m_ghash->add_final_block(y0, 0, nonce_len);
}
secure_vector<uint8_t> 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_ghash->start(m_enc_y0.data(), m_enc_y0.size());
m_initialized = true;
}
@@ -90,17 +93,16 @@ void GMAC::final_result(uint8_t mac[])
// 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, "GMAC was used with a fresh nonce");
+ if(m_initialized == false)
+ throw Invalid_State("GMAC was not used 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());
+ m_ghash->update_associated_data(m_aad_buf.data(), m_aad_buf.size());
}
- secure_vector<uint8_t> result = GHASH::final();
+ secure_vector<uint8_t> result = m_ghash->final();
copy_mem(mac, result.data(), result.size());
clear();
}
diff --git a/src/lib/mac/gmac/gmac.h b/src/lib/mac/gmac/gmac.h
index 970f9c047..bab170252 100644
--- a/src/lib/mac/gmac/gmac.h
+++ b/src/lib/mac/gmac/gmac.h
@@ -1,6 +1,7 @@
/*
* GMAC
* (C) 2016 Matthias Gierlings, René Korthaus
+ * (C) 2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -20,7 +21,7 @@ namespace Botan {
* GMAC requires a unique initialization vector be used for each message.
* This must be provided via the MessageAuthenticationCode::start() API
*/
-class BOTAN_PUBLIC_API(2,0) GMAC final : public MessageAuthenticationCode, public GHASH
+class BOTAN_PUBLIC_API(2,0) GMAC final : public MessageAuthenticationCode
{
public:
void clear() override;
@@ -52,6 +53,7 @@ class BOTAN_PUBLIC_API(2,0) GMAC final : public MessageAuthenticationCode, publi
static const size_t GCM_BS = 16;
secure_vector<uint8_t> m_aad_buf;
std::unique_ptr<BlockCipher> m_cipher;
+ std::unique_ptr<GHASH> m_ghash;
bool m_initialized;
};