Linux cryptographic layer development
 help / color / mirror / Atom feed
* [PATCH] crypto: sha3 - Add missing ULL suffixes for 64-bit constants
From: Geert Uytterhoeven @ 2016-08-03 17:37 UTC (permalink / raw)
  To: Jeff Garzik, Raveendra Padasalagi, Herbert Xu, David S. Miller
  Cc: linux-crypto, linux-kernel, Geert Uytterhoeven

On 32-bit (e.g. with m68k-linux-gnu-gcc-4.1):

    crypto/sha3_generic.c:27: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:28: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:29: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:29: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:31: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:31: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:32: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:32: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:32: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:33: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:33: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:34: warning: integer constant is too large for ‘long’ type
    crypto/sha3_generic.c:34: warning: integer constant is too large for ‘long’ type

Fixes: 53964b9ee63b7075 ("crypto: sha3 - Add SHA-3 hash algorithm")
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 crypto/sha3_generic.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/crypto/sha3_generic.c b/crypto/sha3_generic.c
index 62264397a2d28636..7e8ed96236cefa79 100644
--- a/crypto/sha3_generic.c
+++ b/crypto/sha3_generic.c
@@ -24,14 +24,14 @@
 #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
 
 static const u64 keccakf_rndc[24] = {
-	0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
-	0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
-	0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
-	0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
-	0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
-	0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
-	0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
-	0x8000000000008080, 0x0000000080000001, 0x8000000080008008
+	0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
+	0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
+	0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
+	0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
+	0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
+	0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
+	0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
+	0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
 };
 
 static const int keccakf_rotc[24] = {
-- 
1.9.1

^ permalink raw reply related

* nopea Lainat
From: varainhoitoelimen @ 2016-08-02 21:52 UTC (permalink / raw)
  To: Recipients

Apply for a loan at 2% reply to this Email for more Info

Hae lainaa 2% vastausta tähän viestiin lisätietoja

^ permalink raw reply

* [PATCH] crypto: crc32c-vpmsum - Convert to CPU feature based module autoloading
From: Anton Blanchard @ 2016-08-04  6:38 UTC (permalink / raw)
  To: benh, paulus, mpe, herbert, davem; +Cc: alastair, linuxppc-dev, linux-crypto

From: Anton Blanchard <anton@samba.org>

This patch utilises the GENERIC_CPU_AUTOPROBE infrastructure
to automatically load the crc32c-vpmsum module if the CPU supports
it.

Signed-off-by: Anton Blanchard <anton@samba.org>
---
 arch/powerpc/crypto/crc32c-vpmsum_glue.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/crypto/crc32c-vpmsum_glue.c b/arch/powerpc/crypto/crc32c-vpmsum_glue.c
index bfe3d37..9fa046d 100644
--- a/arch/powerpc/crypto/crc32c-vpmsum_glue.c
+++ b/arch/powerpc/crypto/crc32c-vpmsum_glue.c
@@ -4,6 +4,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/cpufeature.h>
 #include <asm/switch_to.h>
 
 #define CHKSUM_BLOCK_SIZE	1
@@ -157,7 +158,7 @@ static void __exit crc32c_vpmsum_mod_fini(void)
 	crypto_unregister_shash(&alg);
 }
 
-module_init(crc32c_vpmsum_mod_init);
+module_cpu_feature_match(PPC_MODULE_FEATURE_VEC_CRYPTO, crc32c_vpmsum_mod_init);
 module_exit(crc32c_vpmsum_mod_fini);
 
 MODULE_AUTHOR("Anton Blanchard <anton@samba.org>");
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH] crypto: crc32c-vpmsum - Convert to CPU feature based module autoloading
From: Michael Ellerman @ 2016-08-04  8:38 UTC (permalink / raw)
  To: Anton Blanchard, benh, paulus, herbert, davem
  Cc: linuxppc-dev, linux-crypto, alastair
In-Reply-To: <1470292695-9829-1-git-send-email-anton@ozlabs.org>

Anton Blanchard <anton@ozlabs.org> writes:

> From: Anton Blanchard <anton@samba.org>
>
> This patch utilises the GENERIC_CPU_AUTOPROBE infrastructure
> to automatically load the crc32c-vpmsum module if the CPU supports
> it.
>
> Signed-off-by: Anton Blanchard <anton@samba.org>
> ---
>  arch/powerpc/crypto/crc32c-vpmsum_glue.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/crypto/crc32c-vpmsum_glue.c b/arch/powerpc/crypto/crc32c-vpmsum_glue.c
> index bfe3d37..9fa046d 100644
> --- a/arch/powerpc/crypto/crc32c-vpmsum_glue.c
> +++ b/arch/powerpc/crypto/crc32c-vpmsum_glue.c
> @@ -4,6 +4,7 @@
>  #include <linux/module.h>
>  #include <linux/string.h>
>  #include <linux/kernel.h>
> +#include <linux/cpufeature.h>
>  #include <asm/switch_to.h>
>  
>  #define CHKSUM_BLOCK_SIZE	1
> @@ -157,7 +158,7 @@ static void __exit crc32c_vpmsum_mod_fini(void)
>  	crypto_unregister_shash(&alg);
>  }
>  
> -module_init(crc32c_vpmsum_mod_init);
> +module_cpu_feature_match(PPC_MODULE_FEATURE_VEC_CRYPTO, crc32c_vpmsum_mod_init);

Is VEC_CRYPTO the right feature?

That's new power8 crypto stuff.

I thought this only used VMX? (but I haven't looked closely)

cheers

^ permalink raw reply

* Re: [PATCH] crypto: crc32c-vpmsum - Convert to CPU feature based module autoloading
From: Anton Blanchard @ 2016-08-04 10:26 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: herbert, paulus, linux-crypto, alastair, linuxppc-dev, davem
In-Reply-To: <87lh0dexp3.fsf@concordia.ellerman.id.au>

Hi Michael,

> Is VEC_CRYPTO the right feature?
> 
> That's new power8 crypto stuff.

The vpmsum* instructions are part of the same pipeline as the vcipher*
instructions, introduced in POWER8.

> I thought this only used VMX? (but I haven't looked closely)

Yes, vcipher* and vpmsum* are VMX instructions.

Anton

^ permalink raw reply

* [PATCHv3 00/11] crypto: omap HW crypto fixes
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel

Hi,

This revision took quite a bit time to craft due to the rework needed
for sham buffer handling and export/import. I ended up implementing
a flush functionality for draining out the sham buffer when doing
export/import; just shrinking the buffer to sufficiently small size
impacted the performance with small data chunks too much so I dropped
this approach.

The series also fixes a couple of existing issues with omap2/omap3
hardware acceleration, I ran a full boot test / crypto manager
test suite on all boards accessible to me now.

Based on top of latest mainline, which is somewhere before 4.8-rc1
as of writing this, I am unable to rebase the series during the next
three weeks so wanted to get this out now. Targeted for 4.9 merge
window, some fixes could be picked up earlier though if needed.

-Tero

^ permalink raw reply

* [PATCHv3 01/11] crypto: omap-sham: avoid executing tasklet where not needed
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

Some of the call paths of OMAP SHA driver can avoid executing the next
step of the crypto queue under tasklet; instead, execute the next step
directly via function call. This avoids a costly round-trip via the
scheduler giving a slight performance boost.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-sham.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 7fe4eef..fd50005 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -1005,9 +1005,6 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
 
 	if (req->base.complete)
 		req->base.complete(&req->base, err);
-
-	/* handle new request */
-	tasklet_schedule(&dd->done_task);
 }
 
 static int omap_sham_handle_queue(struct omap_sham_dev *dd,
@@ -1018,6 +1015,7 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
 	unsigned long flags;
 	int err = 0, ret = 0;
 
+retry:
 	spin_lock_irqsave(&dd->lock, flags);
 	if (req)
 		ret = ahash_enqueue_request(&dd->queue, req);
@@ -1061,11 +1059,19 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
 		err = omap_sham_final_req(dd);
 	}
 err1:
-	if (err != -EINPROGRESS)
+	dev_dbg(dd->dev, "exit, err: %d\n", err);
+
+	if (err != -EINPROGRESS) {
 		/* done_task will not finish it, so do it here */
 		omap_sham_finish_req(req, err);
+		req = NULL;
 
-	dev_dbg(dd->dev, "exit, err: %d\n", err);
+		/*
+		 * Execute next request immediately if there is anything
+		 * in queue.
+		 */
+		goto retry;
+	}
 
 	return ret;
 }
@@ -1653,6 +1659,10 @@ finish:
 	dev_dbg(dd->dev, "update done: err: %d\n", err);
 	/* finish curent request */
 	omap_sham_finish_req(dd->req, err);
