diff options
Diffstat (limited to 'src/lib/kdf')
-rw-r--r-- | src/lib/kdf/hkdf/hkdf.cpp | 45 | ||||
-rw-r--r-- | src/lib/kdf/hkdf/hkdf.h | 55 | ||||
-rw-r--r-- | src/lib/kdf/kdf.cpp | 16 |
3 files changed, 108 insertions, 8 deletions
diff --git a/src/lib/kdf/hkdf/hkdf.cpp b/src/lib/kdf/hkdf/hkdf.cpp index 13d5832d2..f44ed81bd 100644 --- a/src/lib/kdf/hkdf/hkdf.cpp +++ b/src/lib/kdf/hkdf/hkdf.cpp @@ -1,6 +1,7 @@ /* * HKDF * (C) 2013,2015 Jack Lloyd +* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -9,18 +10,54 @@ namespace Botan { -size_t HKDF::kdf(byte out[], size_t out_len, +size_t HKDF::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len, const byte label[], size_t label_len) const { + HKDF_Extract extract(m_prf->clone()); + HKDF_Expand expand(m_prf->clone()); + secure_vector<byte> prk(m_prf->output_length()); + + extract.kdf(prk.data(), prk.size(), secret, secret_len, salt, salt_len, nullptr, 0); + return expand.kdf(key, key_len, prk.data(), prk.size(), nullptr, 0, label, label_len); + } + +size_t HKDF_Extract::kdf(byte key[], size_t key_len, + const byte secret[], size_t secret_len, + const byte salt[], size_t salt_len, + const byte[], size_t) const + { + secure_vector<byte> prk; + if(salt_len == 0) + { + m_prf->set_key(std::vector<byte>(m_prf->output_length())); + } + else + { + m_prf->set_key(salt, salt_len); + } + + m_prf->update(secret, secret_len); + m_prf->final(prk); + + const size_t written = std::min(prk.size(), key_len); + copy_mem(&key[0], prk.data(), written); + return written; + } + +size_t HKDF_Expand::kdf(byte key[], size_t key_len, + const byte secret[], size_t secret_len, + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const + { m_prf->set_key(secret, secret_len); byte counter = 1; secure_vector<byte> h; size_t offset = 0; - while(offset != out_len && counter != 0) + while(offset != key_len && counter != 0) { m_prf->update(h); m_prf->update(label, label_len); @@ -28,8 +65,8 @@ size_t HKDF::kdf(byte out[], size_t out_len, m_prf->update(counter++); m_prf->final(h); - const size_t written = std::min(h.size(), out_len - offset); - copy_mem(&out[offset], h.data(), written); + const size_t written = std::min(h.size(), key_len - offset); + copy_mem(&key[offset], h.data(), written); offset += written; } diff --git a/src/lib/kdf/hkdf/hkdf.h b/src/lib/kdf/hkdf/hkdf.h index 54ecc5283..5ab253420 100644 --- a/src/lib/kdf/hkdf/hkdf.h +++ b/src/lib/kdf/hkdf/hkdf.h @@ -1,6 +1,7 @@ /* * HKDF * (C) 2013,2015 Jack Lloyd +* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -15,9 +16,7 @@ namespace Botan { /** -* HKDF, see RFC 5869 for details. -* This is only the expansion portion of HKDF. -* An appropriate extraction function should be used before. +* HKDF from RFC 5869. */ class BOTAN_DLL HKDF final : public KDF { @@ -31,7 +30,55 @@ class BOTAN_DLL HKDF final : public KDF std::string name() const override { return "HKDF(" + m_prf->name() + ")"; } - size_t kdf(byte out[], size_t out_len, + size_t kdf(byte key[], size_t key_len, + const byte secret[], size_t secret_len, + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; + + private: + MessageAuthenticationCode* m_prf; + }; + +/** +* HKDF Extraction Step from RFC 5869. +*/ +class BOTAN_DLL HKDF_Extract final : public KDF + { + public: + /** + * @param prf MAC algorithm to use + */ + explicit HKDF_Extract(MessageAuthenticationCode* prf) : m_prf(prf) {} + + KDF* clone() const override { return new HKDF_Extract(m_prf->clone()); } + + std::string name() const override { return "HKDF-Extract(" + m_prf->name() + ")"; } + + size_t kdf(byte key[], size_t key_len, + const byte secret[], size_t secret_len, + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; + + private: + std::unique_ptr<MessageAuthenticationCode> m_prf; + }; + +/** +* HKDF Expansion Step from RFC 5869. +*/ +class BOTAN_DLL HKDF_Expand final : public KDF + { + public: + /** + * @param prf MAC algorithm to use + */ + explicit HKDF_Expand(MessageAuthenticationCode* prf) : m_prf(prf) {} + + KDF* clone() const override { return new HKDF_Expand(m_prf->clone()); } + + std::string name() const override { return "HKDF-Expand(" + m_prf->name() + ")"; } + + size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len, const byte label[], size_t label_len) const override; diff --git a/src/lib/kdf/kdf.cpp b/src/lib/kdf/kdf.cpp index 94694c70c..501f81717 100644 --- a/src/lib/kdf/kdf.cpp +++ b/src/lib/kdf/kdf.cpp @@ -77,6 +77,22 @@ std::unique_ptr<KDF> KDF::create(const std::string& algo_spec, return kdf_create_mac_or_hash<HKDF>(req.arg(0)); } } + + if(req.algo_name() == "HKDF_Extract" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + return kdf_create_mac_or_hash<HKDF_Extract>(req.arg(0)); + } + } + + if(req.algo_name() == "HKDF_Expand" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + return kdf_create_mac_or_hash<HKDF_Expand>(req.arg(0)); + } + } #endif #if defined(BOTAN_HAS_KDF2) |