Re: [PATCH 4/6] crypto: hkdf - RFC5869 Key Derivation Function

2019-01-14 Thread Stephan Mueller
Am Montag, 14. Januar 2019, 18:53:16 CET schrieb Eric Biggers:

Hi Eric,

> > I would not suggest this, because that rounds contrary to the concept of
> > the kernel crypto API IMHO. The caller has to provide the wrapping
> > cipher. It is perfectly viable to allow a caller to invoke a specific
> > keyed message digest.
> Sure, but it would not conform to the HKDF specification.  Are you sure it
> is okay to specify an arbitrary keyed hash?

Technically, I see no issue why this should not be possible. You see that with 
the SP800-108 KDF implementations where using CMAC is perfectly legal (and 
which I also test).

Though, using another keyed hash implementation like CMAC is not covered by 
the HKDF spec. If a caller would use hkdf(cmac(aes)), it would produce 
cryptographically strong values. Though this implementation does not conform 
to any standard. I do not think we should prevent a caller to select such 
combination in the kernel crypto API.

IMHO there would even be valid reasons why one would use cmac(aes) for a kdf. 
For example, when you would want to use a hardware AES which somehow also 
employs a hardware key that is inaccessible to software in order to tie the 
KDF result to the local hardware. This could even be a valid use case for Ext4 
FBE encryption where you derive a key. The KDF could be used to link the 
derived key to the local hardware to prevent the encrypted data could be 
copied to another system and decrypted successfully there.

Ciao
Stephan




Re: [PATCH 4/6] crypto: hkdf - RFC5869 Key Derivation Function

2019-01-14 Thread Eric Biggers
On Mon, Jan 14, 2019 at 10:30:39AM +0100, Stephan Müller wrote:
> Am Samstag, 12. Januar 2019, 06:12:54 CET schrieb Eric Biggers:
> 
> Hi Eric,
> 
> [...]
> 
> > > The extract and expand phases use different instances of the underlying
> > > keyed message digest cipher to ensure that while the extraction phase
> > > generates a new key for the expansion phase, the cipher for the
> > > expansion phase can still be used. This approach is intended to aid
> > > multi-threaded uses cases.
> > 
> > I think you partially misunderstood what I was asking for.  One HMAC tfm is
> > sufficient as long as HKDF-Expand is separated from HKDF-Extract, which
> > you've done.  So just use one HMAC tfm, and in crypto_hkdf_seed() key it
> > with the 'salt', and then afterwards with the 'prk'.
> 
> Ok, thanks for the clarification. I will remove the 2nd HMAC TFM then.
> > 
> > Also everywhere in this patchset, please avoid using the word "cipher" to
> > refer to algorithms that are not encryption/decryption.  I know a lot of
> > the crypto API docs do this, but I think it is a mistake and confusing. 
> > Hash algorithms and KDFs are not "ciphers".
> 
> As you wish, I will refer to specific name of the cryptographic operation.
> 
> [...]
> 
> > > + * NOTE: In-place cipher operations are not supported.
> > > + */
> > 
> > What does an "in-place cipher operation" mean in this context?  That the
> > 'info' buffer must not overlap the 'dst' buffer? 
> 
> Correct, no overlapping.
> 
> > Maybe
> > crypto_rng_generate() should check that for all crypto_rngs?  Or is it
> > different for different crypto_rngs?
> 
> This is the case in general for all KDFs (and even RNGs). It is no technical 
> or cryptographic error to have overlapping buffers. The only issue is that 
> the 
> result will not match the expected value.
> 
> The issue is that the input buffer to the generate function is an input to 
> every round of the KDF. If the input and output buffer overlap, starting with 
> the 2nd iteration of the KDF, the input is the output of the 1st round. 
> Again, 
> I do not think it is a cryptographic error though.
> 
> (To support my conclusion: A colleague of mine has proposed an update to the 
> HKDF specification where the input data changes for each KDF round. This 
> proposal was considered appropriate by one of the authors of HKDF.)
> 
> If the requested output is smaller or equal to the output block size of the 
> KDF, overlapping buffers are even harmless since the implementation will 
> calculate the correct output.
> 
> Due to that, I removed the statement. But I am not sure we should add a 
> technical block to deny overlapping input/output buffers.
> 
> [...]
> > > 
> > > + desc->flags = crypto_shash_get_flags(expand_kmd) &
> > > +   CRYPTO_TFM_REQ_MAY_SLEEP;
> > 
> > This line setting desc->flags doesn't make sense.  How is the user meant to
> > control whether crypto_rng_generate() can sleep or not?  Or can it always
> > sleep? Either way this part is wrong since the user can't get access to the
> > HMAC tfm to set this flag being checked for.
> 
> Could you please help me why a user should set this flag? Isn't the 
> implementation specifying that flag to allow identifying whether the 
> implementation could or could not sleep? Thus, we simply copy the sleeping 
> flag from the lower level keyed message digest implementation.
> 
> At least that is also the implementation found in crypto/hmac.c.
> 
> [...]

