Re: [PATCH 2/6] crypto: kdf - SP800-108 Key Derivation Function

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

Hi Eric,

[...]
> > 
> > +obj-$(CONFIG_CRYPTO_KDF) += kdf.o
> 
> This naming is too generic.  CONFIG_CRYPTO_KDF and kdf.c imply that this is
> related to all KDFs.  But actually it is an implementation of a few specific
> KDFs.  Can you give it a clearer name, like KDF_SP800?
> 
I am going to use kdf_sp800108 or CRYPTO_CONFIG_KDF_SP800108. The reason is 
that there are many SP800 documents.

Thanks

Ciao
Stephan




Re: [PATCH 2/6] crypto: kdf - SP800-108 Key Derivation Function

2019-01-11 Thread Eric Biggers
On Fri, Jan 11, 2019 at 08:10:02PM +0100, Stephan Müller wrote:
> The SP800-108 compliant Key Derivation Function is implemented as a
> random number generator considering that it behaves like a deterministic
> RNG.
> 
> All three KDF types specified in SP800-108 are implemented.
> 
> The code comments provide details about how to invoke the different KDF
> types.
> 
> Signed-off-by: Stephan Mueller 
> ---
>  crypto/Kconfig  |   7 +
>  crypto/Makefile |   1 +
>  crypto/kdf.c| 492 
>  3 files changed, 500 insertions(+)
>  create mode 100644 crypto/kdf.c
> 
> diff --git a/crypto/Kconfig b/crypto/Kconfig
> index 86960aa53e0f..cc80d89e0cf5 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -561,6 +561,13 @@ config CRYPTO_HMAC
> HMAC: Keyed-Hashing for Message Authentication (RFC2104).
> This is required for IPSec.
>  
> +config CRYPTO_KDF
> + tristate "Key Derivation Function (SP800-108)"
> + select CRYPTO_RNG
> + help
> +   Support for KDF compliant to SP800-108. All three types of
> +   KDF specified in SP800-108 are implemented.
> +
>  config CRYPTO_XCBC
>   tristate "XCBC support"
>   select CRYPTO_HASH
> diff --git a/crypto/Makefile b/crypto/Makefile
> index 799ed5e94606..69a0bb64b0ac 100644
> --- a/crypto/Makefile
> +++ b/crypto/Makefile
> @@ -58,6 +58,7 @@ crypto_user-y := crypto_user_base.o
>  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

This naming is too generic.  CONFIG_CRYPTO_KDF and kdf.c imply that this is
related to all KDFs.  But actually it is an implementation of a few specific
KDFs.  Can you give it a clearer name, like KDF_SP800?

- Eric


[PATCH 2/6] crypto: kdf - SP800-108 Key Derivation Function

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

All three KDF types specified in SP800-108 are implemented.

The code comments provide details about how to invoke the different KDF
types.

Signed-off-by: Stephan Mueller 
---
 crypto/Kconfig  |   7 +
 crypto/Makefile |   1 +
 crypto/kdf.c| 492 
 3 files changed, 500 insertions(+)
 create mode 100644 crypto/kdf.c

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 86960aa53e0f..cc80d89e0cf5 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -561,6 +561,13 @@ config CRYPTO_HMAC
  HMAC: Keyed-Hashing for Message Authentication (RFC2104).
  This is required for IPSec.
 
+config CRYPTO_KDF
+   tristate "Key Derivation Function (SP800-108)"
+   select CRYPTO_RNG
+   help
+ Support for KDF compliant to SP800-108. All three types of
+ KDF specified in SP800-108 are implemented.
+
 config CRYPTO_XCBC
tristate "XCBC support"
select CRYPTO_HASH
diff --git a/crypto/Makefile b/crypto/Makefile
index 799ed5e94606..69a0bb64b0ac 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -58,6 +58,7 @@ crypto_user-y := crypto_user_base.o
 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_VMAC) += vmac.o
 obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
 obj-$(CONFIG_CRYPTO_NULL2) += crypto_null.o
