diff options
author | Jack Lloyd <[email protected]> | 2017-09-27 10:14:34 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-09-27 10:14:34 -0400 |
commit | c90e0e21910385ed930865b7dc3d34c6e11685a6 (patch) | |
tree | 83873a0c4b4b8b80c577f11f3d9e3733e2b78aba /src/lib/kdf | |
parent | dbb4db76e234328d3aa7dfd3a086da2f57601d8f (diff) |
Add HKDF-Expand-Label
Step 1/n of TLS 1.3
Diffstat (limited to 'src/lib/kdf')
-rw-r--r-- | src/lib/kdf/hkdf/hkdf.cpp | 48 | ||||
-rw-r--r-- | src/lib/kdf/hkdf/hkdf.h | 14 | ||||
-rw-r--r-- | src/lib/kdf/hkdf/info.txt | 2 |
3 files changed, 62 insertions, 2 deletions
diff --git a/src/lib/kdf/hkdf/hkdf.cpp b/src/lib/kdf/hkdf/hkdf.cpp index 20215125b..d66847244 100644 --- a/src/lib/kdf/hkdf/hkdf.cpp +++ b/src/lib/kdf/hkdf/hkdf.cpp @@ -1,6 +1,6 @@ /* * HKDF -* (C) 2013,2015 Jack Lloyd +* (C) 2013,2015,2017 Jack Lloyd * (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) @@ -73,4 +73,50 @@ size_t HKDF_Expand::kdf(uint8_t key[], size_t key_len, 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) + { + if(length > 0xFFFF) + throw Invalid_Argument("HKDF-Expand-Label requested output too large"); + if(label.size() > 0xFF) + throw Invalid_Argument("HKDF-Expand-Label label too long"); + if(hash_val_len > 0xFF) + throw Invalid_Argument("HKDF-Expand-Label hash too long"); + + auto mac = MessageAuthenticationCode::create("HMAC(" + hash_fn + ")"); + if(!mac) + throw Invalid_Argument("HKDF-Expand-Label with HMAC(" + hash_fn + ") not available"); + + HKDF_Expand hkdf(mac.release()); + + secure_vector<uint8_t> output(length); + std::vector<uint8_t> prefix(3 + label.size() + 1); + + prefix[0] = get_byte<uint16_t>(0, length); + prefix[1] = get_byte<uint16_t>(1, length); + prefix[2] = static_cast<uint8_t>(label.size()); + + copy_mem(prefix.data() + 3, + reinterpret_cast<const uint8_t*>(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/src/lib/kdf/hkdf/hkdf.h b/src/lib/kdf/hkdf/hkdf.h index e63973497..7d2b7f8b2 100644 --- a/src/lib/kdf/hkdf/hkdf.h +++ b/src/lib/kdf/hkdf/hkdf.h @@ -86,6 +86,20 @@ class BOTAN_PUBLIC_API(2,0) HKDF_Expand final : public KDF std::unique_ptr<MessageAuthenticationCode> m_prf; }; +/** +* HKDF-Expand-Label from TLS 1.3/QUIC +* @param label the full label (no "TLS 1.3, " or "tls13 " prefix +* is applied) +*/ +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/src/lib/kdf/hkdf/info.txt b/src/lib/kdf/hkdf/info.txt index db6618c3c..b9b17b3b8 100644 --- a/src/lib/kdf/hkdf/info.txt +++ b/src/lib/kdf/hkdf/info.txt @@ -1,3 +1,3 @@ <defines> -HKDF -> 20131128 +HKDF -> 20170927 </defines> |