Whether the crypto_shash* stuff can sleep is controlled on a per-request basis,
not a per-implementation basis.  So I don't understand what you are talking
about here.

> 
> > > + if (dlen < h) {
> > > + u8 tmpbuffer[CRYPTO_HKDF_MAX_DIGESTSIZE];
> > > +
> > > + err = crypto_shash_finup(desc, , 1, tmpbuffer);
> > > + if (err)
> > > + goto out;
> > > + memcpy(dst, tmpbuffer, dlen);
> > > + memzero_explicit(tmpbuffer, h);
> > > + goto out;
> > > + } else {
> > 
> > No need for the 'else'.
> 
> Could you please help me why that else branch is not needed? If the buffer to 
> be generated is equal or larger than the output block length of the keyed 
> message digest, I would like to directly operate on the output buffer to 
> avoid 
> a memcpy.

I'm simply saying you don't need the 'else' keyword as the previous block ends
with a goto.

> > 
> > > + err = crypto_shash_finup(desc, , 1, dst);
> > > + if (err)
> > > + goto out;
> > > +
> > > + prev = dst;
> > > + dst += h;
> > > + dlen -= h;
> > > + ctr++;
> > > + }
> > > + }
> 
> [...]
> > 
> > > + struct crypto_shash *extract_kmd = ctx->extract_kmd;
> > > + struct crypto_shash *expand_kmd = ctx->expand_kmd;
> > > + struct rtattr *rta = (struct rtattr *)seed;
> > > + SHASH_DESC_ON_STACK(desc, extract_kmd);
> 

Re: [PATCH 4/6] crypto: hkdf - RFC5869 Key Derivation Function

2019-01-14 Thread Stephan Müller
Am Samstag, 12. Januar 2019, 06:12:54 CET schrieb Eric Biggers:

Hi Eric,

[...]

> > The extract and expand phases use different instances of the underlying
> > keyed message digest cipher to ensure that while the extraction phase
> > generates a new key for the expansion phase, the cipher for the
> > expansion phase can still be used. This approach is intended to aid
> > multi-threaded uses cases.
> 
> I think you partially misunderstood what I was asking for.  One HMAC tfm is
> sufficient as long as HKDF-Expand is separated from HKDF-Extract, which
> you've done.  So just use one HMAC tfm, and in crypto_hkdf_seed() key it
> with the 'salt', and then afterwards with the 'prk'.

Ok, thanks for the clarification. I will remove the 2nd HMAC TFM then.
> 
> Also everywhere in this patchset, please avoid using the word "cipher" to
> refer to algorithms that are not encryption/decryption.  I know a lot of
> the crypto API docs do this, but I think it is a mistake and confusing. 
> Hash algorithms and KDFs are not "ciphers".

As you wish, I will refer to specific name of the cryptographic operation.

[...]

> > + * NOTE: In-place cipher operations are not supported.
> > + */
> 
> What does an "in-place cipher operation" mean in this context?  That the
> 'info' buffer must not overlap the 'dst' buffer? 

Correct, no overlapping.

> Maybe
> crypto_rng_generate() should check that for all crypto_rngs?  Or is it
> different for different crypto_rngs?

This is the case in general for all KDFs (and even RNGs). It is no technical 
or cryptographic error to have overlapping buffers. The only issue is that the 
result will not match the expected value.

The issue is that the input buffer to the generate function is an input to 
every round of the KDF. If the input and output buffer overlap, starting with 
the 2nd iteration of the KDF, the input is the output of the 1st round. Again, 
I do not think it is a cryptographic error though.

(To support my conclusion: A colleague of mine has proposed an update to the 
HKDF specification where the input data changes for each KDF round. This 
proposal was considered appropriate by one of the authors of HKDF.)

If the requested output is smaller or equal to the output block size of the 
KDF, overlapping buffers are even harmless since the implementation will 
calculate the correct output.

Due to that, I removed the statement. But I am not sure we should add a 
technical block to deny overlapping input/output buffers.

