aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/kdf
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/kdf')
-rw-r--r--src/lib/kdf/hkdf/hkdf.cpp45
-rw-r--r--src/lib/kdf/hkdf/hkdf.h55
-rw-r--r--src/lib/kdf/kdf.cpp16
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)