+
+	/* If we are not busy, process next req */
+	if (!test_bit(FLAGS_BUSY, &dd->flags))
+		omap_sham_handle_queue(dd, NULL);
 }
 
 static irqreturn_t omap_sham_irq_common(struct omap_sham_dev *dd)
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 02/11] crypto: omap-sham: add support for flushing the buffer
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

This flushes any full blocks of data from the data buffer. Required for
implementing the export/import APIs for the driver, as the flush allows
saving a much smaller context; basically only one block of buffer is
required.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-sham.c | 60 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index fd50005..6e53944 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -112,6 +112,7 @@
 #define FLAGS_DMA_READY		6
 #define FLAGS_AUTO_XOR		7
 #define FLAGS_BE32_SHA1		8
+#define FLAGS_FLUSH		9
 /* context flags */
 #define FLAGS_FINUP		16
 #define FLAGS_SG		17
@@ -996,15 +997,16 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
 		ctx->flags |= BIT(FLAGS_ERROR);
 	}
 
-	/* atomic operation is not needed here */
-	dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
-			BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY));
-
 	pm_runtime_mark_last_busy(dd->dev);
 	pm_runtime_put_autosuspend(dd->dev);
 
-	if (req->base.complete)
+	if (!test_bit(FLAGS_FLUSH, &dd->flags) && req->base.complete)
 		req->base.complete(&req->base, err);
+
+	/* atomic operation is not needed here */
+	dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
+		       BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY) |
+		       BIT(FLAGS_FLUSH));
 }
 
 static int omap_sham_handle_queue(struct omap_sham_dev *dd,
@@ -1329,6 +1331,54 @@ static void omap_sham_cra_exit(struct crypto_tfm *tfm)
 	}
 }
 
+static int omap_sham_flush(struct ahash_request *req)
+{
+	struct omap_sham_reqctx *rctx = ahash_request_ctx(req);
+	struct omap_sham_dev *dd = rctx->dd;
+	int ret, len, bs;
+	unsigned long flags;
+
+	bs = get_block_size(rctx);
+
+	len = rctx->bufcnt / bs * bs;
+
+	spin_lock_irqsave(&dd->lock, flags);
+
+	if (test_bit(FLAGS_BUSY, &dd->flags)) {
+		ret = -EINPROGRESS;
+		goto exit_unlock;
+	}
+
+	if (!len) {
+		ret = 0;
+		goto exit_unlock;
+	}
+
+	set_bit(FLAGS_BUSY, &dd->flags);
+
+	spin_unlock_irqrestore(&dd->lock, flags);
+
+	rctx->total = 0;
+
+	ret = omap_sham_hw_init(dd);
+	if (ret)
+		goto exit_unlock;
+
+	set_bit(FLAGS_FLUSH, &dd->flags);
+
+	ret = omap_sham_xmit_cpu(dd, rctx->buffer, len, 0);
+	if (ret == -EINPROGRESS) {
+		memcpy(rctx->buffer, rctx->buffer + len, rctx->bufcnt - len);
+		rctx->bufcnt -= len;
+	}
+
+	return ret;
+
+exit_unlock:
+	spin_unlock_irqrestore(&dd->lock, flags);
+	return ret;
+}
+
 static struct ahash_alg algs_sha1_md5[] = {
 {
 	.init		= omap_sham_init,
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 03/11] crypto: omap-sham: implement context export/import APIs
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

Context export/import are now required for ahash algorithms due to
required support in algif_hash. Implement these for OMAP SHA driver,
saving and restoring the internal state of the driver.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-sham.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 6e53944..aa71e61 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -1379,6 +1379,27 @@ exit_unlock:
 	return ret;
 }
 
+static int omap_sham_export(struct ahash_request *req, void *out)
+{
+	struct omap_sham_reqctx *rctx = ahash_request_ctx(req);
+
+	while (omap_sham_flush(req) == -EINPROGRESS)
+		msleep(10);
+
+	memcpy(out, rctx, sizeof(*rctx) + SHA512_BLOCK_SIZE);
+
+	return 0;
+}
+
+static int omap_sham_import(struct ahash_request *req, const void *in)
+{
+	struct omap_sham_reqctx *rctx = ahash_request_ctx(req);
+
+	memcpy(rctx, in, sizeof(*rctx) + SHA512_BLOCK_SIZE);
+
+	return 0;
+}
+
 static struct ahash_alg algs_sha1_md5[] = {
 {
 	.init		= omap_sham_init,
@@ -2037,8 +2058,14 @@ static int omap_sham_probe(struct platform_device *pdev)
 
 	for (i = 0; i < dd->pdata->algs_info_size; i++) {
 		for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
-			err = crypto_register_ahash(
-					&dd->pdata->algs_info[i].algs_list[j]);
+			struct ahash_alg *alg;
+
+			alg = &dd->pdata->algs_info[i].algs_list[j];
+			alg->export = omap_sham_export;
+			alg->import = omap_sham_import;
+			alg->halg.statesize = sizeof(struct omap_sham_reqctx) +
+				SHA512_BLOCK_SIZE;
+			err = crypto_register_ahash(alg);
 			if (err)
 				goto err_algs;
 
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 09/11] crypto: omap-aes: Add fallback support
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

From: Lokesh Vutla <lokeshvutla@ti.com>

As setting up the DMA operations is quite costly, add software fallback
support for requests smaller than 200 bytes. This change gives some 10%
extra performance in ipsec use case.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
[t-kristo@ti.com: udpated against latest upstream, to use skcipher mainly]
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/Kconfig    |  3 +++
 drivers/crypto/omap-aes.c | 53 +++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 1af94e2..19ee6ee 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -318,6 +318,9 @@ config CRYPTO_DEV_OMAP_AES
 	select CRYPTO_AES
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_ENGINE
+	select CRYPTO_CBC
+	select CRYPTO_ECB
+	select CRYPTO_CTR
 	help
 	  OMAP processors have AES module accelerator. Select this if you
 	  want to use the OMAP module for AES algorithms.
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 3cf7b8f..6ba4f70 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -35,7 +35,7 @@
 #include <linux/interrupt.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/aes.h>
-#include <crypto/algapi.h>
+#include <crypto/internal/skcipher.h>
 
 #define DST_MAXBURST			4
 #define DMA_MIN				(DST_MAXBURST * sizeof(u32))
@@ -105,6 +105,7 @@ struct omap_aes_ctx {
 	int		keylen;
 	u32		key[AES_KEYSIZE_256 / sizeof(u32)];
 	unsigned long	flags;
+	struct crypto_skcipher	*fallback;
 };
 
 struct omap_aes_reqctx {
@@ -701,11 +702,29 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
 			crypto_ablkcipher_reqtfm(req));
 	struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req);
 	struct omap_aes_dev *dd;
+	int ret;
 
 	pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes,
 		  !!(mode & FLAGS_ENCRYPT),
 		  !!(mode & FLAGS_CBC));
 
+	if (req->nbytes < 200) {
+		SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
+
+		skcipher_request_set_tfm(subreq, ctx->fallback);
+		skcipher_request_set_callback(subreq, req->base.flags, NULL,
+					      NULL);
+		skcipher_request_set_crypt(subreq, req->src, req->dst,
+					   req->nbytes, req->info);
+
+		if (mode & FLAGS_ENCRYPT)
+			ret = crypto_skcipher_encrypt(subreq);
+		else
+			ret = crypto_skcipher_decrypt(subreq);
+
+		skcipher_request_zero(subreq);
+		return ret;
+	}
 	dd = omap_aes_find_dev(ctx);
 	if (!dd)
 		return -ENODEV;
@@ -721,6 +740,7 @@ static int omap_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
 			   unsigned int keylen)
 {
 	struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	int ret;
 
 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
 		   keylen != AES_KEYSIZE_256)
@@ -731,6 +751,14 @@ static int omap_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
 	memcpy(ctx->key, key, keylen);
 	ctx->keylen = keylen;
 
+	crypto_skcipher_clear_flags(ctx->fallback, CRYPTO_TFM_REQ_MASK);
+	crypto_skcipher_set_flags(ctx->fallback, tfm->base.crt_flags &
+						 CRYPTO_TFM_REQ_MASK);
+
+	ret = crypto_skcipher_setkey(ctx->fallback, key, keylen);
+	if (!ret)
+		return 0;
+
 	return 0;
 }
 
@@ -766,6 +794,17 @@ static int omap_aes_ctr_decrypt(struct ablkcipher_request *req)
 
 static int omap_aes_cra_init(struct crypto_tfm *tfm)
 {
+	const char *name = crypto_tfm_alg_name(tfm);
+	const u32 flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK;
+	struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_skcipher *blk;
+
+	blk = crypto_alloc_skcipher(name, 0, flags);
+	if (IS_ERR(blk))
+		return PTR_ERR(blk);
+
+	ctx->fallback = blk;
+
 	tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx);
 
 	return 0;
