When possible, use RFC5869 HKDF implementation from OpenSSL

Also, stop supporting empty HKDF input key material
This commit is contained in:
rl1987 2018-06-12 16:21:05 +03:00
parent f3267741e4
commit 5af29fbb63
3 changed files with 91 additions and 17 deletions

3
changes/ticket19979 Normal file
View File

@ -0,0 +1,3 @@
o Minor features (openssl):
- When possible, use RFC5869 HKDF implementation from OpenSSL.
Resolves ticket 19979.

View File

@ -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
}

View File

@ -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,