diff options
author | Jack Lloyd <[email protected]> | 2017-10-13 12:08:30 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-10-13 12:16:39 -0400 |
commit | 577828a93755549f0e9d8413488e3e4485c67263 (patch) | |
tree | dbb1d6284914e0aa89212bfd33016e1a1a2c45c5 /src/lib/mac | |
parent | 742420b4b631d6d9139fe5f63ca5650f4fb56b9d (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.cpp | 46 | ||||
-rw-r--r-- | src/lib/mac/gmac/gmac.h | 4 |
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; }; |