[...]
> > 
> > +   desc->flags = crypto_shash_get_flags(expand_kmd) &
> > + CRYPTO_TFM_REQ_MAY_SLEEP;
> 
> This line setting desc->flags doesn't make sense.  How is the user meant to
> control whether crypto_rng_generate() can sleep or not?  Or can it always
> sleep? Either way this part is wrong since the user can't get access to the
> HMAC tfm to set this flag being checked for.

Could you please help me why a user should set this flag? Isn't the 
implementation specifying that flag to allow identifying whether the 
implementation could or could not sleep? Thus, we simply copy the sleeping 
flag from the lower level keyed message digest implementation.

At least that is also the implementation found in crypto/hmac.c.

[...]

> > +   if (dlen < h) {
> > +   u8 tmpbuffer[CRYPTO_HKDF_MAX_DIGESTSIZE];
> > +
> > +   err = crypto_shash_finup(desc, , 1, tmpbuffer);
> > +   if (err)
> > +   goto out;
> > +   memcpy(dst, tmpbuffer, dlen);
> > +   memzero_explicit(tmpbuffer, h);
> > +   goto out;
> > +   } else {
> 
> No need for the 'else'.

Could you please help me why that else branch is not needed? If the buffer to 
be generated is equal or larger than the output block length of the keyed 
message digest, I would like to directly operate on the output buffer to avoid 
a memcpy.
> 
> > +   err = crypto_shash_finup(desc, , 1, dst);
> > +   if (err)
> > +   goto out;
> > +
> > +   prev = dst;
> > +   dst += h;
> > +   dlen -= h;
> > +   ctr++;
> > +   }
> > +   }

[...]
> 
> > +   struct crypto_shash *extract_kmd = ctx->extract_kmd;
> > +   struct crypto_shash *expand_kmd = ctx->expand_kmd;
> > +   struct rtattr *rta = (struct rtattr *)seed;
> > +   SHASH_DESC_ON_STACK(desc, extract_kmd);
> > +   u32 saltlen;
> > +   unsigned int h = crypto_shash_digestsize(extract_kmd);
> > +   int err;
> > +   const uint8_t null_salt[CRYPTO_HKDF_MAX_DIGESTSIZE] = { 0 };
> 
> static const
> 

Why would I want to turn that buffer into a static variable? All we need it 
for is in case there is no salt provided.

[...]

> > +
> > +   if (!RTA_OK(rta, slen))
> > +   return -EINVAL;
> > +   if (rta->rta_type != 1)
> > +   return -EINVAL;
> > +   if (RTA_PAYLOAD(rta) < sizeof(saltlen))
> > +   

Re: [PATCH 4/6] crypto: hkdf - RFC5869 Key Derivation Function

2019-01-13 Thread James Bottomley
On Sun, 2019-01-13 at 08:56 +0100, Stephan Müller wrote:
> The question may arise why to plug the KDFs into RNGs. The answer is
> quite simple: KDFs are a form of random number generator. In that
> they take some input for initialization (aka seed, salt, key,
> personalization string). Then they produce pseudo-random bit
> sequences of arbitrary length. Possibly the generation operation can
> be modified by providing some additional input to be used by the
> generation process (aka label, context, info string, additional 
> information string). Thus, the RNG interface is a natural fit for the
> KDFs.

Philosophically, that's quite wrong.  KDFs are a class of pseudorandom
functions (PRFs).  PRFs are designed so that the output is
indistinguishable from a random number generator to observers who don't
know the input but is deterministically useful for participants who do.
 That means the're definitely not RNGs they're functions whose output
is designed to look like the output of an RNG.

I suppose the mathematical thing that distinguishes PRFs and RNGs is
entropy: PRFs have zero entropy because given the same inputs you
expect the same output. Now whether it makes sense to use the RNG API
or not I'll leave that up to the crypto people.  I would have expected
any cryptographic RNG API to be mostly about entropy management (the
Linux core internal one certainly is), but it appears that the one in
crypto isn't.

James



Re: [PATCH 4/6] crypto: hkdf - RFC5869 Key Derivation Function

2019-01-12 Thread Stephan Müller
Am Samstag, 12. Januar 2019, 10:55:35 CET schrieb Herbert Xu:

Hi Herbert,