@@ -773,6 +812,12 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm)
 
 static void omap_aes_cra_exit(struct crypto_tfm *tfm)
 {
+	struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	if (ctx->fallback)
+		crypto_free_skcipher(ctx->fallback);
+
+	ctx->fallback = NULL;
 }
 
 /* ********************** ALGS ************************************ */
@@ -784,7 +829,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
 	.cra_priority		= 300,
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
 				  CRYPTO_ALG_KERN_DRIVER_ONLY |
-				  CRYPTO_ALG_ASYNC,
+				  CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
 	.cra_alignmask		= 0,
@@ -806,7 +851,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
 	.cra_priority		= 300,
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
 				  CRYPTO_ALG_KERN_DRIVER_ONLY |
-				  CRYPTO_ALG_ASYNC,
+				  CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
 	.cra_alignmask		= 0,
@@ -832,7 +877,7 @@ static struct crypto_alg algs_ctr[] = {
 	.cra_priority		= 300,
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
 				  CRYPTO_ALG_KERN_DRIVER_ONLY |
-				  CRYPTO_ALG_ASYNC,
+				  CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
 	.cra_alignmask		= 0,
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 07/11] crypto: omap-aes: use runtime_pm autosuspend for clock handling
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

Calling runtime PM API at the cra_init/exit is bad for power management
purposes, as the lifetime for a CRA can be very long. Instead, use
pm_runtime autosuspend approach for handling the device clocks. Clocks
are enabled when they are actually required, and autosuspend disables
these if they have not been used for a sufficiently long time period.
By default, the timeout value is 1 second.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-aes.c | 43 ++++++++++++++++---------------------------
 1 file changed, 16 insertions(+), 27 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 4ab53a6..f443042 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -85,6 +85,8 @@
 #define AES_REG_IRQ_DATA_OUT           BIT(2)
 #define DEFAULT_TIMEOUT		(5*HZ)
 
+#define DEFAULT_AUTOSUSPEND_DELAY	1000
+
 #define FLAGS_MODE_MASK		0x000f
 #define FLAGS_ENCRYPT		BIT(0)
 #define FLAGS_CBC		BIT(1)
@@ -238,11 +240,19 @@ static void omap_aes_write_n(struct omap_aes_dev *dd, u32 offset,
 
 static int omap_aes_hw_init(struct omap_aes_dev *dd)
 {
+	int err;
+
 	if (!(dd->flags & FLAGS_INIT)) {
 		dd->flags |= FLAGS_INIT;
 		dd->err = 0;
 	}
 
+	err = pm_runtime_get_sync(dd->dev);
+	if (err < 0) {
+		dev_err(dd->dev, "failed to get sync: %d\n", err);
+		return err;
+	}
+
 	return 0;
 }
 
@@ -520,6 +530,9 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
 	pr_debug("err: %d\n", err);
 
 	crypto_finalize_request(dd->engine, req, err);
+
+	pm_runtime_mark_last_busy(dd->dev);
+	pm_runtime_put_autosuspend(dd->dev);
 }
 
 static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
@@ -761,23 +774,6 @@ static int omap_aes_ctr_decrypt(struct ablkcipher_request *req)
 
 static int omap_aes_cra_init(struct crypto_tfm *tfm)
 {
-	struct omap_aes_dev *dd = NULL;
-	int err;
-
-	/* Find AES device, currently picks the first device */
-	spin_lock_bh(&list_lock);
-	list_for_each_entry(dd, &dev_list, list) {
-		break;
-	}
-	spin_unlock_bh(&list_lock);
-
-	err = pm_runtime_get_sync(dd->dev);
-	if (err < 0) {
-		dev_err(dd->dev, "%s: failed to get_sync(%d)\n",
-			__func__, err);
-		return err;
-	}
-
 	tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx);
 
 	return 0;
@@ -785,16 +781,6 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm)
 
 static void omap_aes_cra_exit(struct crypto_tfm *tfm)
 {
-	struct omap_aes_dev *dd = NULL;
-
-	/* Find AES device, currently picks the first device */
-	spin_lock_bh(&list_lock);
-	list_for_each_entry(dd, &dev_list, list) {
-		break;
-	}
-	spin_unlock_bh(&list_lock);
-
-	pm_runtime_put_sync(dd->dev);
 }
 
 /* ********************** ALGS ************************************ */
@@ -1140,6 +1126,9 @@ static int omap_aes_probe(struct platform_device *pdev)
 	}
 	dd->phys_base = res.start;
 
+	pm_runtime_use_autosuspend(dev);
+	pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY);
+
 	pm_runtime_enable(dev);
 	err = pm_runtime_get_sync(dev);
 	if (err < 0) {
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 10/11] crypto: omap-aes: fix crypto engine initialization order
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

The crypto engine must be initialized before registering algorithms,
otherwise the test manager will crash as it attempts to execute
tests for the algos while they are being registered.

Fixes: 0529900a01cb ("crypto: omap-aes - Support crypto engine framework")
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-aes.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 6ba4f70..8159523 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -1212,6 +1212,17 @@ static int omap_aes_probe(struct platform_device *pdev)
 	list_add_tail(&dd->list, &dev_list);
 	spin_unlock(&list_lock);
 
+	/* Initialize crypto engine */
+	dd->engine = crypto_engine_alloc_init(dev, 1);
+	if (!dd->engine)
+		goto err_engine;
+
+	dd->engine->prepare_request = omap_aes_prepare_req;
+	dd->engine->crypt_one_request = omap_aes_crypt_req;
+	err = crypto_engine_start(dd->engine);
+	if (err)
+		goto err_engine;
+
 	for (i = 0; i < dd->pdata->algs_info_size; i++) {
 		if (!dd->pdata->algs_info[i].registered) {
 			for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
@@ -1229,26 +1240,17 @@ static int omap_aes_probe(struct platform_device *pdev)
 		}
 	}
 
-	/* Initialize crypto engine */
-	dd->engine = crypto_engine_alloc_init(dev, 1);
-	if (!dd->engine)
-		goto err_algs;
-
-	dd->engine->prepare_request = omap_aes_prepare_req;
-	dd->engine->crypt_one_request = omap_aes_crypt_req;
-	err = crypto_engine_start(dd->engine);
-	if (err)
-		goto err_engine;
-
 	return 0;
-err_engine:
-	crypto_engine_exit(dd->engine);
 err_algs:
 	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
 		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
 			crypto_unregister_alg(
 					&dd->pdata->algs_info[i].algs_list[j]);
 
+err_engine:
+	if (dd->engine)
+		crypto_engine_exit(dd->engine);
+
 	omap_aes_dma_cleanup(dd);
 err_irq:
 	tasklet_kill(&dd->done_task);
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 11/11] crypto: omap-des: fix crypto engine initialization order
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

The crypto engine must be initialized before registering algorithms,
otherwise the test manager will crash as it attempts to execute
tests for the algos while they are being registered.

Fixes: f1b77aaca85a ("crypto: omap-des - Integrate with the crypto engine framework")
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-des.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
index d0b59f6..2b07e60 100644
--- a/drivers/crypto/omap-des.c
+++ b/drivers/crypto/omap-des.c
@@ -1085,6 +1085,17 @@ static int omap_des_probe(struct platform_device *pdev)
 	list_add_tail(&dd->list, &dev_list);
 	spin_unlock(&list_lock);
 
+	/* Initialize des crypto engine */
+	dd->engine = crypto_engine_alloc_init(dev, 1);
+	if (!dd->engine)
+		goto err_engine;
+
+	dd->engine->prepare_request = omap_des_prepare_req;
+	dd->engine->crypt_one_request = omap_des_crypt_req;
+	err = crypto_engine_start(dd->engine);
+	if (err)
+		goto err_engine;
+
 	for (i = 0; i < dd->pdata->algs_info_size; i++) {
 		for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
 			algp = &dd->pdata->algs_info[i].algs_list[j];
@@ -1100,27 +1111,18 @@ static int omap_des_probe(struct platform_device *pdev)
 		}
 	}
 
-	/* Initialize des crypto engine */
-	dd->engine = crypto_engine_alloc_init(dev, 1);
-	if (!dd->engine)
-		goto err_algs;
-
-	dd->engine->prepare_request = omap_des_prepare_req;
-	dd->engine->crypt_one_request = omap_des_crypt_req;
-	err = crypto_engine_start(dd->engine);
-	if (err)
-		goto err_engine;
-
 	return 0;
 
-err_engine:
-	crypto_engine_exit(dd->engine);
 err_algs:
 	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
 		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
 			crypto_unregister_alg(
 					&dd->pdata->algs_info[i].algs_list[j]);
 
+err_engine:
+	if (dd->engine)
+		crypto_engine_exit(dd->engine);
+
 	omap_des_dma_cleanup(dd);
 err_irq:
 	tasklet_kill(&dd->done_task);
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 05/11] crypto: omap-sham: fix SW fallback HMAC handling for omap2/omap3
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

