aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/kdf
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-09-27 10:14:34 -0400
committerJack Lloyd <[email protected]>2017-09-27 10:14:34 -0400
commitc90e0e21910385ed930865b7dc3d34c6e11685a6 (patch)
tree83873a0c4b4b8b80c577f11f3d9e3733e2b78aba /src/lib/kdf
parentdbb4db76e234328d3aa7dfd3a086da2f57601d8f (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.cpp48
-rw-r--r--src/lib/kdf/hkdf/hkdf.h14
-rw-r--r--src/lib/kdf/hkdf/info.txt2
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>