> On Fri, Jan 11, 2019 at 09:12:54PM -0800, Eric Biggers wrote:
> > Hi Stephan,
> > 
> > On Fri, Jan 11, 2019 at 08:10:39PM +0100, Stephan Müller wrote:
> > > The RFC5869 compliant Key Derivation Function is implemented as a
> > > random number generator considering that it behaves like a deterministic
> > > RNG.
> > 
> > Thanks for the proof of concept!  I guess it ended up okay.  But can you
> > explain more the benefits of using the crypto_rng interface, as opposed
> > to just some crypto_hkdf_*() helper functions that are exported for
> > modules to use?
> I agree.  I see no benefit in adding this through the RNG API as
> opposed to just providing it as a helper.  If some form of hardware
> acceleration were to eventuate in the future we could always revisit
> this.

The advantages for using the kernel crypto API to add KDFs as opposed to 
adding helper wrappers are the following in my view:

- employment of the kernel crypto API testmgr - invocation of the testmgr is 
transparent and thus already provided without any additional code to link to 
it

- FIPS 140-2 compliance: To mark a KDF as FIPS 140-2 approved cipher, it must 
be subject to a known-answer self test (implemented by the testmgr) as well as 
to an enforcement of the integrity check verification. In FIPS 140-2 mode, the 
kernel crypto API panic()s when a kernel crypto API module is loaded and its 
signature does not check out. As this is only relevant for crypto modules (and 
not arbitrary other kernel modules), this is implemented with the invocations 
the crypto_register_alg as well as crypto_register_template functions. Thus, 
when using a wrapper code to implement the KDF, they can per definition not be 
FIPS 140-2 approved.

- The invoker of a KDF has one consistent API. This implies that the KDF 
selection now becomes more of a "configuration" choice. For example, when you 
look at the KDF use case for the keys subsystem (security/keys/dh.c), 
selecting the type of KDF would only necessitate a change of a string 
referencing the KDF. A lot of people somehow favor the extract-and-expand KDFs 
over the traditional KDFs. Now, that the RFC5869 HKDF is also approved as per 
SP800-56A rev3, I could see that folks may want to switch to HKDF for the key 
management. When we have a common API, this choice could even be left to the 
caller.

The question may arise why to plug the KDFs into RNGs. The answer is quite 
simple: KDFs are a form of random number generator. In that they take some 
input for initialization (aka seed, salt, key, personalization string). Then 
they produce pseudo-random bit sequences of arbitrary length. Possibly the 
generation operation can be modified by providing some additional input to be 
used by the generation process (aka label, context, info string, additional 
information string). Thus, the RNG interface is a natural fit for the KDFs.

Ciao
Stephan




Re: [PATCH 4/6] crypto: hkdf - RFC5869 Key Derivation Function

2019-01-12 Thread Herbert Xu
On Fri, Jan 11, 2019 at 09:12:54PM -0800, Eric Biggers wrote:
> Hi Stephan,
> 
> On Fri, Jan 11, 2019 at 08:10:39PM +0100, Stephan Müller wrote:
> > The RFC5869 compliant Key Derivation Function is implemented as a
> > random number generator considering that it behaves like a deterministic
> > RNG.
> > 
> 
> Thanks for the proof of concept!  I guess it ended up okay.  But can you 
> explain
> more the benefits of using the crypto_rng interface, as opposed to just some
> crypto_hkdf_*() helper functions that are exported for modules to use?

I agree.  I see no benefit in adding this through the RNG API as
opposed to just providing it as a helper.  If some form of hardware
acceleration were to eventuate in the future we could always revisit
this.

Cheers,
-- 
Email: Herbert Xu 
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


Re: [PATCH 4/6] crypto: hkdf - RFC5869 Key Derivation Function

2019-01-11 Thread Eric Biggers
Hi Stephan,

On Fri, Jan 11, 2019 at 08:10:39PM +0100, Stephan Müller wrote:
> The RFC5869 compliant Key Derivation Function is implemented as a
> random number generator considering that it behaves like a deterministic
> RNG.
> 

Thanks for the proof of concept!  I guess it ended up okay.  But can you explain
more the benefits of using the crypto_rng interface, as opposed to just some
crypto_hkdf_*() helper functions that are exported for modules to use?

> The extract and expand phases use different instances of the underlying
> keyed message digest cipher to ensure that while the extraction phase
> generates a new key for the expansion phase, the cipher for the
> expansion phase can still be used. This approach is intended to aid
> multi-threaded uses cases.

I think you partially misunderstood what I was asking for.  One HMAC tfm is
sufficient as long as HKDF-Expand is separated from HKDF-Extract, which you've
done.  So just use one HMAC tfm, and in crypto_hkdf_seed() key it with the
'salt', and then afterwards with the 'prk'.

