[tor-commits] [tor/master] When possible, use RFC5869 HKDF implementation from OpenSSL

nickm at torproject.org nickm at torproject.org
Thu Jun 21 12:54:38 UTC 2018


commit 5af29fbb63eed3517e0d57a04072531347e64515
Author: rl1987 <rl1987 at sdf.lonestar.org>
Date:   Tue Jun 12 16:21:05 2018 +0300

    When possible, use RFC5869 HKDF implementation from OpenSSL
    
    Also, stop supporting empty HKDF input key material
---
 changes/ticket19979      |  3 ++
 src/common/crypto_hkdf.c | 96 ++++++++++++++++++++++++++++++++++++++++++++----
 src/test/test_crypto.c   |  9 -----
 3 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/changes/ticket19979 b/changes/ticket19979
new file mode 100644
index 000000000..a6bf93f1a
--- /dev/null
+++ b/changes/ticket19979
@@ -0,0 +1,3 @@
+  o Minor features (openssl):
+    - When possible, use RFC5869 HKDF implementation from OpenSSL.
+      Resolves ticket 19979.
diff --git a/src/common/crypto_hkdf.c b/src/common/crypto_hkdf.c
index 6256f632d..24d2ffd86 100644
--- a/src/common/crypto_hkdf.c
+++ b/src/common/crypto_hkdf.c
@@ -12,6 +12,13 @@
 #include "crypto_hkdf.h"
 #include "crypto_util.h"
 #include "crypto_digest.h"
+#include "crypto_openssl_mgt.h"
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
+#define HAVE_OPENSSL_HKDF 1
+#include <openssl/kdf.h>
+#endif
 
 /** Given <b>key_in_len</b> bytes of negotiated randomness in <b>key_in</b>
  * ("K"), expand it into <b>key_out_len</b> bytes of negotiated key material in
@@ -51,15 +58,56 @@ crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len,
   return r;
 }
 
-/** Expand some secret key material according to RFC5869, using SHA256 as the
- * underlying hash.  The <b>key_in_len</b> bytes at <b>key_in</b> are the
- * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
- * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
- * and "info" parameters respectively.  On success, write <b>key_out_len</b>
- * bytes to <b>key_out</b> and return 0.  Assert on failure.
+#ifdef HAVE_OPENSSL_HKDF
+/**
+ * Perform RFC5869 HKDF computation using OpenSSL (only to be called from
+ * crypto_expand_key_material_rfc5869_sha256_openssl). Note that OpenSSL
+ * requires input key to be nonempty and salt length to be equal or less
+ * than 1024.
  */
-int
-crypto_expand_key_material_rfc5869_sha256(
+static int
+crypto_expand_key_material_rfc5869_sha256_openssl(
+                                    const uint8_t *key_in, size_t key_in_len,
+                                    const uint8_t *salt_in, size_t salt_in_len,
+                                    const uint8_t *info_in, size_t info_in_len,
+                                    uint8_t *key_out, size_t key_out_len)
+{
+  int r;
+  EVP_PKEY_CTX *evp_pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
+  tor_assert(evp_pkey_ctx);
+  tor_assert(key_in_len != 0);
+  tor_assert(salt_in_len <= 1024);
+
+  r = EVP_PKEY_derive_init(evp_pkey_ctx);
+  tor_assert(r == 1);
+
+  r = EVP_PKEY_CTX_set_hkdf_md(evp_pkey_ctx, EVP_sha256());
+  tor_assert(r == 1);
+
+  r = EVP_PKEY_CTX_set1_hkdf_salt(evp_pkey_ctx, salt_in, (int)salt_in_len);
+  tor_assert(r == 1);
+
+  r = EVP_PKEY_CTX_set1_hkdf_key(evp_pkey_ctx, key_in, (int)key_in_len);
+  tor_assert(r == 1);
+
+  r = EVP_PKEY_CTX_add1_hkdf_info(evp_pkey_ctx, info_in, (int)info_in_len);
+  tor_assert(r == 1);
+
+  r = EVP_PKEY_derive(evp_pkey_ctx, key_out, &key_out_len);
+  tor_assert(r == 1);
+
+  EVP_PKEY_CTX_free(evp_pkey_ctx);
+  return 0;
+}
+
+#else
+
+/**
+ * Perform RFC5869 HKDF computation using our own legacy implementation.
+ * Only to be called from crypto_expand_key_material_rfc5869_sha256_openssl.
+ */
+static int
+crypto_expand_key_material_rfc5869_sha256_legacy(
                                     const uint8_t *key_in, size_t key_in_len,
                                     const uint8_t *salt_in, size_t salt_in_len,
                                     const uint8_t *info_in, size_t info_in_len,
@@ -109,4 +157,36 @@ crypto_expand_key_material_rfc5869_sha256(
   memwipe(mac, 0, sizeof(mac));
   return 0;
 }
+#endif
+
+/** Expand some secret key material according to RFC5869, using SHA256 as the
+ * underlying hash.  The <b>key_in_len</b> bytes at <b>key_in</b> are the
+ * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
+ * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
+ * and "info" parameters respectively.  On success, write <b>key_out_len</b>
+ * bytes to <b>key_out</b> and return 0.  Assert on failure.
+ */
+int
+crypto_expand_key_material_rfc5869_sha256(
+                                    const uint8_t *key_in, size_t key_in_len,
+                                    const uint8_t *salt_in, size_t salt_in_len,
+                                    const uint8_t *info_in, size_t info_in_len,
+                                    uint8_t *key_out, size_t key_out_len)
+{
+  tor_assert(key_in);
+  tor_assert(key_in_len > 0);
 
+#ifdef HAVE_OPENSSL_HKDF
+  return crypto_expand_key_material_rfc5869_sha256_openssl(key_in,
+                                             key_in_len, salt_in,
+                                             salt_in_len, info_in,
+                                             info_in_len,
+                                             key_out, key_out_len);
+#else
+  return crypto_expand_key_material_rfc5869_sha256_legacy(key_in,
+                                               key_in_len, salt_in,
+                                               salt_in_len, info_in,
+                                               info_in_len,
+                                               key_out, key_out_len);
+#endif
+}
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index a6913ded9..dba8d9afa 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -1822,15 +1822,6 @@ test_crypto_hkdf_sha256(void *arg)
     key_material, 100)
 
   /* Test vectors generated with ntor_ref.py */
-  memset(key_material, 0, sizeof(key_material));
-  EXPAND("");
-  tt_int_op(r, OP_EQ, 0);
-  test_memeq_hex(key_material,
-                 "d3490ed48b12a48f9547861583573fe3f19aafe3f81dc7fc75"
-                 "eeed96d741b3290f941576c1f9f0b2d463d1ec7ab2c6bf71cd"
-                 "d7f826c6298c00dbfe6711635d7005f0269493edf6046cc7e7"
-                 "dcf6abe0d20c77cf363e8ffe358927817a3d3e73712cee28d8");
-
   EXPAND("Tor");
   tt_int_op(r, OP_EQ, 0);
   test_memeq_hex(key_material,





More information about the tor-commits mailing list