diff options
Diffstat (limited to 'comm/third_party/botan/src/lib/kdf')
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 |