commit 5af29fbb63eed3517e0d57a04072531347e64515 Author: rl1987 rl1987@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,
tor-commits@lists.torproject.org