If software fallback is used on older hardware accelerator setup (OMAP2/
OMAP3), the first block of data must be purged from the buffer. The
first block contains the pre-generated ipad value required by the HW,
but the software fallback algorithm generates its own, causing wrong
results.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-sham.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index b4f5131..f9c5fe5 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -1145,9 +1145,20 @@ static int omap_sham_final_shash(struct ahash_request *req)
 {
 	struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+	int offset = 0;
+
+	/*
+	 * If we are running HMAC on limited hardware support, skip
+	 * the ipad in the beginning of the buffer if we are going for
+	 * software fallback algorithm.
+	 */
+	if (test_bit(FLAGS_HMAC, &ctx->flags) &&
+	    !test_bit(FLAGS_AUTO_XOR, &ctx->dd->flags))
+		offset = get_block_size(ctx);
 
 	return omap_sham_shash_digest(tctx->fallback, req->base.flags,
-				      ctx->buffer, ctx->bufcnt, req->result);
+				      ctx->buffer + offset,
+				      ctx->bufcnt - offset, req->result);
 }
 
 static int omap_sham_final(struct ahash_request *req)
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 06/11] crypto: omap-des: Fix support for unequal lengths
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel, Lokesh Vutla
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

From: Lokesh Vutla <a0131933@ti.com>

For cases where total length of an input SGs is not same as
length of the input data for encryption, omap-des driver
crashes. This happens in the case when IPsec is trying to use
omap-des driver.

To avoid this, we copy all the pages from the input SG list
into a contiguous buffer and prepare a single element SG list
for this buffer with length as the total bytes to crypt, which is
similar thing that is done in case of unaligned lengths.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Tested-by: Aparna Balasubramanian <aparnab@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-des.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
index 5691434..d0b59f6 100644
--- a/drivers/crypto/omap-des.c
+++ b/drivers/crypto/omap-des.c
@@ -521,29 +521,36 @@ static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
 	return 0;
 }
 
-static int omap_des_copy_needed(struct scatterlist *sg)
+static int omap_des_copy_needed(struct scatterlist *sg, int total)
 {
+	int len = 0;
+
+	if (!IS_ALIGNED(total, DES_BLOCK_SIZE))
+		return -1;
+
 	while (sg) {
 		if (!IS_ALIGNED(sg->offset, 4))
 			return -1;
 		if (!IS_ALIGNED(sg->length, DES_BLOCK_SIZE))
 			return -1;
+
+		len += sg->length;
 		sg = sg_next(sg);
 	}
+
+	if (len != total)
+		return -1;
+
 	return 0;
 }
 
 static int omap_des_copy_sgs(struct omap_des_dev *dd)
 {
 	void *buf_in, *buf_out;
-	int pages;
-
-	pages = dd->total >> PAGE_SHIFT;
-
-	if (dd->total & (PAGE_SIZE-1))
-		pages++;
+	int pages, total;
 
-	BUG_ON(!pages);
+	total = ALIGN(dd->total, DES_BLOCK_SIZE);
+	pages = get_order(total);
 
 	buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
 	buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages);
