aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2019-01-31 18:04:19 -0500
committerJack Lloyd <[email protected]>2019-01-31 18:04:19 -0500
commit85321dbcc0ca97846213ef6eb245c3e1159078e2 (patch)
treee8493bc9bda7305309102ef27fa1c53552be5e2e /src/lib
parentd05239be44536057c150fd5aff925ccc226b5c5a (diff)
Minor HMAC optimizations
Most importantly, avoid an allocation when the key is larger than a block size. Also avoid some virtual calls that can be cached.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/mac/hmac/hmac.cpp42
-rw-r--r--src/lib/mac/hmac/hmac.h4
2 files changed, 31 insertions, 15 deletions
diff --git a/src/lib/mac/hmac/hmac.cpp b/src/lib/mac/hmac/hmac.cpp
index 72c617c5b..2552a87f5 100644
--- a/src/lib/mac/hmac/hmac.cpp
+++ b/src/lib/mac/hmac/hmac.cpp
@@ -27,7 +27,7 @@ void HMAC::final_result(uint8_t mac[])
verify_key_set(m_okey.empty() == false);
m_hash->final(mac);
m_hash->update(m_okey);
- m_hash->update(mac, output_length());
+ m_hash->update(mac, m_hash_output_length);
m_hash->final(mac);
m_hash->update(m_ikey);
}
@@ -38,27 +38,38 @@ Key_Length_Specification HMAC::key_spec() const
return Key_Length_Specification(0, 4096);
}
+size_t HMAC::output_length() const
+ {
+ return m_hash_output_length;
+ }
+
/*
* HMAC Key Schedule
*/
void HMAC::key_schedule(const uint8_t key[], size_t length)
{
- m_hash->clear();
-
- m_ikey.resize(m_hash->hash_block_size());
- m_okey.resize(m_hash->hash_block_size());
-
const uint8_t ipad = 0x36;
const uint8_t opad = 0x5C;
- std::fill(m_ikey.begin(), m_ikey.end(), ipad);
- std::fill(m_okey.begin(), m_okey.end(), opad);
+ m_hash->clear();
+
+ m_ikey.resize(m_hash_block_size);
+ set_mem(m_ikey.data(), m_hash_block_size, ipad);
+
+ m_okey.resize(m_hash_block_size);
+ set_mem(m_okey.data(), m_hash_block_size, opad);
- if(length > m_hash->hash_block_size())
+ if(length > m_hash_block_size)
{
- secure_vector<uint8_t> hmac_key = m_hash->process(key, length);
- xor_buf(m_ikey, hmac_key, hmac_key.size());
- xor_buf(m_okey, hmac_key, hmac_key.size());
+ m_hash->update(key, length);
+ m_hash->final(m_ikey.data());
+
+ xor_buf(m_okey.data(), m_ikey.data(), m_hash_output_length);
+
+ for(size_t i = 0; i != m_hash_output_length; ++i)
+ {
+ m_ikey[i] ^= ipad;
+ }
}
else
{
@@ -98,9 +109,12 @@ MessageAuthenticationCode* HMAC::clone() const
/*
* HMAC Constructor
*/
-HMAC::HMAC(HashFunction* hash) : m_hash(hash)
+HMAC::HMAC(HashFunction* hash) :
+ m_hash(hash),
+ m_hash_output_length(m_hash->output_length()),
+ m_hash_block_size(m_hash->hash_block_size())
{
- BOTAN_ARG_CHECK(m_hash->hash_block_size() > 0,
+ BOTAN_ARG_CHECK(m_hash_block_size >= m_hash_output_length,
"HMAC is not compatible with this hash function");
}
diff --git a/src/lib/mac/hmac/hmac.h b/src/lib/mac/hmac/hmac.h
index 800159432..1a6bcd6a0 100644
--- a/src/lib/mac/hmac/hmac.h
+++ b/src/lib/mac/hmac/hmac.h
@@ -23,7 +23,7 @@ class BOTAN_PUBLIC_API(2,0) HMAC final : public MessageAuthenticationCode
std::string name() const override;
MessageAuthenticationCode* clone() const override;
- size_t output_length() const override { return m_hash->output_length(); }
+ size_t output_length() const override;
Key_Length_Specification key_spec() const override;
@@ -41,6 +41,8 @@ class BOTAN_PUBLIC_API(2,0) HMAC final : public MessageAuthenticationCode
std::unique_ptr<HashFunction> m_hash;
secure_vector<uint8_t> m_ikey, m_okey;
+ size_t m_hash_output_length;
+ size_t m_hash_block_size;
};
}