Also everywhere in this patchset, please avoid using the word "cipher" to refer
to algorithms that are not encryption/decryption.  I know a lot of the crypto
API docs do this, but I think it is a mistake and confusing.  Hash algorithms
and KDFs are not "ciphers".

> 
> Signed-off-by: Stephan Mueller 
> ---
>  crypto/Kconfig  |   6 +
>  crypto/Makefile |   1 +
>  crypto/hkdf.c   | 290 
>  3 files changed, 297 insertions(+)
>  create mode 100644 crypto/hkdf.c
> 
> diff --git a/crypto/Kconfig b/crypto/Kconfig
> index cc80d89e0cf5..0eee5e129fa3 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -568,6 +568,12 @@ config CRYPTO_KDF
> Support for KDF compliant to SP800-108. All three types of
> KDF specified in SP800-108 are implemented.
>  
> +config CRYPTO_HKDF
> + tristate "HMAC-based Extract-and expand Key Derivation Function"
> + select CRYPTO_RNG
> + help
> +   Support for KDF compliant to RFC5869.
> +

Make the description
"HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"?
There is a missing dash, and probably the acronym "HKDF" should be in there.

>  config CRYPTO_XCBC
>   tristate "XCBC support"
>   select CRYPTO_HASH
> diff --git a/crypto/Makefile b/crypto/Makefile
> index 69a0bb64b0ac..6bbb0a4dea13 100644
> --- a/crypto/Makefile
> +++ b/crypto/Makefile
> @@ -59,6 +59,7 @@ crypto_user-$(CONFIG_CRYPTO_STATS) += crypto_user_stat.o
>  obj-$(CONFIG_CRYPTO_CMAC) += cmac.o
>  obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
>  obj-$(CONFIG_CRYPTO_KDF) += kdf.o
> +obj-$(CONFIG_CRYPTO_HKDF) += hkdf.o
>  obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
>  obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
>  obj-$(CONFIG_CRYPTO_NULL2) += crypto_null.o
> diff --git a/crypto/hkdf.c b/crypto/hkdf.c
> new file mode 100644
> index ..35a975ed64a8
> --- /dev/null
> +++ b/crypto/hkdf.c
> @@ -0,0 +1,290 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/*
> + * RFC 5869 Key-derivation function
> + *

People don't know what RFC xyz is.  Please be more explicit than just the RFC
number, e.g.

"HKDF: HMAC-based Extract-and-Expand Key Derivation Function (RFC 5869)"

> + * Copyright (C) 2019, Stephan Mueller 
> + */
> +
> +/*
> + * The HKDF extract phase is applied with crypto_rng_reset().
> + * The HKDF expand phase is applied with crypto_rng_generate().
> + *
> + * NOTE: In-place cipher operations are not supported.
> + */

What does an "in-place cipher operation" mean in this context?  That the 'info'
buffer must not overlap the 'dst' buffer?  Maybe crypto_rng_generate() should
check that for all crypto_rngs?  Or is it different for different crypto_rngs?

> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +struct crypto_hkdf_ctx {
> + struct crypto_shash *extract_kmd;
> + struct crypto_shash *expand_kmd;
> +};
> +
> +#define CRYPTO_HKDF_MAX_DIGESTSIZE   64
> +
> +/*
> + * HKDF expand phase
> + */
> +static int crypto_hkdf_random(struct crypto_rng *rng,
> +   const u8 *info, unsigned int infolen,
> +   u8 *dst, unsigned int dlen)

Why call it crypto_hkdf_random() instead of crypto_hkdf_generate()?  The latter
would match rng_alg::generate.

> +{
> + struct crypto_hkdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));

const

> + struct crypto_shash *expand_kmd = ctx->expand_kmd;
> + SHASH_DESC_ON_STACK(desc, expand_kmd);

> + unsigned int h = crypto_shash_digestsize(expand_kmd);

const

> + int err = 0;
> + u8 *dst_orig = dst;
> + const u8 *prev = NULL;

> + uint8_t ctr = 0x01;

u8 instead of uint8_t

> +
> + if (dlen > h * 255)
> + return -EINVAL;
> +
> + desc->tfm = expand_kmd;

> + desc->flags = crypto_shash_get_flags(expand_kmd) &
> +   CRYPTO_TFM_REQ_MAY_SLEEP;

This line setting desc->flags doesn't make sense.  How is the user meant to
control 

[PATCH 4/6] crypto: hkdf - RFC5869 Key Derivation Function

