summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/kdf
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/botan/src/lib/kdf
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/botan/src/lib/kdf')
-rw-r--r--comm/third_party/botan/src/lib/kdf/hkdf/hkdf.cpp122
-rw-r--r--comm/third_party/botan/src/lib/kdf/hkdf/hkdf.h117
-rw-r--r--comm/third_party/botan/src/lib/kdf/hkdf/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/kdf/info.txt12
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf.cpp255
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf.h196
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf1/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf1/kdf1.cpp33
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf1/kdf1.h43
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf1_iso18033/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp38
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h43
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf2/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf2/kdf2.cpp38
-rw-r--r--comm/third_party/botan/src/lib/kdf/kdf2/kdf2.h43
-rw-r--r--comm/third_party/botan/src/lib/kdf/prf_tls/info.txt8
-rw-r--r--comm/third_party/botan/src/lib/kdf/prf_tls/prf_tls.cpp96
-rw-r--r--comm/third_party/botan/src/lib/kdf/prf_tls/prf_tls.h70
-rw-r--r--comm/third_party/botan/src/lib/kdf/prf_x942/info.txt8
-rw-r--r--comm/third_party/botan/src/lib/kdf/prf_x942/prf_x942.cpp92
-rw-r--r--comm/third_party/botan/src/lib/kdf/prf_x942/prf_x942.h42
-rw-r--r--comm/third_party/botan/src/lib/kdf/sp800_108/info.txt8
-rw-r--r--comm/third_party/botan/src/lib/kdf/sp800_108/sp800_108.cpp170
-rw-r--r--comm/third_party/botan/src/lib/kdf/sp800_108/sp800_108.h135
-rw-r--r--comm/third_party/botan/src/lib/kdf/sp800_56a/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/kdf/sp800_56a/sp800_56a.cpp98
-rw-r--r--comm/third_party/botan/src/lib/kdf/sp800_56a/sp800_56a.h103
-rw-r--r--comm/third_party/botan/src/lib/kdf/sp800_56c/info.txt8
-rw-r--r--comm/third_party/botan/src/lib/kdf/sp800_56c/sp800_56c.cpp28
-rw-r--r--comm/third_party/botan/src/lib/kdf/sp800_56c/sp800_56c.h61
30 files changed, 1902 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/kdf/hkdf/hkdf.cpp b/comm/third_party/botan/src/lib/kdf/hkdf/hkdf.cpp
new file mode 100644
index 0000000000..0a62648fcd
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/hkdf/hkdf.cpp
@@ -0,0 +1,122 @@
+/*
+* HKDF
+* (C) 2013,2015,2017 Jack Lloyd
+* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/hkdf.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+size_t HKDF::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ HKDF_Extract extract(m_prf->clone());
+ HKDF_Expand expand(m_prf->clone());
+ secure_vector<uint8_t> 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(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t[], size_t) const
+ {
+ secure_vector<uint8_t> prk;
+ if(salt_len == 0)
+ {
+ m_prf->set_key(std::vector<uint8_t>(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);
+ // FIXME: returns truncated output
+ return written;
+ }
+
+size_t HKDF_Expand::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ m_prf->set_key(secret, secret_len);
+
+ uint8_t counter = 1;
+ secure_vector<uint8_t> h;
+ size_t offset = 0;
+
+ while(offset != key_len && counter != 0)
+ {
+ m_prf->update(h);
+ m_prf->update(label, label_len);
+ m_prf->update(salt, salt_len);
+ m_prf->update(counter++);
+ m_prf->final(h);
+
+ const size_t written = std::min(h.size(), key_len - offset);
+ copy_mem(&key[offset], h.data(), written);
+ offset += written;
+ }
+
+ // FIXME: returns truncated output
+ return offset;
+ }
+
+secure_vector<uint8_t>
+hkdf_expand_label(const std::string& hash_fn,
+ const uint8_t secret[], size_t secret_len,
+ const std::string& label,
+ const uint8_t hash_val[], size_t hash_val_len,
+ size_t length)
+ {
+ BOTAN_ARG_CHECK(length <= 0xFFFF, "HKDF-Expand-Label requested output too large");
+ BOTAN_ARG_CHECK(label.size() <= 0xFF, "HKDF-Expand-Label label too long");
+ BOTAN_ARG_CHECK(hash_val_len <= 0xFF, "HKDF-Expand-Label hash too long");
+
+ const uint16_t length16 = static_cast<uint16_t>(length);
+
+ auto mac = MessageAuthenticationCode::create_or_throw("HMAC(" + hash_fn + ")");
+
+ HKDF_Expand hkdf(mac.release());
+
+ secure_vector<uint8_t> output(length16);
+ std::vector<uint8_t> prefix(3 + label.size() + 1);
+
+ prefix[0] = get_byte(0, length16);
+ prefix[1] = get_byte(1, length16);
+ prefix[2] = static_cast<uint8_t>(label.size());
+
+ copy_mem(prefix.data() + 3,
+ cast_char_ptr_to_uint8(label.data()),
+ label.size());
+
+ prefix[3 + label.size()] = static_cast<uint8_t>(hash_val_len);
+
+ /*
+ * We do something a little dirty here to avoid copying the hash_val,
+ * making use of the fact that Botan's KDF interface supports label+salt,
+ * and knowing that our HKDF hashes first param label then param salt.
+ */
+ hkdf.kdf(output.data(), output.size(),
+ secret, secret_len,
+ hash_val, hash_val_len,
+ prefix.data(), prefix.size());
+
+ return output;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/kdf/hkdf/hkdf.h b/comm/third_party/botan/src/lib/kdf/hkdf/hkdf.h
new file mode 100644
index 0000000000..4b1ed2922c
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/hkdf/hkdf.h
@@ -0,0 +1,117 @@
+/*
+* HKDF
+* (C) 2013,2015 Jack Lloyd
+* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_HKDF_H_
+#define BOTAN_HKDF_H_
+
+#include <botan/mac.h>
+#include <botan/kdf.h>
+
+/*
+* The definitions of HKDF, HKDF_Extract, HKDF_Expand will be made internal
+* in the future. However the function hkdf_expand_label will still be defined.
+*/
+//BOTAN_FUTURE_INTERNAL_HEADER(hkdf.h)
+
+namespace Botan {
+
+/**
+* HKDF from RFC 5869.
+*/
+class BOTAN_PUBLIC_API(2,0) HKDF final : public KDF
+ {
+ public:
+ /**
+ * @param prf MAC algorithm to use
+ */
+ explicit HKDF(MessageAuthenticationCode* prf) : m_prf(prf) {}
+
+ KDF* clone() const override { return new HKDF(m_prf->clone()); }
+
+ std::string name() const override { return "HKDF(" + m_prf->name() + ")"; }
+
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_prf;
+ };
+
+/**
+* HKDF Extraction Step from RFC 5869.
+*/
+class BOTAN_PUBLIC_API(2,0) 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(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_prf;
+ };
+
+/**
+* HKDF Expansion Step from RFC 5869.
+*/
+class BOTAN_PUBLIC_API(2,0) 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(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_prf;
+ };
+
+/**
+* HKDF-Expand-Label from TLS 1.3/QUIC
+* @param hash_fn the hash to use
+* @param secret the secret bits
+* @param secret_len the length of secret
+* @param label the full label (no "TLS 1.3, " or "tls13 " prefix
+* is applied)
+* @param hash_val the previous hash value (used for chaining, may be empty)
+* @param hash_val_len the length of hash_val
+* @param length the desired output length
+*/
+secure_vector<uint8_t>
+BOTAN_PUBLIC_API(2,3) hkdf_expand_label(
+ const std::string& hash_fn,
+ const uint8_t secret[], size_t secret_len,
+ const std::string& label,
+ const uint8_t hash_val[], size_t hash_val_len,
+ size_t length);
+
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/kdf/hkdf/info.txt b/comm/third_party/botan/src/lib/kdf/hkdf/info.txt
new file mode 100644
index 0000000000..9cbd420604
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/hkdf/info.txt
@@ -0,0 +1,7 @@
+<defines>
+HKDF -> 20170927
+</defines>
+
+<requires>
+hmac
+</requires>
diff --git a/comm/third_party/botan/src/lib/kdf/info.txt b/comm/third_party/botan/src/lib/kdf/info.txt
new file mode 100644
index 0000000000..81567300f5
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/info.txt
@@ -0,0 +1,12 @@
+<defines>
+KDF_BASE -> 20131128
+</defines>
+
+<requires>
+mac
+hash
+</requires>
+
+<header:public>
+kdf.h
+</header:public>
diff --git a/comm/third_party/botan/src/lib/kdf/kdf.cpp b/comm/third_party/botan/src/lib/kdf/kdf.cpp
new file mode 100644
index 0000000000..7f7d352dbf
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf.cpp
@@ -0,0 +1,255 @@
+/*
+* KDF Retrieval
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/kdf.h>
+#include <botan/mac.h>
+#include <botan/hash.h>
+#include <botan/scan_name.h>
+#include <botan/exceptn.h>
+
+#if defined(BOTAN_HAS_HKDF)
+#include <botan/hkdf.h>
+#endif
+
+#if defined(BOTAN_HAS_KDF1)
+#include <botan/kdf1.h>
+#endif
+
+#if defined(BOTAN_HAS_KDF2)
+#include <botan/kdf2.h>
+#endif
+
+#if defined(BOTAN_HAS_KDF1_18033)
+#include <botan/kdf1_iso18033.h>
+#endif
+
+#if defined(BOTAN_HAS_TLS_V10_PRF) || defined(BOTAN_HAS_TLS_V12_PRF)
+#include <botan/prf_tls.h>
+#endif
+
+#if defined(BOTAN_HAS_X942_PRF)
+#include <botan/prf_x942.h>
+#endif
+
+#if defined(BOTAN_HAS_SP800_108)
+#include <botan/sp800_108.h>
+#endif
+
+#if defined(BOTAN_HAS_SP800_56A)
+#include <botan/sp800_56a.h>
+#endif
+
+#if defined(BOTAN_HAS_SP800_56C)
+#include <botan/sp800_56c.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+template<typename KDF_Type>
+std::unique_ptr<KDF>
+kdf_create_mac_or_hash(const std::string& nm)
+ {
+ if(auto mac = MessageAuthenticationCode::create(nm))
+ return std::unique_ptr<KDF>(new KDF_Type(mac.release()));
+
+ if(auto mac = MessageAuthenticationCode::create("HMAC(" + nm + ")"))
+ return std::unique_ptr<KDF>(new KDF_Type(mac.release()));
+
+ return nullptr;
+ }
+
+}
+
+std::unique_ptr<KDF> KDF::create(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ const SCAN_Name req(algo_spec);
+
+#if defined(BOTAN_HAS_HKDF)
+ if(req.algo_name() == "HKDF" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ 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)
+ if(req.algo_name() == "KDF2" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ if(auto hash = HashFunction::create(req.arg(0)))
+ return std::unique_ptr<KDF>(new KDF2(hash.release()));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_KDF1_18033)
+ if(req.algo_name() == "KDF1-18033" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ if(auto hash = HashFunction::create(req.arg(0)))
+ return std::unique_ptr<KDF>(new KDF1_18033(hash.release()));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_KDF1)
+ if(req.algo_name() == "KDF1" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ if(auto hash = HashFunction::create(req.arg(0)))
+ return std::unique_ptr<KDF>(new KDF1(hash.release()));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_TLS_V10_PRF)
+ if(req.algo_name() == "TLS-PRF" && req.arg_count() == 0)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ auto hmac_md5 = MessageAuthenticationCode::create("HMAC(MD5)");
+ auto hmac_sha1 = MessageAuthenticationCode::create("HMAC(SHA-1)");
+
+ if(hmac_md5 && hmac_sha1)
+ return std::unique_ptr<KDF>(new TLS_PRF(std::move(hmac_md5), std::move(hmac_sha1)));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_TLS_V12_PRF)
+ if(req.algo_name() == "TLS-12-PRF" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ return kdf_create_mac_or_hash<TLS_12_PRF>(req.arg(0));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_X942_PRF)
+ if(req.algo_name() == "X9.42-PRF" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ return std::unique_ptr<KDF>(new X942_PRF(req.arg(0)));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_SP800_108)
+ if(req.algo_name() == "SP800-108-Counter" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ return kdf_create_mac_or_hash<SP800_108_Counter>(req.arg(0));
+ }
+ }
+
+ if(req.algo_name() == "SP800-108-Feedback" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ return kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0));
+ }
+ }
+
+ if(req.algo_name() == "SP800-108-Pipeline" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ return kdf_create_mac_or_hash<SP800_108_Pipeline>(req.arg(0));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_SP800_56A)
+ if(req.algo_name() == "SP800-56A" && req.arg_count() == 1)
+ {
+ if(auto hash = HashFunction::create(req.arg(0)))
+ return std::unique_ptr<KDF>(new SP800_56A_Hash(hash.release()));
+ if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
+ return std::unique_ptr<KDF>(new SP800_56A_HMAC(mac.release()));
+ }
+#endif
+
+#if defined(BOTAN_HAS_SP800_56C)
+ if(req.algo_name() == "SP800-56C" && req.arg_count() == 1)
+ {
+ std::unique_ptr<KDF> exp(kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0)));
+ if(exp)
+ {
+ if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
+ return std::unique_ptr<KDF>(new SP800_56C(mac.release(), exp.release()));
+
+ if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
+ return std::unique_ptr<KDF>(new SP800_56C(mac.release(), exp.release()));
+ }
+ }
+#endif
+
+ BOTAN_UNUSED(req);
+ BOTAN_UNUSED(provider);
+
+ return nullptr;
+ }
+
+//static
+std::unique_ptr<KDF>
+KDF::create_or_throw(const std::string& algo,
+ const std::string& provider)
+ {
+ if(auto kdf = KDF::create(algo, provider))
+ {
+ return kdf;
+ }
+ throw Lookup_Error("KDF", algo, provider);
+ }
+
+std::vector<std::string> KDF::providers(const std::string& algo_spec)
+ {
+ return probe_providers_of<KDF>(algo_spec, { "base" });
+ }
+
+KDF* get_kdf(const std::string& algo_spec)
+ {
+ SCAN_Name request(algo_spec);
+
+ if(request.algo_name() == "Raw")
+ return nullptr; // No KDF
+
+ //return KDF::create_or_throw(algo_spec).release();
+ auto kdf = KDF::create(algo_spec);
+ if(!kdf)
+ throw Algorithm_Not_Found(algo_spec);
+ return kdf.release();
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/kdf/kdf.h b/comm/third_party/botan/src/lib/kdf/kdf.h
new file mode 100644
index 0000000000..dd4cfedf6d
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf.h
@@ -0,0 +1,196 @@
+/*
+* Key Derivation Function interfaces
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_KDF_BASE_H_
+#define BOTAN_KDF_BASE_H_
+
+#include <botan/secmem.h>
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* Key Derivation Function
+*/
+class BOTAN_PUBLIC_API(2,0) KDF
+ {
+ public:
+ virtual ~KDF() = default;
+
+ /**
+ * Create an instance based on a name
+ * If provider is empty then best available is chosen.
+ * @param algo_spec algorithm name
+ * @param provider provider implementation to choose
+ * @return a null pointer if the algo/provider combination cannot be found
+ */
+ static std::unique_ptr<KDF>
+ create(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ /**
+ * Create an instance based on a name, or throw if the
+ * algo/provider combination cannot be found. If provider is
+ * empty then best available is chosen.
+ */
+ static std::unique_ptr<KDF>
+ create_or_throw(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ /**
+ * @return list of available providers for this algorithm, empty if not available
+ */
+ static std::vector<std::string> providers(const std::string& algo_spec);
+
+ /**
+ * @return KDF name
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Derive a key
+ * @param key buffer holding the derived key, must be of length key_len
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param secret_len size of secret in bytes
+ * @param salt a diversifier
+ * @param salt_len size of salt in bytes
+ * @param label purpose for the derived keying material
+ * @param label_len size of label in bytes
+ * @return the derived key
+ */
+ virtual size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const = 0;
+
+ /**
+ * Derive a key
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param secret_len size of secret in bytes
+ * @param salt a diversifier
+ * @param salt_len size of salt in bytes
+ * @param label purpose for the derived keying material
+ * @param label_len size of label in bytes
+ * @return the derived key
+ */
+ secure_vector<uint8_t> derive_key(size_t key_len,
+ const uint8_t secret[],
+ size_t secret_len,
+ const uint8_t salt[],
+ size_t salt_len,
+ const uint8_t label[] = nullptr,
+ size_t label_len = 0) const
+ {
+ secure_vector<uint8_t> key(key_len);
+ key.resize(kdf(key.data(), key.size(), secret, secret_len, salt, salt_len, label, label_len));
+ return key;
+ }
+
+ /**
+ * Derive a key
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param salt a diversifier
+ * @param label purpose for the derived keying material
+ * @return the derived key
+ */
+ secure_vector<uint8_t> derive_key(size_t key_len,
+ const secure_vector<uint8_t>& secret,
+ const std::string& salt = "",
+ const std::string& label = "") const
+ {
+ return derive_key(key_len, secret.data(), secret.size(),
+ cast_char_ptr_to_uint8(salt.data()),
+ salt.length(),
+ cast_char_ptr_to_uint8(label.data()),
+ label.length());
+
+ }
+
+ /**
+ * Derive a key
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param salt a diversifier
+ * @param label purpose for the derived keying material
+ * @return the derived key
+ */
+ template<typename Alloc, typename Alloc2, typename Alloc3>
+ secure_vector<uint8_t> derive_key(size_t key_len,
+ const std::vector<uint8_t, Alloc>& secret,
+ const std::vector<uint8_t, Alloc2>& salt,
+ const std::vector<uint8_t, Alloc3>& label) const
+ {
+ return derive_key(key_len,
+ secret.data(), secret.size(),
+ salt.data(), salt.size(),
+ label.data(), label.size());
+ }
+
+ /**
+ * Derive a key
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param salt a diversifier
+ * @param salt_len size of salt in bytes
+ * @param label purpose for the derived keying material
+ * @return the derived key
+ */
+ secure_vector<uint8_t> derive_key(size_t key_len,
+ const secure_vector<uint8_t>& secret,
+ const uint8_t salt[],
+ size_t salt_len,
+ const std::string& label = "") const
+ {
+ return derive_key(key_len,
+ secret.data(), secret.size(),
+ salt, salt_len,
+ cast_char_ptr_to_uint8(label.data()),
+ label.size());
+ }
+
+ /**
+ * Derive a key
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param secret_len size of secret in bytes
+ * @param salt a diversifier
+ * @param label purpose for the derived keying material
+ * @return the derived key
+ */
+ secure_vector<uint8_t> derive_key(size_t key_len,
+ const uint8_t secret[],
+ size_t secret_len,
+ const std::string& salt = "",
+ const std::string& label = "") const
+ {
+ return derive_key(key_len, secret, secret_len,
+ cast_char_ptr_to_uint8(salt.data()),
+ salt.length(),
+ cast_char_ptr_to_uint8(label.data()),
+ label.length());
+ }
+
+ /**
+ * @return new object representing the same algorithm as *this
+ */
+ virtual KDF* clone() const = 0;
+ };
+
+/**
+* Factory method for KDF (key derivation function)
+* @param algo_spec the name of the KDF to create
+* @return pointer to newly allocated object of that type
+*/
+BOTAN_PUBLIC_API(2,0) KDF* get_kdf(const std::string& algo_spec);
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/kdf/kdf1/info.txt b/comm/third_party/botan/src/lib/kdf/kdf1/info.txt
new file mode 100644
index 0000000000..f88268f93e
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf1/info.txt
@@ -0,0 +1,7 @@
+<defines>
+KDF1 -> 20131128
+</defines>
+
+<requires>
+hash
+</requires>
diff --git a/comm/third_party/botan/src/lib/kdf/kdf1/kdf1.cpp b/comm/third_party/botan/src/lib/kdf/kdf1/kdf1.cpp
new file mode 100644
index 0000000000..3de261c55f
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf1/kdf1.cpp
@@ -0,0 +1,33 @@
+/*
+* KDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/kdf1.h>
+
+namespace Botan {
+
+size_t KDF1::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ m_hash->update(secret, secret_len);
+ m_hash->update(label, label_len);
+ m_hash->update(salt, salt_len);
+
+ if(key_len < m_hash->output_length())
+ {
+ secure_vector<uint8_t> v = m_hash->final();
+ copy_mem(key, v.data(), key_len);
+ return key_len;
+ }
+
+ m_hash->final(key);
+ // FIXME: returns truncated output
+ return m_hash->output_length();
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/kdf/kdf1/kdf1.h b/comm/third_party/botan/src/lib/kdf/kdf1/kdf1.h
new file mode 100644
index 0000000000..388b552517
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf1/kdf1.h
@@ -0,0 +1,43 @@
+/*
+* KDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_KDF1_H_
+#define BOTAN_KDF1_H_
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(kdf1.h)
+
+namespace Botan {
+
+/**
+* KDF1, from IEEE 1363
+*/
+class BOTAN_PUBLIC_API(2,0) KDF1 final : public KDF
+ {
+ public:
+ std::string name() const override { return "KDF1(" + m_hash->name() + ")"; }
+
+ KDF* clone() const override { return new KDF1(m_hash->clone()); }
+
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ /**
+ * @param h hash function to use
+ */
+ explicit KDF1(HashFunction* h) : m_hash(h) {}
+ private:
+ std::unique_ptr<HashFunction> m_hash;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/kdf/kdf1_iso18033/info.txt b/comm/third_party/botan/src/lib/kdf/kdf1_iso18033/info.txt
new file mode 100644
index 0000000000..494b8358b0
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf1_iso18033/info.txt
@@ -0,0 +1,7 @@
+<defines>
+KDF1_18033 -> 20160128
+</defines>
+
+<requires>
+hash
+</requires>
diff --git a/comm/third_party/botan/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp b/comm/third_party/botan/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp
new file mode 100644
index 0000000000..c7699d2f25
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp
@@ -0,0 +1,38 @@
+/*
+* KDF1 from ISO 18033-2
+* (C) 2016 Philipp Weber
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/kdf1_iso18033.h>
+
+namespace Botan {
+
+size_t KDF1_18033::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ uint32_t counter = 0;
+ secure_vector<uint8_t> h;
+
+ size_t offset = 0;
+ while(offset != key_len && counter != 0xFFFFFFFF)
+ {
+ m_hash->update(secret, secret_len);
+ m_hash->update_be(counter++);
+ m_hash->update(label, label_len);
+ m_hash->update(salt, salt_len);
+ m_hash->final(h);
+
+ const size_t added = std::min(h.size(), key_len - offset);
+ copy_mem(&key[offset], h.data(), added);
+ offset += added;
+ }
+
+ // FIXME: returns truncated output
+ return offset;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h b/comm/third_party/botan/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h
new file mode 100644
index 0000000000..5f913057e1
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h
@@ -0,0 +1,43 @@
+/*
+* KDF1 from ISO 18033-2
+* (C) 2016 Philipp Weber
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_KDF1_18033_H_
+#define BOTAN_KDF1_18033_H_
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(kdf1_iso18033.h)
+
+namespace Botan {
+
+/**
+* KDF1, from ISO 18033-2
+*/
+class BOTAN_PUBLIC_API(2,0) KDF1_18033 final : public KDF
+ {
+ public:
+ std::string name() const override { return "KDF1-18033(" + m_hash->name() + ")"; }
+
+ KDF* clone() const override { return new KDF1_18033(m_hash->clone()); }
+
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ /**
+ * @param h hash function to use
+ */
+ explicit KDF1_18033(HashFunction* h) : m_hash(h) {}
+ private:
+ std::unique_ptr<HashFunction> m_hash;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/kdf/kdf2/info.txt b/comm/third_party/botan/src/lib/kdf/kdf2/info.txt
new file mode 100644
index 0000000000..e222a4521f
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf2/info.txt
@@ -0,0 +1,7 @@
+<defines>
+KDF2 -> 20131128
+</defines>
+
+<requires>
+hash
+</requires>
diff --git a/comm/third_party/botan/src/lib/kdf/kdf2/kdf2.cpp b/comm/third_party/botan/src/lib/kdf/kdf2/kdf2.cpp
new file mode 100644
index 0000000000..4e3bb55832
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf2/kdf2.cpp
@@ -0,0 +1,38 @@
+/*
+* KDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/kdf2.h>
+
+namespace Botan {
+
+size_t KDF2::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ uint32_t counter = 1;
+ secure_vector<uint8_t> h;
+
+ size_t offset = 0;
+ while(offset != key_len && counter != 0)
+ {
+ m_hash->update(secret, secret_len);
+ m_hash->update_be(counter++);
+ m_hash->update(label, label_len);
+ m_hash->update(salt, salt_len);
+ m_hash->final(h);
+
+ const size_t added = std::min(h.size(), key_len - offset);
+ copy_mem(&key[offset], h.data(), added);
+ offset += added;
+ }
+
+ // FIXME: returns truncated output
+ return offset;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/kdf/kdf2/kdf2.h b/comm/third_party/botan/src/lib/kdf/kdf2/kdf2.h
new file mode 100644
index 0000000000..43abbf087e
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/kdf2/kdf2.h
@@ -0,0 +1,43 @@
+/*
+* KDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_KDF2_H_
+#define BOTAN_KDF2_H_
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(kdf2.h)
+
+namespace Botan {
+
+/**
+* KDF2, from IEEE 1363
+*/
+class BOTAN_PUBLIC_API(2,0) KDF2 final : public KDF
+ {
+ public:
+ std::string name() const override { return "KDF2(" + m_hash->name() + ")"; }
+
+ KDF* clone() const override { return new KDF2(m_hash->clone()); }
+
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ /**
+ * @param h hash function to use
+ */
+ explicit KDF2(HashFunction* h) : m_hash(h) {}
+ private:
+ std::unique_ptr<HashFunction> m_hash;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/kdf/prf_tls/info.txt b/comm/third_party/botan/src/lib/kdf/prf_tls/info.txt
new file mode 100644
index 0000000000..3d76e4b4cb
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/prf_tls/info.txt
@@ -0,0 +1,8 @@
+<defines>
+TLS_V10_PRF -> 20131128
+TLS_V12_PRF -> 20131128
+</defines>
+
+<requires>
+hmac
+</requires>
diff --git a/comm/third_party/botan/src/lib/kdf/prf_tls/prf_tls.cpp b/comm/third_party/botan/src/lib/kdf/prf_tls/prf_tls.cpp
new file mode 100644
index 0000000000..c98c7d3516
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/prf_tls/prf_tls.cpp
@@ -0,0 +1,96 @@
+/*
+* TLS v1.0 and v1.2 PRFs
+* (C) 2004-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/prf_tls.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+TLS_PRF::TLS_PRF() :
+ TLS_PRF(MessageAuthenticationCode::create_or_throw("HMAC(MD5)"),
+ MessageAuthenticationCode::create_or_throw("HMAC(SHA-1)"))
+ {
+ }
+
+namespace {
+
+/*
+* TLS PRF P_hash function
+*/
+void P_hash(uint8_t out[], size_t out_len,
+ MessageAuthenticationCode& mac,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len)
+ {
+ try
+ {
+ mac.set_key(secret, secret_len);
+ }
+ catch(Invalid_Key_Length&)
+ {
+ throw Internal_Error("The premaster secret of " +
+ std::to_string(secret_len) +
+ " bytes is too long for the PRF");
+ }
+
+ secure_vector<uint8_t> A(salt, salt + salt_len);
+ secure_vector<uint8_t> h;
+
+ size_t offset = 0;
+
+ while(offset != out_len)
+ {
+ A = mac.process(A);
+
+ mac.update(A);
+ mac.update(salt, salt_len);
+ mac.final(h);
+
+ const size_t writing = std::min(h.size(), out_len - offset);
+ xor_buf(&out[offset], h.data(), writing);
+ offset += writing;
+ }
+ }
+
+}
+
+size_t TLS_PRF::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ const size_t S1_len = (secret_len + 1) / 2,
+ S2_len = (secret_len + 1) / 2;
+ const uint8_t* S1 = secret;
+ const uint8_t* S2 = secret + (secret_len - S2_len);
+ secure_vector<uint8_t> msg;
+
+ msg.reserve(label_len + salt_len);
+ msg += std::make_pair(label, label_len);
+ msg += std::make_pair(salt, salt_len);
+
+ P_hash(key, key_len, *m_hmac_md5, S1, S1_len, msg.data(), msg.size());
+ P_hash(key, key_len, *m_hmac_sha1, S2, S2_len, msg.data(), msg.size());
+ return key_len;
+ }
+
+size_t TLS_12_PRF::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ secure_vector<uint8_t> msg;
+
+ msg.reserve(label_len + salt_len);
+ msg += std::make_pair(label, label_len);
+ msg += std::make_pair(salt, salt_len);
+
+ P_hash(key, key_len, *m_mac, secret, secret_len, msg.data(), msg.size());
+ return key_len;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/kdf/prf_tls/prf_tls.h b/comm/third_party/botan/src/lib/kdf/prf_tls/prf_tls.h
new file mode 100644
index 0000000000..603086a7e9
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/prf_tls/prf_tls.h
@@ -0,0 +1,70 @@
+/*
+* TLS v1.0 and v1.2 PRFs
+* (C) 2004-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_TLS_PRF_H_
+#define BOTAN_TLS_PRF_H_
+
+#include <botan/kdf.h>
+#include <botan/mac.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(prf_tls.h)
+
+namespace Botan {
+
+/**
+* PRF used in TLS 1.0/1.1
+*/
+class BOTAN_PUBLIC_API(2,0) TLS_PRF final : public KDF
+ {
+ public:
+ std::string name() const override { return "TLS-PRF"; }
+
+ KDF* clone() const override { return new TLS_PRF; }
+
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ TLS_PRF(std::unique_ptr<MessageAuthenticationCode> hmac_md5,
+ std::unique_ptr<MessageAuthenticationCode> hmac_sha1) :
+ m_hmac_md5(std::move(hmac_md5)),
+ m_hmac_sha1(std::move(hmac_sha1))
+ {}
+
+ TLS_PRF();
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_hmac_md5;
+ std::unique_ptr<MessageAuthenticationCode> m_hmac_sha1;
+ };
+
+/**
+* PRF used in TLS 1.2
+*/
+class BOTAN_PUBLIC_API(2,0) TLS_12_PRF final : public KDF
+ {
+ public:
+ std::string name() const override { return "TLS-12-PRF(" + m_mac->name() + ")"; }
+
+ KDF* clone() const override { return new TLS_12_PRF(m_mac->clone()); }
+
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ /**
+ * @param mac MAC algorithm to use
+ */
+ explicit TLS_12_PRF(MessageAuthenticationCode* mac) : m_mac(mac) {}
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_mac;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/kdf/prf_x942/info.txt b/comm/third_party/botan/src/lib/kdf/prf_x942/info.txt
new file mode 100644
index 0000000000..8226433654
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/prf_x942/info.txt
@@ -0,0 +1,8 @@
+<defines>
+X942_PRF -> 20131128
+</defines>
+
+<requires>
+asn1
+sha1
+</requires>
diff --git a/comm/third_party/botan/src/lib/kdf/prf_x942/prf_x942.cpp b/comm/third_party/botan/src/lib/kdf/prf_x942/prf_x942.cpp
new file mode 100644
index 0000000000..4a4a3a7f09
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/prf_x942/prf_x942.cpp
@@ -0,0 +1,92 @@
+/*
+* X9.42 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/prf_x942.h>
+#include <botan/der_enc.h>
+#include <botan/hash.h>
+#include <botan/loadstor.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Encode an integer as an OCTET STRING
+*/
+std::vector<uint8_t> encode_x942_int(uint32_t n)
+ {
+ uint8_t n_buf[4] = { 0 };
+ store_be(n, n_buf);
+
+ std::vector<uint8_t> output;
+ DER_Encoder(output).encode(n_buf, 4, OCTET_STRING);
+ return output;
+ }
+
+}
+
+size_t X942_PRF::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-160"));
+
+ secure_vector<uint8_t> h;
+ secure_vector<uint8_t> in;
+ size_t offset = 0;
+ uint32_t counter = 1;
+
+ in.reserve(salt_len + label_len);
+ in += std::make_pair(label,label_len);
+ in += std::make_pair(salt,salt_len);
+
+ while(offset != key_len && counter)
+ {
+ hash->update(secret, secret_len);
+
+ hash->update(
+ DER_Encoder().start_cons(SEQUENCE)
+
+ .start_cons(SEQUENCE)
+ .encode(m_key_wrap_oid)
+ .raw_bytes(encode_x942_int(counter))
+ .end_cons()
+
+ .encode_if(salt_len != 0,
+ DER_Encoder()
+ .start_explicit(0)
+ .encode(in, OCTET_STRING)
+ .end_explicit()
+ )
+
+ .start_explicit(2)
+ .raw_bytes(encode_x942_int(static_cast<uint32_t>(8 * key_len)))
+ .end_explicit()
+
+ .end_cons().get_contents()
+ );
+
+ hash->final(h);
+ const size_t copied = std::min(h.size(), key_len - offset);
+ copy_mem(&key[offset], h.data(), copied);
+ offset += copied;
+
+ ++counter;
+ }
+
+ // FIXME: returns truncated output
+ return offset;
+ }
+
+std::string X942_PRF::name() const
+ {
+ return "X9.42-PRF(" + m_key_wrap_oid.to_formatted_string() + ")";
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/kdf/prf_x942/prf_x942.h b/comm/third_party/botan/src/lib/kdf/prf_x942/prf_x942.h
new file mode 100644
index 0000000000..98af7e069b
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/prf_x942/prf_x942.h
@@ -0,0 +1,42 @@
+/*
+* X9.42 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ANSI_X942_PRF_H_
+#define BOTAN_ANSI_X942_PRF_H_
+
+#include <botan/kdf.h>
+#include <botan/asn1_obj.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(prf_x942.h)
+
+namespace Botan {
+
+/**
+* PRF from ANSI X9.42
+*/
+class BOTAN_PUBLIC_API(2,0) X942_PRF final : public KDF
+ {
+ public:
+ std::string name() const override;
+
+ KDF* clone() const override { return new X942_PRF(m_key_wrap_oid); }
+
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ explicit X942_PRF(const std::string& oid) : m_key_wrap_oid(OID::from_string(oid)) {}
+
+ explicit X942_PRF(const OID& oid) : m_key_wrap_oid(oid) {}
+ private:
+ OID m_key_wrap_oid;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/kdf/sp800_108/info.txt b/comm/third_party/botan/src/lib/kdf/sp800_108/info.txt
new file mode 100644
index 0000000000..864a7fb9c3
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/sp800_108/info.txt
@@ -0,0 +1,8 @@
+<defines>
+SP800_108 -> 20160128
+</defines>
+
+<requires>
+mac
+hmac
+</requires>
diff --git a/comm/third_party/botan/src/lib/kdf/sp800_108/sp800_108.cpp b/comm/third_party/botan/src/lib/kdf/sp800_108/sp800_108.cpp
new file mode 100644
index 0000000000..909e8d47d5
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/sp800_108/sp800_108.cpp
@@ -0,0 +1,170 @@
+/*
+* KDFs defined in NIST SP 800-108
+* (C) 2016 Kai Michaelis
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/sp800_108.h>
+#include <botan/loadstor.h>
+#include <botan/exceptn.h>
+#include <iterator>
+
+namespace Botan {
+
+size_t SP800_108_Counter::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ const std::size_t prf_len = m_prf->output_length();
+
+ const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
+
+ if(blocks_required > 0xFFFFFFFF)
+ throw Invalid_Argument("SP800_108_Counter output size too large");
+
+ const uint8_t delim = 0;
+ const uint32_t length = static_cast<uint32_t>(key_len * 8);
+
+ uint8_t *p = key;
+ uint32_t counter = 1;
+ uint8_t be_len[4] = { 0 };
+ secure_vector<uint8_t> tmp;
+
+ store_be(length, be_len);
+ m_prf->set_key(secret, secret_len);
+
+ while(p < key + key_len)
+ {
+ const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
+ uint8_t be_cnt[4] = { 0 };
+
+ store_be(counter, be_cnt);
+
+ m_prf->update(be_cnt,4);
+ m_prf->update(label,label_len);
+ m_prf->update(delim);
+ m_prf->update(salt,salt_len);
+ m_prf->update(be_len,4);
+ m_prf->final(tmp);
+
+ copy_mem(p, tmp.data(), to_copy);
+ p += to_copy;
+
+ ++counter;
+ BOTAN_ASSERT(counter != 0, "No counter overflow");
+ }
+
+ return key_len;
+ }
+
+size_t SP800_108_Feedback::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ const uint32_t length = static_cast<uint32_t>(key_len * 8);
+ const std::size_t prf_len = m_prf->output_length();
+ const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0);
+ const uint8_t delim = 0;
+
+ const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
+
+ if(blocks_required > 0xFFFFFFFF)
+ throw Invalid_Argument("SP800_108_Feedback output size too large");
+
+ uint8_t *p = key;
+ uint32_t counter = 1;
+ uint8_t be_len[4] = { 0 };
+ secure_vector< uint8_t > prev(salt, salt + iv_len);
+ secure_vector< uint8_t > ctx(salt + iv_len, salt + salt_len);
+
+ store_be(length, be_len);
+ m_prf->set_key(secret, secret_len);
+
+ while(p < key + key_len)
+ {
+ const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
+ uint8_t be_cnt[4] = { 0 };
+
+ store_be(counter, be_cnt);
+
+ m_prf->update(prev);
+ m_prf->update(be_cnt,4);
+ m_prf->update(label,label_len);
+ m_prf->update(delim);
+ m_prf->update(ctx);
+ m_prf->update(be_len,4);
+ m_prf->final(prev);
+
+ copy_mem(p, prev.data(), to_copy);
+ p += to_copy;
+
+ ++counter;
+
+ BOTAN_ASSERT(counter != 0, "No overflow");
+ }
+
+ return key_len;
+ }
+
+size_t SP800_108_Pipeline::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ const uint32_t length = static_cast<uint32_t>(key_len * 8);
+ const std::size_t prf_len = m_prf->output_length();
+ const uint8_t delim = 0;
+
+ const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
+
+ if(blocks_required > 0xFFFFFFFF)
+ throw Invalid_Argument("SP800_108_Feedback output size too large");
+
+ uint8_t *p = key;
+ uint32_t counter = 1;
+ uint8_t be_len[4] = { 0 };
+ secure_vector<uint8_t> ai, ki;
+
+ store_be(length, be_len);
+ m_prf->set_key(secret,secret_len);
+
+ // A(0)
+ std::copy(label,label + label_len,std::back_inserter(ai));
+ ai.emplace_back(delim);
+ std::copy(salt,salt + salt_len,std::back_inserter(ai));
+ std::copy(be_len,be_len + 4,std::back_inserter(ai));
+
+ while(p < key + key_len)
+ {
+ // A(i)
+ m_prf->update(ai);
+ m_prf->final(ai);
+
+ // K(i)
+ const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
+ uint8_t be_cnt[4] = { 0 };
+
+ store_be(counter, be_cnt);
+
+ m_prf->update(ai);
+ m_prf->update(be_cnt,4);
+ m_prf->update(label, label_len);
+ m_prf->update(delim);
+ m_prf->update(salt, salt_len);
+ m_prf->update(be_len,4);
+ m_prf->final(ki);
+
+ copy_mem(p, ki.data(), to_copy);
+ p += to_copy;
+
+ ++counter;
+
+ BOTAN_ASSERT(counter != 0, "No overflow");
+ }
+
+ return key_len;
+ }
+}
diff --git a/comm/third_party/botan/src/lib/kdf/sp800_108/sp800_108.h b/comm/third_party/botan/src/lib/kdf/sp800_108/sp800_108.h
new file mode 100644
index 0000000000..46f734e8ea
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/sp800_108/sp800_108.h
@@ -0,0 +1,135 @@
+/*
+* KDFs defined in NIST SP 800-108
+* (C) 2016 Kai Michaelis
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_SP800_108_H_
+#define BOTAN_SP800_108_H_
+
+#include <botan/kdf.h>
+#include <botan/mac.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(sp800_108.h)
+
+namespace Botan {
+
+/**
+ * NIST SP 800-108 KDF in Counter Mode (5.1)
+ */
+class BOTAN_PUBLIC_API(2,0) SP800_108_Counter final : public KDF
+ {
+ public:
+ std::string name() const override { return "SP800-108-Counter(" + m_prf->name() + ")"; }
+
+ KDF* clone() const override { return new SP800_108_Counter(m_prf->clone()); }
+
+ /**
+ * Derive a key using the SP800-108 KDF in Counter mode.
+ *
+ * The implementation hard codes the length of [L]_2
+ * and [i]_2 (the value r) to 32 bits.
+ *
+ * @param key resulting keying material
+ * @param key_len the desired output length in bytes
+ * @param secret K_I
+ * @param secret_len size of K_I in bytes
+ * @param salt Context
+ * @param salt_len size of Context in bytes
+ * @param label Label
+ * @param label_len size of Label in bytes
+ *
+ * @throws Invalid_Argument key_len > 2^32
+ */
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ /**
+ * @param mac MAC algorithm to use
+ */
+ explicit SP800_108_Counter(MessageAuthenticationCode* mac) : m_prf(mac) {}
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_prf;
+ };
+
+/**
+ * NIST SP 800-108 KDF in Feedback Mode (5.2)
+ */
+class BOTAN_PUBLIC_API(2,0) SP800_108_Feedback final : public KDF
+ {
+ public:
+ std::string name() const override { return "SP800-108-Feedback(" + m_prf->name() + ")"; }
+
+ KDF* clone() const override { return new SP800_108_Feedback(m_prf->clone()); }
+
+ /**
+ * Derive a key using the SP800-108 KDF in Feedback mode.
+ *
+ * The implementation uses the optional counter i and hard
+ * codes the length of [L]_2 and [i]_2 (the value r) to 32 bits.
+ *
+ * @param key resulting keying material
+ * @param key_len the desired output length in bytes
+ * @param secret K_I
+ * @param secret_len size of K_I in bytes
+ * @param salt IV || Context
+ * @param salt_len size of Context plus IV in bytes
+ * @param label Label
+ * @param label_len size of Label in bytes
+ *
+ * @throws Invalid_Argument key_len > 2^32
+ */
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ explicit SP800_108_Feedback(MessageAuthenticationCode* mac) : m_prf(mac) {}
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_prf;
+ };
+
+/**
+ * NIST SP 800-108 KDF in Double Pipeline Mode (5.3)
+ */
+class BOTAN_PUBLIC_API(2,0) SP800_108_Pipeline final : public KDF
+ {
+ public:
+ std::string name() const override { return "SP800-108-Pipeline(" + m_prf->name() + ")"; }
+
+ KDF* clone() const override { return new SP800_108_Pipeline(m_prf->clone()); }
+
+ /**
+ * Derive a key using the SP800-108 KDF in Double Pipeline mode.
+ *
+ * The implementation uses the optional counter i and hard
+ * codes the length of [L]_2 and [i]_2 (the value r) to 32 bits.
+ *
+ * @param key resulting keying material
+ * @param key_len the desired output length in bytes
+ * @param secret K_I
+ * @param secret_len size of K_I in bytes
+ * @param salt Context
+ * @param salt_len size of Context in bytes
+ * @param label Label
+ * @param label_len size of Label in bytes
+ *
+ * @throws Invalid_Argument key_len > 2^32
+ */
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ explicit SP800_108_Pipeline(MessageAuthenticationCode* mac) : m_prf(mac) {}
+
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_prf;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/kdf/sp800_56a/info.txt b/comm/third_party/botan/src/lib/kdf/sp800_56a/info.txt
new file mode 100644
index 0000000000..d8ef51673b
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/sp800_56a/info.txt
@@ -0,0 +1,7 @@
+<defines>
+SP800_56A -> 20170501
+</defines>
+
+<requires>
+hmac
+</requires>
diff --git a/comm/third_party/botan/src/lib/kdf/sp800_56a/sp800_56a.cpp b/comm/third_party/botan/src/lib/kdf/sp800_56a/sp800_56a.cpp
new file mode 100644
index 0000000000..8e9bcf8560
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/sp800_56a/sp800_56a.cpp
@@ -0,0 +1,98 @@
+/*
+* KDF defined in NIST SP 800-56a (Approved Alternative 1)
+*
+* (C) 2017 Ribose Inc. Written by Krzysztof Kwiatkowski.
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/sp800_56a.h>
+#include <botan/scan_name.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace {
+
+template<class AuxiliaryFunction_t>
+size_t SP800_56A_kdf(
+ AuxiliaryFunction_t& auxfunc,
+ uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t label[], size_t label_len)
+ {
+ const uint64_t kRepsUpperBound = (1ULL << 32);
+
+ const size_t digest_len = auxfunc.output_length();
+
+ const size_t reps = key_len / digest_len + ((key_len % digest_len) ? 1 : 0);
+
+ if (reps >= kRepsUpperBound)
+ {
+ // See SP-800-56A, point 5.8.1
+ throw Invalid_Argument("SP800-56A KDF requested output too large");
+ }
+
+ uint32_t counter = 1;
+ secure_vector<uint8_t> result;
+ for(size_t i = 0; i < reps; i++)
+ {
+ auxfunc.update_be(counter++);
+ auxfunc.update(secret, secret_len);
+ auxfunc.update(label, label_len);
+ auxfunc.final(result);
+
+ const size_t offset = digest_len * i;
+ const size_t len = std::min(result.size(), key_len - offset);
+ copy_mem(&key[offset], result.data(), len);
+ }
+
+ return key_len;
+ }
+
+}
+
+size_t SP800_56A_Hash::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ /*
+ * TODO: should we reject a non-empty salt with an exception?
+ * Ignoring the salt seems quite dangerous to applications which
+ * don't expect it.
+ */
+ BOTAN_UNUSED(salt, salt_len);
+
+ return SP800_56A_kdf(*m_hash, key, key_len, secret, secret_len, label, label_len);
+ }
+
+SP800_56A_HMAC::SP800_56A_HMAC(MessageAuthenticationCode* mac) : m_mac(mac)
+ {
+ // TODO: we need a MessageAuthenticationCode::is_hmac
+ const SCAN_Name req(m_mac->name());
+ if(req.algo_name() != "HMAC")
+ {
+ throw Algorithm_Not_Found("Only HMAC can be used with KDF SP800-56A");
+ }
+ }
+
+size_t SP800_56A_HMAC::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ /*
+ * SP 800-56A specifies if the salt is empty then a block of zeros
+ * equal to the hash's underlying block size are used. However this
+ * is equivalent to setting a zero-length key, so the same call
+ * works for either case.
+ */
+ m_mac->set_key(salt, salt_len);
+
+ return SP800_56A_kdf(*m_mac, key, key_len, secret, secret_len, label, label_len);
+ }
+
+
+
+}
diff --git a/comm/third_party/botan/src/lib/kdf/sp800_56a/sp800_56a.h b/comm/third_party/botan/src/lib/kdf/sp800_56a/sp800_56a.h
new file mode 100644
index 0000000000..e83f117e2e
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/sp800_56a/sp800_56a.h
@@ -0,0 +1,103 @@
+/*
+* KDF defined in NIST SP 800-56a revision 2 (Single-step key-derivation function)
+*
+* (C) 2017 Ribose Inc. Written by Krzysztof Kwiatkowski.
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_SP800_56A_H_
+#define BOTAN_SP800_56A_H_
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(sp800_56a.h)
+
+namespace Botan {
+
+/**
+ * NIST SP 800-56A KDF using hash function
+ * @warning This KDF ignores the provided salt value
+ */
+class BOTAN_PUBLIC_API(2,2) SP800_56A_Hash final : public KDF
+ {
+ public:
+ std::string name() const override { return "SP800-56A(" + m_hash->name() + ")"; }
+
+ KDF* clone() const override { return new SP800_56A_Hash(m_hash->clone()); }
+
+ /**
+ * Derive a key using the SP800-56A KDF.
+ *
+ * The implementation hard codes the context value for the
+ * expansion step to the empty string.
+ *
+ * @param key derived keying material K_M
+ * @param key_len the desired output length in bytes
+ * @param secret shared secret Z
+ * @param secret_len size of Z in bytes
+ * @param salt ignored
+ * @param salt_len ignored
+ * @param label label for the expansion step
+ * @param label_len size of label in bytes
+ *
+ * @throws Invalid_Argument key_len > 2^32
+ */
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ /**
+ * @param hash the hash function to use as the auxiliary function
+ */
+ explicit SP800_56A_Hash(HashFunction* hash) : m_hash(hash) {}
+ private:
+ std::unique_ptr<HashFunction> m_hash;
+ };
+
+/**
+ * NIST SP 800-56A KDF using HMAC
+ */
+class BOTAN_PUBLIC_API(2,2) SP800_56A_HMAC final : public KDF
+ {
+ public:
+ std::string name() const override { return "SP800-56A(" + m_mac->name() + ")"; }
+
+ KDF* clone() const override { return new SP800_56A_HMAC(m_mac->clone()); }
+
+ /**
+ * Derive a key using the SP800-56A KDF.
+ *
+ * The implementation hard codes the context value for the
+ * expansion step to the empty string.
+ *
+ * @param key derived keying material K_M
+ * @param key_len the desired output length in bytes
+ * @param secret shared secret Z
+ * @param secret_len size of Z in bytes
+ * @param salt ignored
+ * @param salt_len ignored
+ * @param label label for the expansion step
+ * @param label_len size of label in bytes
+ *
+ * @throws Invalid_Argument key_len > 2^32 or MAC is not a HMAC
+ */
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ /**
+ * @param mac the HMAC to use as the auxiliary function
+ */
+ explicit SP800_56A_HMAC(MessageAuthenticationCode* mac);
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_mac;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/kdf/sp800_56c/info.txt b/comm/third_party/botan/src/lib/kdf/sp800_56c/info.txt
new file mode 100644
index 0000000000..e598e88454
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/sp800_56c/info.txt
@@ -0,0 +1,8 @@
+<defines>
+SP800_56C -> 20160211
+</defines>
+
+<requires>
+sp800_108
+hmac
+</requires>
diff --git a/comm/third_party/botan/src/lib/kdf/sp800_56c/sp800_56c.cpp b/comm/third_party/botan/src/lib/kdf/sp800_56c/sp800_56c.cpp
new file mode 100644
index 0000000000..c0a1a1f689
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/sp800_56c/sp800_56c.cpp
@@ -0,0 +1,28 @@
+/*
+* KDF defined in NIST SP 800-56c
+* (C) 2016 Kai Michaelis
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/sp800_56c.h>
+
+namespace Botan {
+
+size_t SP800_56C::kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+ {
+ // Randomness Extraction
+ secure_vector<uint8_t> k_dk;
+
+ m_prf->set_key(salt, salt_len);
+ m_prf->update(secret, secret_len);
+ m_prf->final(k_dk);
+
+ // Key Expansion
+ return m_exp->kdf(key, key_len, k_dk.data(), k_dk.size(), nullptr, 0, label, label_len);
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/kdf/sp800_56c/sp800_56c.h b/comm/third_party/botan/src/lib/kdf/sp800_56c/sp800_56c.h
new file mode 100644
index 0000000000..bdbdfcd9e1
--- /dev/null
+++ b/comm/third_party/botan/src/lib/kdf/sp800_56c/sp800_56c.h
@@ -0,0 +1,61 @@
+/*
+* KDF defined in NIST SP 800-56c
+* (C) 2016 Kai Michaelis
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_SP800_56C_H_
+#define BOTAN_SP800_56C_H_
+
+#include <botan/kdf.h>
+#include <botan/mac.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(sp800_56c.h)
+
+namespace Botan {
+
+/**
+ * NIST SP 800-56C KDF
+ */
+class BOTAN_PUBLIC_API(2,0) SP800_56C final : public KDF
+ {
+ public:
+ std::string name() const override { return "SP800-56C(" + m_prf->name() + ")"; }
+
+ KDF* clone() const override { return new SP800_56C(m_prf->clone(), m_exp->clone()); }
+
+ /**
+ * Derive a key using the SP800-56C KDF.
+ *
+ * The implementation hard codes the context value for the
+ * expansion step to the empty string.
+ *
+ * @param key derived keying material K_M
+ * @param key_len the desired output length in bytes
+ * @param secret shared secret Z
+ * @param secret_len size of Z in bytes
+ * @param salt salt s of the extraction step
+ * @param salt_len size of s in bytes
+ * @param label label for the expansion step
+ * @param label_len size of label in bytes
+ *
+ * @throws Invalid_Argument key_len > 2^32
+ */
+ size_t kdf(uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const override;
+
+ /**
+ * @param mac MAC algorithm used for randomness extraction
+ * @param exp KDF used for key expansion
+ */
+ SP800_56C(MessageAuthenticationCode* mac, KDF* exp) : m_prf(mac), m_exp(exp) {}
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_prf;
+ std::unique_ptr<KDF> m_exp;
+ };
+}
+
+#endif