diff options
Diffstat (limited to 'src/lib/kdf')
-rw-r--r-- | src/lib/kdf/hkdf/hkdf.cpp | 4 | ||||
-rw-r--r-- | src/lib/kdf/hkdf/hkdf.h | 3 | ||||
-rw-r--r-- | src/lib/kdf/kdf.h | 45 | ||||
-rw-r--r-- | src/lib/kdf/kdf1/kdf1.cpp | 4 | ||||
-rw-r--r-- | src/lib/kdf/kdf1/kdf1.h | 3 | ||||
-rw-r--r-- | src/lib/kdf/kdf2/kdf2.cpp | 4 | ||||
-rw-r--r-- | src/lib/kdf/kdf2/kdf2.h | 3 | ||||
-rw-r--r-- | src/lib/kdf/prf_tls/prf_tls.cpp | 23 | ||||
-rw-r--r-- | src/lib/kdf/prf_tls/prf_tls.h | 6 | ||||
-rw-r--r-- | src/lib/kdf/prf_x942/prf_x942.cpp | 10 | ||||
-rw-r--r-- | src/lib/kdf/prf_x942/prf_x942.h | 3 | ||||
-rw-r--r-- | src/lib/kdf/sp800_108/sp800_108.cpp | 43 | ||||
-rw-r--r-- | src/lib/kdf/sp800_108/sp800_108.h | 60 | ||||
-rw-r--r-- | src/lib/kdf/sp800_56c/sp800_56c.cpp | 7 | ||||
-rw-r--r-- | src/lib/kdf/sp800_56c/sp800_56c.h | 20 |
15 files changed, 198 insertions, 40 deletions
diff --git a/src/lib/kdf/hkdf/hkdf.cpp b/src/lib/kdf/hkdf/hkdf.cpp index 6f83853f9..56dc72f09 100644 --- a/src/lib/kdf/hkdf/hkdf.cpp +++ b/src/lib/kdf/hkdf/hkdf.cpp @@ -22,7 +22,8 @@ HKDF* HKDF::make(const Spec& spec) size_t HKDF::kdf(byte out[], size_t out_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { m_prf->set_key(secret, secret_len); @@ -33,6 +34,7 @@ size_t HKDF::kdf(byte out[], size_t out_len, while(offset != out_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); diff --git a/src/lib/kdf/hkdf/hkdf.h b/src/lib/kdf/hkdf/hkdf.h index 3e3e2b73a..1dba82ee2 100644 --- a/src/lib/kdf/hkdf/hkdf.h +++ b/src/lib/kdf/hkdf/hkdf.h @@ -31,7 +31,8 @@ class BOTAN_DLL HKDF final : public KDF size_t kdf(byte out[], size_t out_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; private: std::unique_ptr<MessageAuthenticationCode> m_prf; diff --git a/src/lib/kdf/kdf.h b/src/lib/kdf/kdf.h index 88b50c8b8..3c8a7a013 100644 --- a/src/lib/kdf/kdf.h +++ b/src/lib/kdf/kdf.h @@ -40,7 +40,8 @@ class BOTAN_DLL KDF virtual size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const = 0; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const = 0; /** @@ -50,15 +51,19 @@ class BOTAN_DLL KDF * @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 */ secure_vector<byte> derive_key(size_t key_len, const byte secret[], size_t secret_len, const byte salt[], - size_t salt_len) const + size_t salt_len, + const byte label[] = nullptr, + size_t label_len = 0) const { secure_vector<byte> key(key_len); - key.resize(kdf(key.data(), key.size(), secret, secret_len, salt, salt_len)); + key.resize(kdf(key.data(), key.size(), secret, secret_len, salt, salt_len, label, label_len)); return key; } @@ -67,14 +72,19 @@ class BOTAN_DLL KDF * @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 */ secure_vector<byte> derive_key(size_t key_len, const secure_vector<byte>& secret, - const std::string& salt = "") const + const std::string& salt = "", + const std::string& label = "") const { return derive_key(key_len, secret.data(), secret.size(), reinterpret_cast<const byte*>(salt.data()), - salt.length()); + salt.length(), + reinterpret_cast<const byte*>(label.data()), + label.length()); + } /** @@ -82,15 +92,18 @@ class BOTAN_DLL KDF * @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 */ - template<typename Alloc, typename Alloc2> + template<typename Alloc, typename Alloc2, typename Alloc3> secure_vector<byte> derive_key(size_t key_len, const std::vector<byte, Alloc>& secret, - const std::vector<byte, Alloc2>& salt) const + const std::vector<byte, Alloc2>& salt, + const std::vector<byte, Alloc3>& label) const { return derive_key(key_len, secret.data(), secret.size(), - salt.data(), salt.size()); + salt.data(), salt.size(), + label.data(), label.size()); } /** @@ -99,15 +112,19 @@ class BOTAN_DLL KDF * @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 */ secure_vector<byte> derive_key(size_t key_len, const secure_vector<byte>& secret, const byte salt[], - size_t salt_len) const + size_t salt_len, + const std::string& label = "") const { return derive_key(key_len, secret.data(), secret.size(), - salt, salt_len); + salt, salt_len, + reinterpret_cast<const byte*>(label.data()), + label.size()); } /** @@ -116,15 +133,19 @@ class BOTAN_DLL KDF * @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 */ secure_vector<byte> derive_key(size_t key_len, const byte secret[], size_t secret_len, - const std::string& salt = "") const + const std::string& salt = "", + const std::string& label = "") const { return derive_key(key_len, secret, secret_len, reinterpret_cast<const byte*>(salt.data()), - salt.length()); + salt.length(), + reinterpret_cast<const byte*>(label.data()), + label.length()); } virtual KDF* clone() const = 0; diff --git a/src/lib/kdf/kdf1/kdf1.cpp b/src/lib/kdf/kdf1/kdf1.cpp index c7ea3c37e..14dddc5f4 100644 --- a/src/lib/kdf/kdf1/kdf1.cpp +++ b/src/lib/kdf/kdf1/kdf1.cpp @@ -11,9 +11,11 @@ namespace Botan { size_t KDF1::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte 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()) diff --git a/src/lib/kdf/kdf1/kdf1.h b/src/lib/kdf/kdf1/kdf1.h index adaa84894..59bff4d8d 100644 --- a/src/lib/kdf/kdf1/kdf1.h +++ b/src/lib/kdf/kdf1/kdf1.h @@ -25,7 +25,8 @@ class BOTAN_DLL KDF1 final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; explicit KDF1(HashFunction* h) : m_hash(h) {} private: diff --git a/src/lib/kdf/kdf2/kdf2.cpp b/src/lib/kdf/kdf2/kdf2.cpp index df2b7a91c..760ebfc83 100644 --- a/src/lib/kdf/kdf2/kdf2.cpp +++ b/src/lib/kdf/kdf2/kdf2.cpp @@ -11,7 +11,8 @@ namespace Botan { size_t KDF2::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { u32bit counter = 1; secure_vector<byte> h; @@ -21,6 +22,7 @@ size_t KDF2::kdf(byte key[], size_t key_len, { 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); diff --git a/src/lib/kdf/kdf2/kdf2.h b/src/lib/kdf/kdf2/kdf2.h index 7403df21c..600f7c91c 100644 --- a/src/lib/kdf/kdf2/kdf2.h +++ b/src/lib/kdf/kdf2/kdf2.h @@ -25,7 +25,8 @@ class BOTAN_DLL KDF2 final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; explicit KDF2(HashFunction* h) : m_hash(h) {} private: diff --git a/src/lib/kdf/prf_tls/prf_tls.cpp b/src/lib/kdf/prf_tls/prf_tls.cpp index 547b0c9c8..14b330901 100644 --- a/src/lib/kdf/prf_tls/prf_tls.cpp +++ b/src/lib/kdf/prf_tls/prf_tls.cpp @@ -73,23 +73,36 @@ void P_hash(byte out[], size_t out_len, size_t TLS_PRF::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { const size_t S1_len = (secret_len + 1) / 2, S2_len = (secret_len + 1) / 2; const byte* S1 = secret; const byte* S2 = secret + (secret_len - S2_len); + secure_vector<byte> msg; - P_hash(key, key_len, *m_hmac_md5, S1, S1_len, salt, salt_len); - P_hash(key, key_len, *m_hmac_sha1, S2, S2_len, salt, salt_len); + 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(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { - P_hash(key, key_len, *m_mac, secret, secret_len, salt, salt_len); + secure_vector<byte> 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/src/lib/kdf/prf_tls/prf_tls.h b/src/lib/kdf/prf_tls/prf_tls.h index a51006d88..37a517125 100644 --- a/src/lib/kdf/prf_tls/prf_tls.h +++ b/src/lib/kdf/prf_tls/prf_tls.h @@ -25,7 +25,8 @@ class BOTAN_DLL TLS_PRF final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; TLS_PRF(); private: @@ -45,7 +46,8 @@ class BOTAN_DLL TLS_12_PRF final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; explicit TLS_12_PRF(MessageAuthenticationCode* mac) : m_mac(mac) {} diff --git a/src/lib/kdf/prf_x942/prf_x942.cpp b/src/lib/kdf/prf_x942/prf_x942.cpp index fb8de1e85..206cf6ce6 100644 --- a/src/lib/kdf/prf_x942/prf_x942.cpp +++ b/src/lib/kdf/prf_x942/prf_x942.cpp @@ -30,15 +30,21 @@ std::vector<byte> encode_x942_int(u32bit n) size_t X942_PRF::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-160")); const OID kek_algo(m_key_wrap_oid); secure_vector<byte> h; + secure_vector<byte> in; size_t offset = 0; u32bit 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); @@ -54,7 +60,7 @@ size_t X942_PRF::kdf(byte key[], size_t key_len, .encode_if(salt_len != 0, DER_Encoder() .start_explicit(0) - .encode(salt, salt_len, OCTET_STRING) + .encode(in, OCTET_STRING) .end_explicit() ) diff --git a/src/lib/kdf/prf_x942/prf_x942.h b/src/lib/kdf/prf_x942/prf_x942.h index c15be9845..afe56de80 100644 --- a/src/lib/kdf/prf_x942/prf_x942.h +++ b/src/lib/kdf/prf_x942/prf_x942.h @@ -24,7 +24,8 @@ class BOTAN_DLL X942_PRF final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; explicit X942_PRF(const std::string& oid); private: diff --git a/src/lib/kdf/sp800_108/sp800_108.cpp b/src/lib/kdf/sp800_108/sp800_108.cpp index 873db814c..aafb349b2 100644 --- a/src/lib/kdf/sp800_108/sp800_108.cpp +++ b/src/lib/kdf/sp800_108/sp800_108.cpp @@ -8,6 +8,8 @@ #include <botan/sp800_108.h> #include <botan/hmac.h> +#include <iterator> + namespace Botan { SP800_108_Counter* SP800_108_Counter::make(const Spec& spec) @@ -23,13 +25,18 @@ SP800_108_Counter* SP800_108_Counter::make(const Spec& spec) size_t SP800_108_Counter::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { const std::size_t prf_len = m_prf->output_length(); + const byte delim = 0; byte *p = key; uint32_t counter = 1; + uint32_t length = key_len * 8; + byte be_len[4] = { 0 }; secure_vector<byte> tmp; + store_be(length, be_len); m_prf->set_key(secret, secret_len); while(p < key + key_len && counter != 0) @@ -40,7 +47,10 @@ size_t SP800_108_Counter::kdf(byte key[], size_t key_len, store_be(counter, be_cnt); m_prf->update(be_cnt,4); - m_prf->update(salt, salt_len); + 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); std::move(tmp.begin(), tmp.begin() + to_copy, p); @@ -68,16 +78,21 @@ SP800_108_Feedback* SP800_108_Feedback::make(const Spec& spec) size_t SP800_108_Feedback::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { const std::size_t prf_len = m_prf->output_length(); const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0); + const byte delim = 0; byte *p = key; uint32_t counter = 1; + uint32_t length = key_len * 8; + byte be_len[4] = { 0 }; secure_vector< byte > prev(salt, salt + iv_len); secure_vector< byte > ctx(salt + iv_len, salt + salt_len); + store_be(length, be_len); m_prf->set_key(secret, secret_len); while(p < key + key_len && counter != 0) @@ -89,7 +104,10 @@ size_t SP800_108_Feedback::kdf(byte key[], size_t key_len, 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); std::copy(prev.begin(), prev.begin() + to_copy, p); @@ -117,15 +135,27 @@ SP800_108_Pipeline* SP800_108_Pipeline::make(const Spec& spec) size_t SP800_108_Pipeline::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { const std::size_t prf_len = m_prf->output_length(); + const byte delim = 0; + byte *p = key; uint32_t counter = 1; - secure_vector<byte> ai(salt, salt + salt_len), ki; + uint32_t length = key_len * 8; + byte be_len[4] = { 0 }; + secure_vector<byte> 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 && counter != 0) { // A(i) @@ -140,7 +170,10 @@ size_t SP800_108_Pipeline::kdf(byte key[], size_t key_len, 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); std::copy(ki.begin(), ki.begin() + to_copy, p); diff --git a/src/lib/kdf/sp800_108/sp800_108.h b/src/lib/kdf/sp800_108/sp800_108.h index 0acdfacf9..71a918c15 100644 --- a/src/lib/kdf/sp800_108/sp800_108.h +++ b/src/lib/kdf/sp800_108/sp800_108.h @@ -23,9 +23,27 @@ class BOTAN_DLL SP800_108_Counter : public KDF 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(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; SP800_108_Counter(MessageAuthenticationCode* mac) : m_prf(mac) {} @@ -44,9 +62,27 @@ class BOTAN_DLL SP800_108_Feedback : public KDF 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(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; SP800_108_Feedback(MessageAuthenticationCode* mac) : m_prf(mac) {} @@ -65,9 +101,27 @@ class BOTAN_DLL SP800_108_Pipeline : public KDF 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(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; SP800_108_Pipeline(MessageAuthenticationCode* mac) : m_prf(mac) {} diff --git a/src/lib/kdf/sp800_56c/sp800_56c.cpp b/src/lib/kdf/sp800_56c/sp800_56c.cpp index 664d32b30..338feba2a 100644 --- a/src/lib/kdf/sp800_56c/sp800_56c.cpp +++ b/src/lib/kdf/sp800_56c/sp800_56c.cpp @@ -27,17 +27,18 @@ SP800_56C* SP800_56C::make(const Spec& spec) size_t SP800_56C::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { // Randomness Extraction - secure_vector< byte > k_dk, context; + secure_vector< byte > k_dk; m_prf->set_key(salt, salt_len); m_prf->update(secret, secret_len); m_prf->final(k_dk); // Key Expansion - m_exp->kdf(key, key_len, k_dk.data(), k_dk.size(), context.data(), context.size()); + m_exp->kdf(key, key_len, k_dk.data(), k_dk.size(), nullptr, 0, label, label_len); return key_len; } diff --git a/src/lib/kdf/sp800_56c/sp800_56c.h b/src/lib/kdf/sp800_56c/sp800_56c.h index d1b6f39b5..1281ed314 100644 --- a/src/lib/kdf/sp800_56c/sp800_56c.h +++ b/src/lib/kdf/sp800_56c/sp800_56c.h @@ -23,9 +23,27 @@ class BOTAN_DLL SP800_56C : public KDF 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(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; SP800_56C(MessageAuthenticationCode* mac, KDF* exp) : m_prf(mac), m_exp(exp) {} |