2019-01-11 Thread Stephan Müller
The RFC5869 compliant Key Derivation Function is implemented as a
random number generator considering that it behaves like a deterministic
RNG.

The extract and expand phases use different instances of the underlying
keyed message digest cipher to ensure that while the extraction phase
generates a new key for the expansion phase, the cipher for the
expansion phase can still be used. This approach is intended to aid
multi-threaded uses cases.

Signed-off-by: Stephan Mueller 
---
 crypto/Kconfig  |   6 +
 crypto/Makefile |   1 +
 crypto/hkdf.c   | 290 
 3 files changed, 297 insertions(+)
 create mode 100644 crypto/hkdf.c

diff --git a/crypto/Kconfig b/crypto/Kconfig
index cc80d89e0cf5..0eee5e129fa3 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -568,6 +568,12 @@ config CRYPTO_KDF
  Support for KDF compliant to SP800-108. All three types of
  KDF specified in SP800-108 are implemented.
 
+config CRYPTO_HKDF
+   tristate "HMAC-based Extract-and expand Key Derivation Function"
+   select CRYPTO_RNG
+   help
+ Support for KDF compliant to RFC5869.
+
 config CRYPTO_XCBC
tristate "XCBC support"
select CRYPTO_HASH
diff --git a/crypto/Makefile b/crypto/Makefile
index 69a0bb64b0ac..6bbb0a4dea13 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -59,6 +59,7 @@ crypto_user-$(CONFIG_CRYPTO_STATS) += crypto_user_stat.o
 obj-$(CONFIG_CRYPTO_CMAC) += cmac.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
 obj-$(CONFIG_CRYPTO_KDF) += kdf.o
+obj-$(CONFIG_CRYPTO_HKDF) += hkdf.o
 obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
 obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
 obj-$(CONFIG_CRYPTO_NULL2) += crypto_null.o
diff --git a/crypto/hkdf.c b/crypto/hkdf.c
new file mode 100644
index ..35a975ed64a8
--- /dev/null
+++ b/crypto/hkdf.c
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * RFC 5869 Key-derivation function
+ *
+ * Copyright (C) 2019, Stephan Mueller 
+ */
+
+/*
+ * The HKDF extract phase is applied with crypto_rng_reset().
+ * The HKDF expand phase is applied with crypto_rng_generate().
+ *
+ * NOTE: In-place cipher operations are not supported.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct crypto_hkdf_ctx {
+   struct crypto_shash *extract_kmd;
+   struct crypto_shash *expand_kmd;
+};
+
+#define CRYPTO_HKDF_MAX_DIGESTSIZE 64
+
+/*
+ * HKDF expand phase
+ */
+static int crypto_hkdf_random(struct crypto_rng *rng,
+ const u8 *info, unsigned int infolen,
+ u8 *dst, unsigned int dlen)
+{
+   struct crypto_hkdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));
+   struct crypto_shash *expand_kmd = ctx->expand_kmd;
+   SHASH_DESC_ON_STACK(desc, expand_kmd);
+   unsigned int h = crypto_shash_digestsize(expand_kmd);
+   int err = 0;
+   u8 *dst_orig = dst;
+   const u8 *prev = NULL;
+   uint8_t ctr = 0x01;
+
+   if (dlen > h * 255)
+   return -EINVAL;
+
+   desc->tfm = expand_kmd;
+   desc->flags = crypto_shash_get_flags(expand_kmd) &
+ CRYPTO_TFM_REQ_MAY_SLEEP;
+
+   /* 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;
+   }
+
+   if (info) {
+   err = crypto_shash_update(desc, info, infolen);
+   if (err)
+   goto out;
+   }
+
+   if (dlen < h) {
+   u8 tmpbuffer[CRYPTO_HKDF_MAX_DIGESTSIZE];
+
+   err = crypto_shash_finup(desc, , 1, tmpbuffer);
+   if (err)
+   goto out;
+   memcpy(dst, tmpbuffer, dlen);
+   memzero_explicit(tmpbuffer, h);
+   goto out;
+   } else {
+   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;
+}
+
+/*
+ * HKDF extract phase.
+ *
+ * The seed is defined to be a concatenation of the salt and the IKM.
+ * The data buffer is pre-pended by an rtattr which provides an u32 value
+ * with the length of the salt. Thus, the buffer length - salt length is the
+ * IKM length.
+ */
+static int crypto_hkdf_seed(struct crypto_rng *rng,
+   const u8 *seed, unsigned int slen)
+{
+   struct