diff --git a/crypto/kdf.c b/crypto/kdf.c
new file mode 100644
index ..2c6dd8676a9f
--- /dev/null
+++ b/crypto/kdf.c
@@ -0,0 +1,492 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * SP800-108 Key-derivation function
+ *
+ * Copyright (C) 2019, Stephan Mueller 
+ */
+
+/*
+ * For performing a KDF operation, the following input is required
+ * from the caller:
+ *
+ * * Keying material to be used to derive the new keys from
+ *   (denoted as Ko in SP800-108)
+ * * Label -- a free form binary string
+ * * Context -- a free form binary string
+ *
+ * The KDF is implemented as a random number generator.
+ *
+ * The Ko keying material is to be provided with the initialization of the KDF
+ * "random number generator", i.e. with the crypto_rng_reset function.
+ *
+ * The Label and Context concatenated string is provided when obtaining random
+ * numbers, i.e. with the crypto_rng_generate function. The caller must format
+ * the free-form Label || Context input as deemed necessary for the given
+ * purpose. Note, SP800-108 mandates that the Label and Context are separated
+ * by a 0x00 byte, i.e. the caller shall provide the input as
+ * Label || 0x00 || Context when trying to be compliant to SP800-108. For
+ * the feedback KDF, an IV is required as documented below.
+ *
+ * Example without proper error handling:
+ * char *keying_material = "\x00\x11\x22\x33\x44\x55\x66\x77";
+ * char *label_context = "\xde\xad\xbe\xef\x00\xde\xad\xbe\xef";
+ * kdf = crypto_alloc_rng(name, 0, 0);
+ * crypto_rng_reset(kdf, keying_material, 8);
+ * crypto_rng_generate(kdf, label_context, 9, outbuf, outbuflen);
+ *
+ * NOTE: In-place cipher operations are not supported.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct crypto_kdf_ctx {
+   struct crypto_shash *kmd;
+};
+
+#define CRYPTO_KDF_MAX_DIGESTSIZE  64
+#define CRYPTO_KDF_MAX_ALIGNMASK   0x3f
+
+static inline void crypto_kdf_init_desc(struct shash_desc *desc,
+   struct crypto_shash *kmd)
+{
+   desc->tfm = kmd;
+   desc->flags = crypto_shash_get_flags(kmd) & CRYPTO_TFM_REQ_MAY_SLEEP;
+}
+
+/*
+ * Implementation of the KDF in double pipeline iteration mode according with
+ * counter to SP800-108 section 5.3.
+ *
+ * The caller must provide Label || 0x00 || Context in src. This src pointer
+ * may also be NULL if the caller wishes not to provide anything.
+ */
+static int crypto_kdf_dpi_random(struct crypto_rng *rng,
+const u8 *src, unsigned int slen,
+u8 *dst, unsigned int dlen)
+{
+   struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));
+   struct crypto_shash *kmd = ctx->kmd;
+   SHASH_DESC_ON_STACK(desc, kmd);
+   __be32 counter = cpu_to_be32(1);
+   unsigned int h = crypto_shash_digestsize(kmd);
+   unsigned int alignmask = crypto_shash_alignmask(kmd);
+   int err = 0;
+   u8 *dst_orig = dst;
+   u8 Aiblock[CRYPTO_KDF_MAX_DIGESTSIZE + CRYPTO_KDF_MAX_ALIGNMASK];
+   u8 *Ai = PTR_ALIGN((u8 *)Aiblock, alignmask + 1);
+
+   crypto_kdf_init_desc(desc, kmd);
+
+   memset(Ai, 0, h);
+
+   while (dlen) {
+   /* Calculate A(i) */
+   if (dst == dst_orig && src && slen)
+   /* 5.3 step 4 and 5.a */
+   err = crypto_shash_di