@@ -605,8 +612,8 @@ static int omap_des_prepare_req(struct crypto_engine *engine,
 	if (dd->out_sg_len < 0)
 		return dd->out_sg_len;
 
-	if (omap_des_copy_needed(dd->in_sg) ||
-	    omap_des_copy_needed(dd->out_sg)) {
+	if (omap_des_copy_needed(dd->in_sg, dd->total) ||
+	    omap_des_copy_needed(dd->out_sg, dd->total)) {
 		if (omap_des_copy_sgs(dd))
 			pr_err("Failed to copy SGs for unaligned cases\n");
 		dd->sgs_copied = 1;
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 04/11] crypto: omap-sham: fix software fallback handling
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

If we have processed any data with the hardware accelerator (digcnt > 0),
we must complete the entire hash by using it. This is because the current
hash value can't be imported to the software fallback algorithm. Otherwise
we end up with wrong hash results.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-sham.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index aa71e61..b4f5131 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -1165,7 +1165,7 @@ static int omap_sham_final(struct ahash_request *req)
 	 * If buffersize is less than 240, we use fallback SW encoding,
 	 * as using DMA + HW in this case doesn't provide any benefit.
 	 */
-	if ((ctx->digcnt + ctx->bufcnt) < 240)
+	if (!ctx->digcnt && ctx->bufcnt < 240)
 		return omap_sham_final_shash(req);
 	else if (ctx->bufcnt)
 		return omap_sham_enqueue(req, OP_FINAL);
-- 
1.9.1

^ permalink raw reply related

* [PATCHv3 08/11] crypto: omap-aes: Add support for multiple cores
From: Tero Kristo @ 2016-08-04 10:28 UTC (permalink / raw)
  To: herbert, lokeshvutla, davem, linux-crypto, tony, linux-omap
  Cc: linux-arm-kernel
In-Reply-To: <1470306526-27219-1-git-send-email-t-kristo@ti.com>

From: Lokesh Vutla <lokeshvutla@ti.com>

Some SoCs like omap4/omap5/dra7 contain multiple AES crypto accelerator
cores. Adapt the driver to support this. The driver picks the last used
device from a list of AES devices.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
[t-kristo@ti.com: forward ported to 4.7 kernel]
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/crypto/omap-aes.c | 20 ++++++--------------
 1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index f443042..3cf7b8f 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -329,20 +329,12 @@ static void omap_aes_dma_stop(struct omap_aes_dev *dd)
 
 static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
 {
-	struct omap_aes_dev *dd = NULL, *tmp;
+	struct omap_aes_dev *dd;
 
 	spin_lock_bh(&list_lock);
-	if (!ctx->dd) {
-		list_for_each_entry(tmp, &dev_list, list) {
-			/* FIXME: take fist available aes core */
-			dd = tmp;
-			break;
-		}
-		ctx->dd = dd;
-	} else {
-		/* already found before */
-		dd = ctx->dd;
-	}
+	dd = list_first_entry(&dev_list, struct omap_aes_dev, list);
+	list_move_tail(&dd->list, &dev_list);
+	ctx->dd = dd;
 	spin_unlock_bh(&list_lock);
 
 	return dd;
@@ -615,7 +607,7 @@ static int omap_aes_prepare_req(struct crypto_engine *engine,
 {
 	struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
 			crypto_ablkcipher_reqtfm(req));
-	struct omap_aes_dev *dd = omap_aes_find_dev(ctx);
+	struct omap_aes_dev *dd = ctx->dd;
 	struct omap_aes_reqctx *rctx;
 
 	if (!dd)
@@ -661,7 +653,7 @@ static int omap_aes_crypt_req(struct crypto_engine *engine,
 {
 	struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
 			crypto_ablkcipher_reqtfm(req));
-	struct omap_aes_dev *dd = omap_aes_find_dev(ctx);
+	struct omap_aes_dev *dd = ctx->dd;
 
 	if (!dd)
 		return -ENODEV;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 0/2] crypto: caam - authenc fixes
From: Horia Geantă @ 2016-08-04 17:02 UTC (permalink / raw)
  To: Herbert Xu; +Cc: linux-crypto, David S. Miller

The first patch fixes a few typos in the encrypt shared descriptor
used by echainiv(authenc) algorithms.

Second patch fixes the case when .setkey is called before .setauthsize,
avoiding creating authenc descriptors with zero authsize.

Both patches are also being sent to -stable for v4.3+ kernels.

Thanks,
Horia

Horia Geantă (2):
  crypto: caam - fix echainiv(authenc) encrypt shared descriptor
  crypto: caam - defer aead_set_sh_desc in case of zero authsize

 drivers/crypto/caam/caamalg.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

-- 
2.4.4

^ permalink raw reply

* [PATCH 1/2] crypto: caam - fix echainiv(authenc) encrypt shared descriptor
From: Horia Geantă @ 2016-08-04 17:02 UTC (permalink / raw)
  To: Herbert Xu; +Cc: linux-crypto, David S. Miller
In-Reply-To: <1470330167-31534-1-git-send-email-horia.geanta@nxp.com>

There are a few things missed by the conversion to the
new AEAD interface:

1 - echainiv(authenc) encrypt shared descriptor

The shared descriptor is incorrect: due to the order of operations,
at some point in time MATH3 register is being overwritten.

2 - buffer used for echainiv(authenc) encrypt shared descriptor

Encrypt and givencrypt shared descriptors (for AEAD ops) are mutually
exclusive and thus use the same buffer in context state: sh_desc_enc.

However, there's one place missed by s/sh_desc_givenc/sh_desc_enc,
leading to errors when echainiv(authenc(...)) algorithms are used:
DECO: desc idx 14: Header Error. Invalid length or parity, or
certain other problems.

While here, also fix a typo: dma_mapping_error() is checking
for validity of sh_desc_givenc_dma instead of sh_desc_enc_dma.

Cc: <stable@vger.kernel.org> # 4.3+
Fixes: 479bcc7c5b9e ("crypto: caam - Convert authenc to new AEAD interface")
Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
---
 drivers/crypto/caam/caamalg.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index ea8189f4b021..e356005a7212 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -614,7 +614,7 @@ skip_enc:
 		keys_fit_inline = true;
 
 	/* aead_givencrypt shared descriptor */
-	desc = ctx->sh_desc_givenc;
+	desc = ctx->sh_desc_enc;
 
 	/* Note: Context registers are saved. */
 	init_sh_desc_key_aead(desc, ctx, keys_fit_inline, is_rfc3686);
@@ -645,13 +645,13 @@ copy_iv:
 	append_operation(desc, ctx->class2_alg_type |
 			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
 
-	/* ivsize + cryptlen = seqoutlen - authsize */
-	append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
-
 	/* Read and write assoclen bytes */
 	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
 	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
 
+	/* ivsize + cryptlen = seqoutlen - authsize */
+	append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
 	/* Skip assoc data */
 	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
 
@@ -697,7 +697,7 @@ copy_iv:
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
-	if (dma_mapping_error(jrdev, ctx->sh_desc_givenc_dma)) {
+	if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-- 
2.4.4

^ permalink raw reply related

* [PATCH 2/2] crypto: caam - defer aead_set_sh_desc in case of zero authsize
From: Horia Geantă @ 2016-08-04 17:02 UTC (permalink / raw)
  To: Herbert Xu; +Cc: linux-crypto, David S. Miller
In-Reply-To: <1470330167-31534-1-git-send-email-horia.geanta@nxp.com>

To be able to generate shared descriptors for AEAD, the authentication size
needs to be known. However, there is no imposed order of calling .setkey,
.setauthsize callbacks.

Thus, in case authentication size is not known at .setkey time, defer it
until .setauthsize is called.

The authsize != 0 check was incorrectly removed when converting the driver
to the new AEAD interface.

Cc: <stable@vger.kernel.org> # 4.3+
Fixes: 479bcc7c5b9e ("crypto: caam - Convert authenc to new AEAD interface")
Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
---
 drivers/crypto/caam/caamalg.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index e356005a7212..6dc597126b79 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -441,6 +441,9 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 			       OP_ALG_AAI_CTR_MOD128);
 	const bool is_rfc3686 = alg->caam.rfc3686;
 
+	if (!ctx->authsize)
+		return 0;
+
 	/* NULL encryption / decryption */
 	if (!ctx->enckeylen)
 		return aead_null_set_sh_desc(aead);
-- 
2.4.4

^ permalink raw reply related

* [PATCH v4 4/4] crypto: kdf - enable compilation
From: Stephan Mueller @ 2016-08-04 18:41 UTC (permalink / raw)
  To: Mat Martineau; +Cc: David Howells, keyrings, linux-crypto
In-Reply-To: <1908905.sE4dlalNOn@positron.chronox.de>

Include KDF into Kconfig and Makefile for compilation.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/Kconfig  | 7 +++++++
 crypto/Makefile | 1 +
 2 files changed, 8 insertions(+)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index a9377be..91ef2a6 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -372,6 +372,13 @@ config CRYPTO_KEYWRAP
 	  Support for key wrapping (NIST SP800-38F / RFC3394) without
 	  padding.
 
+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.
+
 comment "Hash modes"
 
 config CRYPTO_CMAC
diff --git a/crypto/Makefile b/crypto/Makefile
index 99cc64a..9022280 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -80,6 +80,7 @@ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_XTS) += xts.o
 obj-$(CONFIG_CRYPTO_CTR) += ctr.o
 obj-$(CONFIG_CRYPTO_KEYWRAP) += keywrap.o
+obj-$(CONFIG_CRYPTO_KDF) += kdf.o
 obj-$(CONFIG_CRYPTO_GCM) += gcm.o
 obj-$(CONFIG_CRYPTO_CCM) += ccm.o
 obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 0/4] crypto: Key Derivation Function (SP800-108)
From: Stephan Mueller @ 2016-08-04 18:39 UTC (permalink / raw)
  To: Mat Martineau; +Cc: David Howells, keyrings, linux-crypto
In-Reply-To: <2239809.KsND40bFeW@positron.chronox.de>

Hi,

this patch set implements all three key derivation functions defined in
SP800-108.

The implementation is provided as a template for random number generators,
since a KDF can be considered a form of deterministic RNG where the key
material is used as a seed.

With the KDF implemented as a template, all types of keyed and
non-keyed hashes can be utilized, including HMAC and CMAC. The testmgr
tests are derived from publicly available test vectors from NIST.

The KDF are all tested with a complete round of CAVS testing on 32 and 64 bit.

The patch set introduces an extension to the kernel crypto API in the first
patch by adding a template handling for random number generators based on the
same logic as for keyed hashes.

Changes v4:
* removal of the check that src and dst buffers are not the same from the KDF
  implementations as requested by Herbert
* implement and use new free API in the RNG instance handling as requested
  by Herbert
* move the instance handling code from include/crypto/rng.h to
  include/crypto/internal/rng.h

Changes v3:
* port testmgr patch to current cryptodev-2.6 tree
* add non-keyed KDF references to testmgr.c

Changes v2:
* port to 4.7-rc1

Stephan Mueller (4):
  crypto: add template handling for RNGs
  crypto: kdf - add known answer tests
  crypto: kdf - SP800-108 Key Derivation Function
  crypto: kdf - enable compilation

 crypto/Kconfig                |   7 +
 crypto/Makefile               |   1 +
 crypto/kdf.c                  | 508 ++++++++++++++++++++++++++++++++++++++++++
 crypto/rng.c                  |  32 +++
 crypto/testmgr.c              | 226 +++++++++++++++++++
 crypto/testmgr.h              | 110 +++++++++
 include/crypto/internal/rng.h |  38 ++++
 7 files changed, 922 insertions(+)
 create mode 100644 crypto/kdf.c

-- 
2.7.4

^ permalink raw reply

* [PATCH v4 1/4] crypto: add template handling for RNGs
From: Stephan Mueller @ 2016-08-04 18:40 UTC (permalink / raw)
  To: Mat Martineau; +Cc: David Howells, keyrings, linux-crypto
In-Reply-To: <1908905.sE4dlalNOn@positron.chronox.de>

This patch adds the ability to register templates for RNGs. RNGs are
"meta" mechanisms using raw cipher primitives. Thus, RNGs can now be
implemented as templates to allow the complete flexibility the kernel
crypto API provides.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/rng.c                  | 32 ++++++++++++++++++++++++++++++++
 include/crypto/internal/rng.h | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/crypto/rng.c b/crypto/rng.c
index b81cffb..e12bd30 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -63,6 +63,13 @@ static int crypto_rng_init_tfm(struct crypto_tfm *tfm)
 	return 0;
 }
 
+static void crypto_rng_free_instance(struct crypto_instance *inst)
+{
+	struct rng_instance *rng = rng_instance(inst);
+
+	rng->free(rng);
+}
+
 static unsigned int seedsize(struct crypto_alg *alg)
 {
 	struct rng_alg *ralg = container_of(alg, struct rng_alg, base);
@@ -105,6 +112,7 @@ static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
 static const struct crypto_type crypto_rng_type = {
 	.extsize = crypto_alg_extsize,
 	.init_tfm = crypto_rng_init_tfm,
+	.free = crypto_rng_free_instance,
 #ifdef CONFIG_PROC_FS
 	.show = crypto_rng_show,
 #endif
@@ -232,5 +240,29 @@ void crypto_unregister_rngs(struct rng_alg *algs, int count)
 }
 EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
 
+static int rng_prepare_alg(struct rng_alg *alg)
+{
+	struct crypto_alg *base = &alg->base;
+
+	base->cra_type = &crypto_rng_type;
+	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+	base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
+
+	return 0;
+}
+
+int rng_register_instance(struct crypto_template *tmpl,
+			  struct rng_instance *inst)
+{
+	int err;
+
+	err = rng_prepare_alg(&inst->alg);
+	if (err)
+		return err;
+
+	return crypto_register_instance(tmpl, rng_crypto_instance(inst));
+}
+EXPORT_SYMBOL_GPL(rng_register_instance);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Random Number Generator");
diff --git a/include/crypto/internal/rng.h b/include/crypto/internal/rng.h
index a52ef34..30ff076 100644
--- a/include/crypto/internal/rng.h
+++ b/include/crypto/internal/rng.h
@@ -42,4 +42,42 @@ static inline void crypto_rng_set_entropy(struct crypto_rng *tfm,
 	crypto_rng_alg(tfm)->set_ent(tfm, data, len);
 }
 
+struct rng_instance {
+	void (*free)(struct rng_instance *inst);
+	struct rng_alg alg;
+};
+
+static inline struct rng_instance *rng_alloc_instance(
+	const char *name, struct crypto_alg *alg)
+{
+	return crypto_alloc_instance2(name, alg,
+			      sizeof(struct rng_instance) - sizeof(*alg));
+}
+
+static inline struct crypto_instance *rng_crypto_instance(
+	struct rng_instance *inst)
+{
+	return container_of(&inst->alg.base, struct crypto_instance, alg);
+}
+
+static inline void *rng_instance_ctx(struct rng_instance *inst)
+{
+	return crypto_instance_ctx(rng_crypto_instance(inst));
+}
+
+static inline struct rng_alg *__crypto_rng_alg(struct crypto_alg *alg)
+{
+	return container_of(alg, struct rng_alg, base);
+}
+
+static inline struct rng_instance *rng_instance(
+	struct crypto_instance *inst)
+{
+	return container_of(__crypto_rng_alg(&inst->alg),
+			    struct rng_instance, alg);
+}
+
+int rng_register_instance(struct crypto_template *tmpl,
+			  struct rng_instance *inst);
+
 #endif
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 2/4] crypto: kdf - add known answer tests
From: Stephan Mueller @ 2016-08-04 18:40 UTC (permalink / raw)
  To: Mat Martineau; +Cc: David Howells, keyrings, linux-crypto
In-Reply-To: <1908905.sE4dlalNOn@positron.chronox.de>

Add known answer tests to the testmgr for the KDF (SP800-108) cipher.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/testmgr.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 crypto/testmgr.h | 110 +++++++++++++++++++++++++++
 2 files changed, 336 insertions(+)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 5c9d5a5..e63b21e 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -116,6 +116,11 @@ struct drbg_test_suite {
 	unsigned int count;
 };
 
+struct kdf_test_suite {
+	struct kdf_testvec *vecs;
+	unsigned int count;
+};
+
 struct akcipher_test_suite {
 	struct akcipher_testvec *vecs;
 	unsigned int count;
@@ -139,6 +144,7 @@ struct alg_test_desc {
 		struct hash_test_suite hash;
 		struct cprng_test_suite cprng;
 		struct drbg_test_suite drbg;
+		struct kdf_test_suite kdf;
 		struct akcipher_test_suite akcipher;
 		struct kpp_test_suite kpp;
 	} suite;
@@ -1758,6 +1764,64 @@ outbuf:
 	return ret;
 }
 
+static int kdf_cavs_test(struct kdf_testvec *test,
+			 const char *driver, u32 type, u32 mask)
+{
+	int ret = -EAGAIN;
+	struct crypto_rng *drng;
+	unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
+
+	if (!buf)
+		return -ENOMEM;
+
+	drng = crypto_alloc_rng(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	if (IS_ERR(drng)) {
+		printk(KERN_ERR "alg: kdf: could not allocate cipher handle "
+		       "for %s\n", driver);
+		kzfree(buf);
+		return -ENOMEM;
+	}
+
+	ret = crypto_rng_reset(drng, test->K1, test->K1len);
+	if (ret) {
+		printk(KERN_ERR "alg: kdf: could not set key derivation key\n");
+		goto err;
+	}
+
+	ret = crypto_rng_generate(drng, test->context, test->contextlen,
+				  buf, test->expectedlen);
+	if (ret) {
+		printk(KERN_ERR "alg: kdf: could not obtain key data\n");
+		goto err;
+	}
+
+	ret = memcmp(test->expected, buf, test->expectedlen);
+
+err:
+	crypto_free_rng(drng);
+	kzfree(buf);
+	return ret;
+}
+
+static int alg_test_kdf(const struct alg_test_desc *desc, const char *driver,
+			u32 type, u32 mask)
+{
+	int err = 0;
+	unsigned int i = 0;
+	struct kdf_testvec *template = desc->suite.kdf.vecs;
+	unsigned int tcount = desc->suite.kdf.count;
+
+	for (i = 0; i < tcount; i++) {
+		err = kdf_cavs_test(&template[i], driver, type, mask);
+		if (err) {
+			printk(KERN_ERR "alg: kdf: Test %d failed for %s\n",
+			       i, driver);
+			err = -EINVAL;
+			break;
+		}
+	}
+	return err;
+}
 
 static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
 			 u32 type, u32 mask)
@@ -3467,6 +3531,168 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.fips_allowed = 1,
 		.test = alg_test_null,
 	}, {
+		.alg = "kdf_ctr(cmac(aes))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(cmac(des3_ede))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(hmac(sha1))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(hmac(sha224))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(hmac(sha256))",
+		.test = alg_test_kdf,
+		.fips_allowed = 1,
+		.suite = {
+			.kdf = {
+				.vecs = kdf_ctr_hmac_sha256_tv_template,
+				.count = ARRAY_SIZE(kdf_ctr_hmac_sha256_tv_template)
+			}
+		}
+	}, {
+		.alg = "kdf_ctr(hmac(sha384))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(hmac(sha512))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(sha1)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(sha224)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(sha256)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(sha384)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_ctr(sha512)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(cmac(aes))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(cmac(des3_ede))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(hmac(sha1))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(hmac(sha224))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(hmac(sha256))",
+		.test = alg_test_kdf,
+		.fips_allowed = 1,
+		.suite = {
+			.kdf = {
+				.vecs = kdf_dpi_hmac_sha256_tv_template,
+				.count = ARRAY_SIZE(kdf_dpi_hmac_sha256_tv_template)
+			}
+		}
+	}, {
+		.alg = "kdf_dpi(hmac(sha384))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(hmac(sha512))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(sha1)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(sha224)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(sha256)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(sha384)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_dpi(sha512)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(cmac(aes))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(cmac(des3_ede))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(hmac(sha1))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(hmac(sha224))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(hmac(sha256))",
+		.test = alg_test_kdf,
+		.fips_allowed = 1,
+		.suite = {
+			.kdf = {
+				.vecs = kdf_fb_hmac_sha256_tv_template,
+				.count = ARRAY_SIZE(kdf_fb_hmac_sha256_tv_template)
+			}
+		}
+	}, {
+		.alg = "kdf_fb(hmac(sha384))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(hmac(sha512))",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(sha1)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(sha224)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(sha256)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(sha384)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "kdf_fb(sha512)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
 		.alg = "kw(aes)",
 		.test = alg_test_skcipher,
 		.fips_allowed = 1,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index acb6bbf..1fe93ed 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -123,6 +123,15 @@ struct drbg_testvec {
 	size_t expectedlen;
 };
 
+struct kdf_testvec {
+	unsigned char *K1;
+	size_t K1len;
+	unsigned char *context;
+	size_t contextlen;
+	unsigned char *expected;
+	size_t expectedlen;
+};
+
 struct akcipher_testvec {
 	unsigned char *key;
 	unsigned char *m;
@@ -25827,6 +25836,107 @@ static struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] = {
 	},
 };
 
+/*
+ * Test vector obtained from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/KBKDF800-108/CounterMode.zip
+ */
+static struct kdf_testvec kdf_ctr_hmac_sha256_tv_template[] = {
+	{
+		.K1 = (unsigned char *)
+			"\xdd\x1d\x91\xb7\xd9\x0b\x2b\xd3"
+			"\x13\x85\x33\xce\x92\xb2\x72\xfb"
+			"\xf8\xa3\x69\x31\x6a\xef\xe2\x42"
+			"\xe6\x59\xcc\x0a\xe2\x38\xaf\xe0",
+		.K1len = 32,
+		.context = (unsigned char *)
+			"\x01\x32\x2b\x96\xb3\x0a\xcd\x19"
+			"\x79\x79\x44\x4e\x46\x8e\x1c\x5c"
+			"\x68\x59\xbf\x1b\x1c\xf9\x51\xb7"
+			"\xe7\x25\x30\x3e\x23\x7e\x46\xb8"
+			"\x64\xa1\x45\xfa\xb2\x5e\x51\x7b"
+			"\x08\xf8\x68\x3d\x03\x15\xbb\x29"
+			"\x11\xd8\x0a\x0e\x8a\xba\x17\xf3"
+			"\xb4\x13\xfa\xac",
+		.contextlen = 60,
+		.expected = (unsigned char *)
+			"\x10\x62\x13\x42\xbf\xb0\xfd\x40"
+			"\x04\x6c\x0e\x29\xf2\xcf\xdb\xf0",
+		.expectedlen = 16
+	}
+};
+
+/*
+ * Test vector obtained from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/KBKDF800-108/FeedbackModeNOzeroiv.zip
+ */
+static struct kdf_testvec kdf_fb_hmac_sha256_tv_template[] = {
+	{
+		.K1 = (unsigned char *)
+			"\x93\xf6\x98\xe8\x42\xee\xd7\x53"
+			"\x94\xd6\x29\xd9\x57\xe2\xe8\x9c"
+			"\x6e\x74\x1f\x81\x0b\x62\x3c\x8b"
+			"\x90\x1e\x38\x37\x6d\x06\x8e\x7b",
+		.K1len = 32,
+		.context = (unsigned char *)
+			"\x9f\x57\x5d\x90\x59\xd3\xe0\xc0"
+			"\x80\x3f\x08\x11\x2f\x8a\x80\x6d"
+			"\xe3\xc3\x47\x19\x12\xcd\xf4\x2b"
+			"\x09\x53\x88\xb1\x4b\x33\x50\x8e"
+			"\x53\xb8\x9c\x18\x69\x0e\x20\x57"
+			"\xa1\xd1\x67\x82\x2e\x63\x6d\xe5"
+			"\x0b\xe0\x01\x85\x32\xc4\x31\xf7"
+			"\xf5\xe3\x7f\x77\x13\x92\x20\xd5"
+			"\xe0\x42\x59\x9e\xbe\x26\x6a\xf5"
+			"\x76\x7e\xe1\x8c\xd2\xc5\xc1\x9a"
+			"\x1f\x0f\x80",
+		.contextlen = 83,
+		.expected = (unsigned char *)
+			"\xbd\x14\x76\xf4\x3a\x4e\x31\x57"
+			"\x47\xcf\x59\x18\xe0\xea\x5b\xc0"
+			"\xd9\x87\x69\x45\x74\x77\xc3\xab"
+			"\x18\xb7\x42\xde\xf0\xe0\x79\xa9"
+			"\x33\xb7\x56\x36\x5a\xfb\x55\x41"
+			"\xf2\x53\xfe\xe4\x3c\x6f\xd7\x88"
+			"\xa4\x40\x41\x03\x85\x09\xe9\xee"
+			"\xb6\x8f\x7d\x65\xff\xbb\x5f\x95",
+		.expectedlen = 64
+	}
+};
+
+/*
+ * Test vector obtained from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/KBKDF800-108/PipelineModewithCounter.zip
+ */
+static struct kdf_testvec kdf_dpi_hmac_sha256_tv_template[] = {
+	{
+		.K1 = (unsigned char *)
+			"\x02\xd3\x6f\xa0\x21\xc2\x0d\xdb"
+			"\xde\xe4\x69\xf0\x57\x94\x68\xba"
+			"\xe5\xcb\x13\xb5\x48\xb6\xc6\x1c"
+			"\xdf\x9d\x3e\xc4\x19\x11\x1d\xe2",
+		.K1len = 32,
+		.context = (unsigned char *)
+			"\x85\xab\xe3\x8b\xf2\x65\xfb\xdc"
+			"\x64\x45\xae\x5c\x71\x15\x9f\x15"
+			"\x48\xc7\x3b\x7d\x52\x6a\x62\x31"
+			"\x04\x90\x4a\x0f\x87\x92\x07\x0b"
+			"\x3d\xf9\x90\x2b\x96\x69\x49\x04"
+			"\x25\xa3\x85\xea\xdb\x0f\x9c\x76"
+			"\xe4\x6f\x0f",
+		.contextlen = 51,
+		.expected = (unsigned char *)
+			"\xd6\x9f\x74\xf5\x18\xc9\xf6\x4f"
+			"\x90\xa0\xbe\xeb\xab\x69\xf6\x89"
+			"\xb7\x3b\x5c\x13\xeb\x0f\x86\x0a"
+			"\x95\xca\xd7\xd9\x81\x4f\x8c\x50"
+			"\x6e\xb7\xb1\x79\xa5\xc5\xb4\x46"
+			"\x6a\x9e\xc1\x54\xc3\xbf\x1c\x13"
+			"\xef\xd6\xec\x0d\x82\xb0\x2c\x29"
+			"\xaf\x2c\x69\x02\x99\xed\xc4\x53",
+		.expectedlen = 64
+	}
+};
+
 /* Cast5 test vectors from RFC 2144 */
 #define CAST5_ENC_TEST_VECTORS		4
 #define CAST5_DEC_TEST_VECTORS		4
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 3/4] crypto: kdf - SP800-108 Key Derivation Function
From: Stephan Mueller @ 2016-08-04 18:40 UTC (permalink / raw)
  To: Mat Martineau; +Cc: David Howells, keyrings, linux-crypto
