Re: [PATCH 3/5] crypto: add RFC5869 HKDF
On Thu, Jan 07, 2021 at 08:53:15AM +0100, Stephan Mueller wrote: > > > > > RFC5869 > > > allows two optional parameters to be provided to the extract operation: > > > the salt and additional information. Both are to be provided with the > > > seed parameter where the salt is the first entry of the seed parameter > > > and all subsequent entries are handled as additional information. If > > > the caller intends to invoke the HKDF without salt, it has to provide a > > > NULL/0 entry as first entry in seed. > > > > Where does "additional information" for extract come from? RFC 5869 has: > > > > HKDF-Extract(salt, IKM) -> PRK > > > > Inputs: > > salt optional salt value (a non-secret random value); > > if not provided, it is set to a string of HashLen > > zeros. > > IKM input keying material > > > > There's no "additional information". > > I used the terminology from SP800-108. I will update the description > accordingly. For HKDF, it would be better to stick to the terminology used in RFC 5869 (https://tools.ietf.org/html/rfc5869), as generally that's what people are most familiar with for HKDF. It also matches the HKDF paper (https://eprint.iacr.org/2010/264.pdf) more closely. - Eric
Re: [PATCH 3/5] crypto: add RFC5869 HKDF
Am Mittwoch, dem 06.01.2021 um 23:30 -0800 schrieb Eric Biggers: > On Mon, Jan 04, 2021 at 10:49:13PM +0100, Stephan Müller wrote: > > RFC5869 specifies an extract and expand two-step key derivation > > function. The HKDF implementation is provided as a service function that > > operates on a caller-provided HMAC cipher handle. > > HMAC isn't a "cipher". > > > The extract function is invoked via the crypto_hkdf_setkey call. > > Any reason not to call this crypto_hkdf_extract(), to match the > specification? I named it to match the other KDF implementation. But you are right, I will name it accordingly. > > > RFC5869 > > allows two optional parameters to be provided to the extract operation: > > the salt and additional information. Both are to be provided with the > > seed parameter where the salt is the first entry of the seed parameter > > and all subsequent entries are handled as additional information. If > > the caller intends to invoke the HKDF without salt, it has to provide a > > NULL/0 entry as first entry in seed. > > Where does "additional information" for extract come from? RFC 5869 has: > > HKDF-Extract(salt, IKM) -> PRK > > Inputs: > salt optional salt value (a non-secret random value); > if not provided, it is set to a string of HashLen > zeros. > IKM input keying material > > There's no "additional information". I used the terminology from SP800-108. I will update the description accordingly. > > > > > The expand function is invoked via the crypto_hkdf_generate and can be > > invoked multiple times. This function allows the caller to provide a > > context for the key derivation operation. As specified in RFC5869, it is > > optional. In case such context is not provided, the caller must provide > > NULL / 0 for the info / info_nvec parameters. > > Any reason not to call this crypto_hkdf_expand() to match the specification? I will update the function name. Thanks Stephan > > - Eric
Re: [PATCH 3/5] crypto: add RFC5869 HKDF
On Mon, Jan 04, 2021 at 10:49:13PM +0100, Stephan Müller wrote: > RFC5869 specifies an extract and expand two-step key derivation > function. The HKDF implementation is provided as a service function that > operates on a caller-provided HMAC cipher handle. HMAC isn't a "cipher". > The extract function is invoked via the crypto_hkdf_setkey call. Any reason not to call this crypto_hkdf_extract(), to match the specification? > RFC5869 > allows two optional parameters to be provided to the extract operation: > the salt and additional information. Both are to be provided with the > seed parameter where the salt is the first entry of the seed parameter > and all subsequent entries are handled as additional information. If > the caller intends to invoke the HKDF without salt, it has to provide a > NULL/0 entry as first entry in seed. Where does "additional information" for extract come from? RFC 5869 has: HKDF-Extract(salt, IKM) -> PRK Inputs: salt optional salt value (a non-secret random value); if not provided, it is set to a string of HashLen zeros. IKM input keying material There's no "additional information". > > The expand function is invoked via the crypto_hkdf_generate and can be > invoked multiple times. This function allows the caller to provide a > context for the key derivation operation. As specified in RFC5869, it is > optional. In case such context is not provided, the caller must provide > NULL / 0 for the info / info_nvec parameters. Any reason not to call this crypto_hkdf_expand() to match the specification? - Eric
[PATCH 3/5] crypto: add RFC5869 HKDF
RFC5869 specifies an extract and expand two-step key derivation function. The HKDF implementation is provided as a service function that operates on a caller-provided HMAC cipher handle. The caller has to allocate the HMAC cipher and then can invoke the HKDF service functions. The HKDF implementation ensures that the entire state is kept with the HMAC cipher handle which implies that no additional state is required to be maintained by the HKDF implementation. The extract function is invoked via the crypto_hkdf_setkey call. RFC5869 allows two optional parameters to be provided to the extract operation: the salt and additional information. Both are to be provided with the seed parameter where the salt is the first entry of the seed parameter and all subsequent entries are handled as additional information. If the caller intends to invoke the HKDF without salt, it has to provide a NULL/0 entry as first entry in seed. The expand function is invoked via the crypto_hkdf_generate and can be invoked multiple times. This function allows the caller to provide a context for the key derivation operation. As specified in RFC5869, it is optional. In case such context is not provided, the caller must provide NULL / 0 for the info / info_nvec parameters. Signed-off-by: Stephan Mueller --- crypto/Kconfig| 7 ++ crypto/Makefile | 1 + crypto/hkdf.c | 226 ++ include/crypto/hkdf.h | 48 + 4 files changed, 282 insertions(+) create mode 100644 crypto/hkdf.c create mode 100644 include/crypto/hkdf.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 9f375c2350f5..661287d7283b 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1862,6 +1862,13 @@ config CRYPTO_JITTERENTROPY random numbers. This Jitterentropy RNG registers with the kernel crypto API and can be used by any caller. +config CRYPTO_HKDF + tristate "Extract and Expand HKDF (RFC 5869)" + select CRYPTO_HASH + help + Enable the extract and expand key derivation function compliant + to RFC 5869. + config CRYPTO_KDF800108_CTR tristate "Counter KDF (SP800-108)" select CRYPTO_HASH diff --git a/crypto/Makefile b/crypto/Makefile index 46845a70850d..55a4d8c31a45 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -201,4 +201,5 @@ obj-$(CONFIG_CRYPTO_SIMD) += crypto_simd.o # # Key derivation function # +obj-$(CONFIG_CRYPTO_HKDF) += hkdf.o obj-$(CONFIG_CRYPTO_KDF800108_CTR) += kdf_sp800108.o diff --git a/crypto/hkdf.c b/crypto/hkdf.c new file mode 100644 index ..a3bf6d6b07ea --- /dev/null +++ b/crypto/hkdf.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * HMAC-based Extract-and-Expand Key Derivation Function (conformant to RFC5869) + * + * Copyright (C) 2020, Stephan Mueller + */ + +#include +#include +#include + +/* + * HKDF expand phase + */ +int crypto_hkdf_generate(struct crypto_shash *kmd, +const struct kvec *info, unsigned int info_nvec, +u8 *dst, unsigned int dlen) +{ + SHASH_DESC_ON_STACK(desc, kmd); + const unsigned int h = crypto_shash_digestsize(kmd); + unsigned int i; + int err = 0; + u8 *dst_orig = dst; + const u8 *prev = NULL; + u8 ctr = 0x01; + + if (dlen > h * 255) + return -EINVAL; + + desc->tfm = kmd; + + /* T(1) and following */ + while (dlen) { + err = crypto_shash_init(desc); + if (err) + goto out; + + if (prev) { + err = crypto_shash_update(desc, prev, h); + if (err) + goto out; + } + + for (i = 0; i < info_nvec; i++) { + err = crypto_shash_update(desc, info[i].iov_base, + info[i].iov_len); + if (err) + goto out; + } + + if (dlen < h) { + u8 tmpbuffer[HASH_MAX_DIGESTSIZE]; + + err = crypto_shash_finup(desc, , 1, tmpbuffer); + if (err) + goto out; + memcpy(dst, tmpbuffer, dlen); + memzero_explicit(tmpbuffer, h); + goto out; + } + + err = crypto_shash_finup(desc, , 1, dst); + if (err) + goto out; + + prev = dst; + dst += h; + dlen -= h; + ctr++; + } + +out: + if (err) + memzero_explicit(dst_orig, dlen); + shash_desc_zero(desc); + return err; +} +EXPORT_SYMBOL(crypto_hkdf_generate); + +/* + * HKDF extract phase. + */ +int crypto_hkdf_setkey(struct crypto_shash *kmd, + const struct kvec *seed,