In-Reply-To: <1908905.sE4dlalNOn@positron.chronox.de>

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 <smueller@chronox.de>
---
 crypto/kdf.c | 508 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 508 insertions(+)
 create mode 100644 crypto/kdf.c

diff --git a/crypto/kdf.c b/crypto/kdf.c
new file mode 100644
index 0000000..6f9f082
--- /dev/null
+++ b/crypto/kdf.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2016, Stephan Mueller <smueller@chronox.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL2
+ * are required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+/*
+ * 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 <linux/module.h>
+#include <crypto/rng.h>
+#include <crypto/internal/rng.h>
+#include <crypto/hash.h>
+#include <crypto/internal/hash.h>
+
+struct crypto_kdf_ctx {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+/* convert 32 bit integer into its string representation */
+static inline void crypto_kw_cpu_to_be32(u32 val, u8 *buf)
+{
+	__be32 *a = (__be32 *)buf;
+
+	*a = cpu_to_be32(val);
+}
+
+/*
+ * 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 shash_desc *desc = &ctx->shash;
+	unsigned int h = crypto_shash_digestsize(desc->tfm);
+	unsigned int alignmask = crypto_shash_alignmask(desc->tfm);
+	int err = 0;
+	u8 *dst_orig = dst;
+	u8 Aiblock[h + alignmask];
+	u8 *Ai = PTR_ALIGN((u8 *)Aiblock, alignmask + 1);
+	u32 i = 1;
+	u8 iteration[sizeof(u32)];
+
+	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_digest(desc, src, slen, Ai);
+		else
+			/* 5.3 step 5.a */
+			err = crypto_shash_digest(desc, Ai, h, Ai);
+		if (err)
+			goto err;
+
+		/* Calculate K(i) -- step 5.b */
+		err = crypto_shash_init(desc);
+		if (err)
+			goto err;
+
+		err = crypto_shash_update(desc, Ai, h);
+		if (err)
+			goto err;
+
+		crypto_kw_cpu_to_be32(i, iteration);
+		err = crypto_shash_update(desc, iteration, sizeof(u32));
+		if (err)
+			goto err;
+		if (src && slen) {
+			err = crypto_shash_update(desc, src, slen);
+			if (err)
+				goto err;
+		}
+
+		if (dlen < h) {
+			u8 tmpbuffer[h];
+
+			err = crypto_shash_final(desc, tmpbuffer);
+			if (err)
+				goto err;
+			memcpy(dst, tmpbuffer, dlen);
+			memzero_explicit(tmpbuffer, h);
+			goto ret;
+		} else {
+			err = crypto_shash_final(desc, dst);
+			if (err)
+				goto err;
+			dlen -= h;
+			dst += h;
+			i++;
+		}
+	}
+
+err:
+	memzero_explicit(dst_orig, dlen);
+ret:
+	memzero_explicit(Ai, h);
+	return err;
+}
+
+/*
+ * Implementation of the KDF in feedback mode with a non-NULL IV and with
+ * counter according to SP800-108 section 5.2. The IV is supplied with src
+ * and must be equal to the digestsize of the used cipher.
+ *
+ * In addition, the caller must provide Label || 0x00 || Context in src. This
+ * src pointer must not be NULL as the IV is required. The ultimate format of
+ * the src pointer is IV || Label || 0x00 || Context where the length of the
+ * IV is equal to the output size of the PRF.
+ */
+static int crypto_kdf_fb_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 shash_desc *desc = &ctx->shash;
+	unsigned int h = crypto_shash_digestsize(desc->tfm);
+	int err = 0;
+	u8 *dst_orig = dst;
+	const u8 *label;
+	unsigned int labellen = 0;
+	u32 i = 1;
+	u8 iteration[sizeof(u32)];
+
+	/* require the presence of an IV */
+	if (!src || slen < h)
+		return -EINVAL;
+
+	/* calculate the offset of the label / context data */
+	label = src + h;
+	labellen = slen - h;
+
+	while (dlen) {
+		err = crypto_shash_init(desc);
+		if (err)
+			goto err;
+
+		/*
+		 * Feedback mode applies to all rounds except first which uses
+		 * the IV.
+		 */
+		if (dst_orig == dst)
+			err = crypto_shash_update(desc, src, h);
+		else
+			err = crypto_shash_update(desc, dst - h, h);
+		if (err)
+			goto err;
+
+		crypto_kw_cpu_to_be32(i, iteration);
+		err = crypto_shash_update(desc, iteration, sizeof(u32));
+		if (err)
+			goto err;
+		if (labellen) {
+			err = crypto_shash_update(desc, label, labellen);
+			if (err)
+				goto err;
+		}
+
+		if (dlen < h) {
+			u8 tmpbuffer[h];
+
+			err = crypto_shash_final(desc, tmpbuffer);
+			if (err)
+				goto err;
+			memcpy(dst, tmpbuffer, dlen);
+			memzero_explicit(tmpbuffer, h);
+			return 0;
+		} else {
+			err = crypto_shash_final(desc, dst);
+			if (err)
+				goto err;
+			dlen -= h;
+			dst += h;
+			i++;
+		}
+	}
+
+	return 0;
+
+err:
+	memzero_explicit(dst_orig, dlen);
+	return err;
+}
+
+/*
+ * Implementation of the KDF in counter mode according to SP800-108 section 5.1
+ * as well as SP800-56A section 5.8.1 (Single-step KDF).
+ *
+ * SP800-108:
+ * The caller must provide Label || 0x00 || Context in src. This src pointer
+ * may also be NULL if the caller wishes not to provide anything.
+ *
+ * SP800-56A:
+ * The key provided for the HMAC during the crypto_rng_reset shall NOT be the
+ * shared secret from the DH operation, but an independently generated key.
+ * The src pointer is defined as Z || other info where Z is the shared secret
+ * from DH and other info is an arbitrary string (see SP800-56A section
+ * 5.8.1.2).
+ */
+static int crypto_kdf_ctr_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 shash_desc *desc = &ctx->shash;
+	unsigned int h = crypto_shash_digestsize(desc->tfm);
+	int err = 0;
+	u8 *dst_orig = dst;
+	u32 i = 1;
+	u8 iteration[sizeof(u32)];
+
+	while (dlen) {
+		err = crypto_shash_init(desc);
+		if (err)
+			goto err;
+
+		crypto_kw_cpu_to_be32(i, iteration);
+		err = crypto_shash_update(desc, iteration, sizeof(u32));
+		if (err)
+			goto err;
+
+		if (src && slen) {
+			err = crypto_shash_update(desc, src, slen);
+			if (err)
+				goto err;
+		}
+
+		if (dlen < h) {
+			u8 tmpbuffer[h];
+
+			err = crypto_shash_final(desc, tmpbuffer);
+			if (err)
+				goto err;
+			memcpy(dst, tmpbuffer, dlen);
+			memzero_explicit(tmpbuffer, h);
+			return 0;
+		} else {
+			err = crypto_shash_final(desc, dst);
+			if (err)
+				goto err;
+
+			dlen -= h;
+			dst += h;
+			i++;
+		}
+	}
+
+	return 0;
+
+err:
+	memzero_explicit(dst_orig, dlen);
+	return err;
+}
+
+/*
+ * The seeding of the KDF allows to set a key which must be at least
+ * digestsize long.
+ */
+static int crypto_kdf_seed(struct crypto_rng *rng,
+			   const u8 *seed, unsigned int slen)
+{
+	struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));
+	unsigned int ds = crypto_shash_digestsize(ctx->shash.tfm);
+
+	/* Check according to SP800-108 section 7.2 */
+	if (ds > slen)
+		return -EINVAL;
+
+	/*
+	 * We require that we operate on a MAC -- if we do not operate on a
+	 * MAC, this function returns an error.
+	 */
+	return crypto_shash_setkey(ctx->shash.tfm, seed, slen);
+}
+
+static int crypto_kdf_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+	struct crypto_shash_spawn *spawn = crypto_instance_ctx(inst);
+	struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_shash *hash;
+
+	hash = crypto_spawn_shash(spawn);
+	if (IS_ERR(hash))
+		return PTR_ERR(hash);
+
+	ctx->shash.tfm = hash;
+
+	return 0;
+}
+
+static void crypto_kdf_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto_free_shash(ctx->shash.tfm);
+}
+
+static void crypto_kdf_free(struct rng_instance *inst)
+{
+	crypto_drop_spawn(rng_instance_ctx(inst));
+	kfree(inst);
+}
+
+static int crypto_kdf_alloc_common(struct crypto_template *tmpl,
+				   struct rtattr **tb,
+				   const u8 *name,
+				   int (*generate)(struct crypto_rng *tfm,
+						   const u8 *src,
+						   unsigned int slen,
+						   u8 *dst, unsigned int dlen))
+{
+	struct rng_instance *inst;
+	struct crypto_alg *alg;
+	struct shash_alg *salg;
+	int err;
+	unsigned int ds, ss;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_RNG);
+	if (err)
+		return err;
+
+	salg = shash_attr_alg(tb[1], 0, 0);
+	if (IS_ERR(salg))
+		return PTR_ERR(salg);
+
+	ds = salg->digestsize;
+	ss = salg->statesize;
+	alg = &salg->base;
+
+	inst = rng_alloc_instance(name, alg);
+	err = PTR_ERR(inst);
+	if (IS_ERR(inst))
+		goto out_put_alg;
+
+	err = crypto_init_shash_spawn(rng_instance_ctx(inst), salg,
+				      rng_crypto_instance(inst));
+	if (err)
+		goto out_free_inst;
+
+	inst->alg.base.cra_priority	= alg->cra_priority;
+	inst->alg.base.cra_blocksize	= alg->cra_blocksize;
+	inst->alg.base.cra_alignmask	= alg->cra_alignmask;
+
+	inst->alg.generate		= generate;
+	inst->alg.seed			= crypto_kdf_seed;
+	inst->alg.seedsize		= ds;
+
+	inst->alg.base.cra_init		= crypto_kdf_init_tfm;
+	inst->alg.base.cra_exit		= crypto_kdf_exit_tfm;
+	inst->alg.base.cra_ctxsize	= ALIGN(sizeof(struct crypto_kdf_ctx) +
+					  ss * 2, crypto_tfm_ctx_alignment());
+
+	inst->free			= crypto_kdf_free;
+
+	err = rng_register_instance(tmpl, inst);
+
+	if (err) {
+out_free_inst:
+		crypto_kdf_free(inst);
+	}
+
+out_put_alg:
+	crypto_mod_put(alg);
+	return err;
+}
+
+static int crypto_kdf_ctr_create(struct crypto_template *tmpl,
+				 struct rtattr **tb)
+{
+	return crypto_kdf_alloc_common(tmpl, tb, "kdf_ctr",
+				       crypto_kdf_ctr_random);
+}
+
+static struct crypto_template crypto_kdf_ctr_tmpl = {
+	.name = "kdf_ctr",
+	.create = crypto_kdf_ctr_create,
+	.module = THIS_MODULE,
+};
+
+static int crypto_kdf_fb_create(struct crypto_template *tmpl,
+				struct rtattr **tb) {
+	return crypto_kdf_alloc_common(tmpl, tb, "kdf_fb",
+				       crypto_kdf_fb_random);
+}
+
+static struct crypto_template crypto_kdf_fb_tmpl = {
+	.name = "kdf_fb",
+	.create = crypto_kdf_fb_create,
+	.module = THIS_MODULE,
+};
+
+static int crypto_kdf_dpi_create(struct crypto_template *tmpl,
+				 struct rtattr **tb) {
+	return crypto_kdf_alloc_common(tmpl, tb, "kdf_dpi",
+				       crypto_kdf_dpi_random);
+}
+
+static struct crypto_template crypto_kdf_dpi_tmpl = {
+	.name = "kdf_dpi",
+	.create = crypto_kdf_dpi_create,
+	.module = THIS_MODULE,
+};
+
+static int __init crypto_kdf_init(void)
+{
+	int err = crypto_register_template(&crypto_kdf_ctr_tmpl);
+
+	if (err)
+		return err;
+
+	err = crypto_register_template(&crypto_kdf_fb_tmpl);
+	if (err) {
+		crypto_unregister_template(&crypto_kdf_ctr_tmpl);
+		return err;
+	}
+
+	err = crypto_register_template(&crypto_kdf_dpi_tmpl);
+	if (err) {
+		crypto_unregister_template(&crypto_kdf_ctr_tmpl);
+		crypto_unregister_template(&crypto_kdf_fb_tmpl);
+	}
+	return err;
+}
+
+static void __exit crypto_kdf_exit(void)
+{
+	crypto_unregister_template(&crypto_kdf_ctr_tmpl);
+	crypto_unregister_template(&crypto_kdf_fb_tmpl);
+	crypto_unregister_template(&crypto_kdf_dpi_tmpl);
+}
+
+module_init(crypto_kdf_init);
+module_exit(crypto_kdf_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Key Derivation Function according to SP800-108 and SP800-56A");
+MODULE_ALIAS_CRYPTO("kdf_ctr");
+MODULE_ALIAS_CRYPTO("kdf_fb");
+MODULE_ALIAS_CRYPTO("kdf_dpi");
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox