Linux cryptographic layer development
 help / color / mirror / Atom feed
* [PATCH 05/10] crypto: CCP AES crypto API support
From: Tom Lendacky @ 2013-11-12 17:46 UTC (permalink / raw)
  To: davem, linux-crypto, herbert; +Cc: linux-kernel
In-Reply-To: <20131112174558.19746.47262.stgit@tlendack-t1.amdoffice.net>

These routines provide crypto API support for AES on the AMD CCP.

Support for AES modes: ECB, CBC, OFB, CFB and CTR

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 drivers/crypto/ccp/ccp-crypto-aes.c |  375 +++++++++++++++++++++++++++++++++++
 1 file changed, 375 insertions(+)
 create mode 100644 drivers/crypto/ccp/ccp-crypto-aes.c

diff --git a/drivers/crypto/ccp/ccp-crypto-aes.c b/drivers/crypto/ccp/ccp-crypto-aes.c
new file mode 100644
index 0000000..f302a5b7
--- /dev/null
+++ b/drivers/crypto/ccp/ccp-crypto-aes.c
@@ -0,0 +1,375 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) AES crypto API support
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/ctr.h>
+#include <crypto/scatterwalk.h>
+
+#include "ccp-crypto.h"
+
+
+static int ccp_aes_complete(struct crypto_async_request *async_req, int ret)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+	struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+
+	if (ret)
+		return ret;
+
+	if (ctx->u.aes.mode != CCP_AES_MODE_ECB)
+		memcpy(req->info, rctx->iv, AES_BLOCK_SIZE);
+
+	return 0;
+}
+
+static int ccp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+			  unsigned int key_len)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm));
+	struct ccp_crypto_ablkcipher_alg *alg =
+		ccp_crypto_ablkcipher_alg(crypto_ablkcipher_tfm(tfm));
+
+	switch (key_len) {
+	case AES_KEYSIZE_128:
+		ctx->u.aes.type = CCP_AES_TYPE_128;
+		break;
+	case AES_KEYSIZE_192:
+		ctx->u.aes.type = CCP_AES_TYPE_192;
+		break;
+	case AES_KEYSIZE_256:
+		ctx->u.aes.type = CCP_AES_TYPE_256;
+		break;
+	default:
+		crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	ctx->u.aes.mode = alg->mode;
+	ctx->u.aes.key_len = key_len;
+
+	memcpy(ctx->u.aes.key, key, key_len);
+	sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
+
+	return 0;
+}
+
+static int ccp_aes_crypt(struct ablkcipher_request *req, bool encrypt)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+	struct scatterlist *iv_sg = NULL;
+	unsigned int iv_len = 0;
+	int ret;
+
+	if (!ctx->u.aes.key_len) {
+		pr_err("AES key not set\n");
+		return -EINVAL;
+	}
+
+	if (((ctx->u.aes.mode == CCP_AES_MODE_ECB) ||
+	     (ctx->u.aes.mode == CCP_AES_MODE_CBC) ||
+	     (ctx->u.aes.mode == CCP_AES_MODE_CFB)) &&
+	    (req->nbytes & (AES_BLOCK_SIZE - 1))) {
+		pr_err("AES request size is not a multiple of the block size\n");
+		return -EINVAL;
+	}
+
+	if (ctx->u.aes.mode != CCP_AES_MODE_ECB) {
+		if (!req->info) {
+			pr_err("AES IV not supplied");
+			return -EINVAL;
+		}
+
+		memcpy(rctx->iv, req->info, AES_BLOCK_SIZE);
+		iv_sg = &rctx->iv_sg;
+		iv_len = AES_BLOCK_SIZE;
+		sg_init_one(iv_sg, rctx->iv, iv_len);
+	}
+
+	memset(&rctx->cmd, 0, sizeof(rctx->cmd));
+	INIT_LIST_HEAD(&rctx->cmd.entry);
+	rctx->cmd.engine = CCP_ENGINE_AES;
+	rctx->cmd.u.aes.type = ctx->u.aes.type;
+	rctx->cmd.u.aes.mode = ctx->u.aes.mode;
+	rctx->cmd.u.aes.action =
+		(encrypt) ? CCP_AES_ACTION_ENCRYPT : CCP_AES_ACTION_DECRYPT;
+	rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;
+	rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;
+	rctx->cmd.u.aes.iv = iv_sg;
+	rctx->cmd.u.aes.iv_len = iv_len;
+	rctx->cmd.u.aes.src = req->src;
+	rctx->cmd.u.aes.src_len = req->nbytes;
+	rctx->cmd.u.aes.dst = req->dst;
+
+	ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
+
+	return ret;
+}
+
+static int ccp_aes_encrypt(struct ablkcipher_request *req)
+{
+	return ccp_aes_crypt(req, true);
+}
+
+static int ccp_aes_decrypt(struct ablkcipher_request *req)
+{
+	return ccp_aes_crypt(req, false);
+}
+
+static int ccp_aes_cra_init(struct crypto_tfm *tfm)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->complete = ccp_aes_complete;
+	ctx->u.aes.key_len = 0;
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx);
+
+	return 0;
+}
+
+static void ccp_aes_cra_exit(struct crypto_tfm *tfm)
+{
+}
+
+static int ccp_aes_rfc3686_complete(struct crypto_async_request *async_req,
+				    int ret)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+
+	/* Restore the original pointer */
+	req->info = rctx->rfc3686_info;
+
+	return ccp_aes_complete(async_req, ret);
+}
+
+static int ccp_aes_rfc3686_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+				  unsigned int key_len)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm));
+
+	if (key_len < CTR_RFC3686_NONCE_SIZE)
+		return -EINVAL;
+
+	key_len -= CTR_RFC3686_NONCE_SIZE;
+	memcpy(ctx->u.aes.nonce, key + key_len, CTR_RFC3686_NONCE_SIZE);
+
+	return ccp_aes_setkey(tfm, key, key_len);
+}
+
+static int ccp_aes_rfc3686_crypt(struct ablkcipher_request *req, bool encrypt)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+	u8 *iv;
+
+	/* Initialize the CTR block */
+	iv = rctx->rfc3686_iv;
+	memcpy(iv, ctx->u.aes.nonce, CTR_RFC3686_NONCE_SIZE);
+
+	iv += CTR_RFC3686_NONCE_SIZE;
+	memcpy(iv, req->info, CTR_RFC3686_IV_SIZE);
+
+	iv += CTR_RFC3686_IV_SIZE;
+	*(__be32 *)iv = cpu_to_be32(1);
+
+	/* Point to the new IV */
+	rctx->rfc3686_info = req->info;
+	req->info = rctx->rfc3686_iv;
+
+	return ccp_aes_crypt(req, encrypt);
+}
+
+static int ccp_aes_rfc3686_encrypt(struct ablkcipher_request *req)
+{
+	return ccp_aes_rfc3686_crypt(req, true);
+}
+
+static int ccp_aes_rfc3686_decrypt(struct ablkcipher_request *req)
+{
+	return ccp_aes_rfc3686_crypt(req, false);
+}
+
+static int ccp_aes_rfc3686_cra_init(struct crypto_tfm *tfm)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->complete = ccp_aes_rfc3686_complete;
+	ctx->u.aes.key_len = 0;
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx);
+
+	return 0;
+}
+
+static void ccp_aes_rfc3686_cra_exit(struct crypto_tfm *tfm)
+{
+}
+
+static struct crypto_alg ccp_aes_defaults = {
+	.cra_flags	= CRYPTO_ALG_TYPE_ABLKCIPHER |
+			  CRYPTO_ALG_ASYNC |
+			  CRYPTO_ALG_KERN_DRIVER_ONLY |
+			  CRYPTO_ALG_NEED_FALLBACK,
+	.cra_blocksize	= AES_BLOCK_SIZE,
+	.cra_ctxsize	= sizeof(struct ccp_ctx),
+	.cra_priority	= CCP_CRA_PRIORITY,
+	.cra_type	= &crypto_ablkcipher_type,
+	.cra_init	= ccp_aes_cra_init,
+	.cra_exit	= ccp_aes_cra_exit,
+	.cra_module	= THIS_MODULE,
+	.cra_ablkcipher	= {
+		.setkey		= ccp_aes_setkey,
+		.encrypt	= ccp_aes_encrypt,
+		.decrypt	= ccp_aes_decrypt,
+		.min_keysize	= AES_MIN_KEY_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+	},
+};
+
+static struct crypto_alg ccp_aes_rfc3686_defaults = {
+	.cra_flags	= CRYPTO_ALG_TYPE_ABLKCIPHER |
+			   CRYPTO_ALG_ASYNC |
+			   CRYPTO_ALG_KERN_DRIVER_ONLY |
+			   CRYPTO_ALG_NEED_FALLBACK,
+	.cra_blocksize	= CTR_RFC3686_BLOCK_SIZE,
+	.cra_ctxsize	= sizeof(struct ccp_ctx),
+	.cra_priority	= CCP_CRA_PRIORITY,
+	.cra_type	= &crypto_ablkcipher_type,
+	.cra_init	= ccp_aes_rfc3686_cra_init,
+	.cra_exit	= ccp_aes_rfc3686_cra_exit,
+	.cra_module	= THIS_MODULE,
+	.cra_ablkcipher	= {
+		.setkey		= ccp_aes_rfc3686_setkey,
+		.encrypt	= ccp_aes_rfc3686_encrypt,
+		.decrypt	= ccp_aes_rfc3686_decrypt,
+		.min_keysize	= AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
+	},
+};
+
+struct ccp_aes_def {
+	enum ccp_aes_mode mode;
+	const char *name;
+	const char *driver_name;
+	unsigned int blocksize;
+	unsigned int ivsize;
+	struct crypto_alg *alg_defaults;
+};
+
+static struct ccp_aes_def aes_algs[] = {
+	{
+		.mode		= CCP_AES_MODE_ECB,
+		.name		= "ecb(aes)",
+		.driver_name	= "ecb-aes-ccp",
+		.blocksize	= AES_BLOCK_SIZE,
+		.ivsize		= 0,
+		.alg_defaults	= &ccp_aes_defaults,
+	},
+	{
+		.mode		= CCP_AES_MODE_CBC,
+		.name		= "cbc(aes)",
+		.driver_name	= "cbc-aes-ccp",
+		.blocksize	= AES_BLOCK_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.alg_defaults	= &ccp_aes_defaults,
+	},
+	{
+		.mode		= CCP_AES_MODE_CFB,
+		.name		= "cfb(aes)",
+		.driver_name	= "cfb-aes-ccp",
+		.blocksize	= AES_BLOCK_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.alg_defaults	= &ccp_aes_defaults,
+	},
+	{
+		.mode		= CCP_AES_MODE_OFB,
+		.name		= "ofb(aes)",
+		.driver_name	= "ofb-aes-ccp",
+		.blocksize	= 1,
+		.ivsize		= AES_BLOCK_SIZE,
+		.alg_defaults	= &ccp_aes_defaults,
+	},
+	{
+		.mode		= CCP_AES_MODE_CTR,
+		.name		= "ctr(aes)",
+		.driver_name	= "ctr-aes-ccp",
+		.blocksize	= 1,
+		.ivsize		= AES_BLOCK_SIZE,
+		.alg_defaults	= &ccp_aes_defaults,
+	},
+	{
+		.mode		= CCP_AES_MODE_CTR,
+		.name		= "rfc3686(ctr(aes))",
+		.driver_name	= "rfc3686-ctr-aes-ccp",
+		.blocksize	= 1,
+		.ivsize		= CTR_RFC3686_IV_SIZE,
+		.alg_defaults	= &ccp_aes_rfc3686_defaults,
+	},
+};
+
+static int ccp_register_aes_alg(struct list_head *head,
+				const struct ccp_aes_def *def)
+{
+	struct ccp_crypto_ablkcipher_alg *ccp_alg;
+	struct crypto_alg *alg;
+	int ret;
+
+	ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
+	if (!ccp_alg)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&ccp_alg->entry);
+
+	ccp_alg->mode = def->mode;
+
+	/* Copy the defaults and override as necessary */
+	alg = &ccp_alg->alg;
+	memcpy(alg, def->alg_defaults, sizeof(*alg));
+	snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+	snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+		 def->driver_name);
+	alg->cra_blocksize = def->blocksize;
+	alg->cra_ablkcipher.ivsize = def->ivsize;
+
+	ret = crypto_register_alg(alg);
+	if (ret) {
+		pr_err("%s ablkcipher algorithm registration error (%d)\n",
+			alg->cra_name, ret);
+		kfree(ccp_alg);
+		return ret;
+	}
+
+	list_add(&ccp_alg->entry, head);
+
+	return 0;
+}
+
+int ccp_register_aes_algs(struct list_head *head)
+{
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
+		ret = ccp_register_aes_alg(head, &aes_algs[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}

^ permalink raw reply related

* [PATCH 07/10] crypto: CCP XTS-AES crypto API support
From: Tom Lendacky @ 2013-11-12 17:46 UTC (permalink / raw)
  To: davem, linux-crypto, herbert; +Cc: linux-kernel
In-Reply-To: <20131112174558.19746.47262.stgit@tlendack-t1.amdoffice.net>

These routines provide crypto API support for the XTS-AES mode of AES
on the AMD CCP.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 drivers/crypto/ccp/ccp-crypto-aes-xts.c |  285 +++++++++++++++++++++++++++++++
 1 file changed, 285 insertions(+)
 create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-xts.c

diff --git a/drivers/crypto/ccp/ccp-crypto-aes-xts.c b/drivers/crypto/ccp/ccp-crypto-aes-xts.c
new file mode 100644
index 0000000..d100b48
--- /dev/null
+++ b/drivers/crypto/ccp/ccp-crypto-aes-xts.c
@@ -0,0 +1,285 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) AES XTS crypto API support
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/scatterwalk.h>
+
+#include "ccp-crypto.h"
+
+
+struct ccp_aes_xts_def {
+	const char *name;
+	const char *drv_name;
+};
+
+static struct ccp_aes_xts_def aes_xts_algs[] = {
+	{
+		.name		= "xts(aes)",
+		.drv_name	= "xts-aes-ccp",
+	},
+};
+
+struct ccp_unit_size_map {
+	unsigned int size;
+	u32 value;
+};
+
+static struct ccp_unit_size_map unit_size_map[] = {
+	{
+		.size	= 4096,
+		.value	= CCP_XTS_AES_UNIT_SIZE_4096,
+	},
+	{
+		.size	= 2048,
+		.value	= CCP_XTS_AES_UNIT_SIZE_2048,
+	},
+	{
+		.size	= 1024,
+		.value	= CCP_XTS_AES_UNIT_SIZE_1024,
+	},
+	{
+		.size	= 512,
+		.value	= CCP_XTS_AES_UNIT_SIZE_512,
+	},
+	{
+		.size	= 256,
+		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
+	},
+	{
+		.size	= 128,
+		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
+	},
+	{
+		.size	= 64,
+		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
+	},
+	{
+		.size	= 32,
+		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
+	},
+	{
+		.size	= 16,
+		.value	= CCP_XTS_AES_UNIT_SIZE_16,
+	},
+	{
+		.size	= 1,
+		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
+	},
+};
+
+static int ccp_aes_xts_complete(struct crypto_async_request *async_req, int ret)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+
+	if (ret)
+		return ret;
+
+	memcpy(req->info, rctx->iv, AES_BLOCK_SIZE);
+
+	return 0;
+}
+
+static int ccp_aes_xts_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+			      unsigned int key_len)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm));
+
+	/* Only support 128-bit AES key with a 128-bit Tweak key,
+	 * otherwise use the fallback
+	 */
+	switch (key_len) {
+	case AES_KEYSIZE_128 * 2:
+		memcpy(ctx->u.aes.key, key, key_len);
+		break;
+	}
+	ctx->u.aes.key_len = key_len / 2;
+	sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
+
+	return crypto_ablkcipher_setkey(ctx->u.aes.tfm_ablkcipher, key,
+					key_len);
+}
+
+static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
+			     unsigned int encrypt)
+{
+	struct crypto_tfm *tfm =
+		crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+	struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+	unsigned int unit;
+	int ret;
+
+	if (!ctx->u.aes.key_len) {
+		pr_err("AES key not set\n");
+		return -EINVAL;
+	}
+
+	if (req->nbytes & (AES_BLOCK_SIZE - 1)) {
+		pr_err("AES request size is not a multiple of the block size\n");
+		return -EINVAL;
+	}
+
+	if (!req->info) {
+		pr_err("AES IV not supplied");
+		return -EINVAL;
+	}
+
+	for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++)
+		if (!(req->nbytes & (unit_size_map[unit].size - 1)))
+			break;
+
+	if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) ||
+	    (ctx->u.aes.key_len != AES_KEYSIZE_128)) {
+		/* Use the fallback to process the request for any
+		 * unsupported unit sizes or key sizes
+		 */
+		ablkcipher_request_set_tfm(req, ctx->u.aes.tfm_ablkcipher);
+		ret = (encrypt) ? crypto_ablkcipher_encrypt(req) :
+				  crypto_ablkcipher_decrypt(req);
+		ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+
+		return ret;
+	}
+
+	memcpy(rctx->iv, req->info, AES_BLOCK_SIZE);
+	sg_init_one(&rctx->iv_sg, rctx->iv, AES_BLOCK_SIZE);
+
+	memset(&rctx->cmd, 0, sizeof(rctx->cmd));
+	INIT_LIST_HEAD(&rctx->cmd.entry);
+	rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
+	rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
+					   : CCP_AES_ACTION_DECRYPT;
+	rctx->cmd.u.xts.unit_size = unit_size_map[unit].value;
+	rctx->cmd.u.xts.key = &ctx->u.aes.key_sg;
+	rctx->cmd.u.xts.key_len = ctx->u.aes.key_len;
+	rctx->cmd.u.xts.iv = &rctx->iv_sg;
+	rctx->cmd.u.xts.iv_len = AES_BLOCK_SIZE;
+	rctx->cmd.u.xts.src = req->src;
+	rctx->cmd.u.xts.src_len = req->nbytes;
+	rctx->cmd.u.xts.dst = req->dst;
+
+	ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
+
+	return ret;
+}
+
+static int ccp_aes_xts_encrypt(struct ablkcipher_request *req)
+{
+	return ccp_aes_xts_crypt(req, 1);
+}
+
+static int ccp_aes_xts_decrypt(struct ablkcipher_request *req)
+{
+	return ccp_aes_xts_crypt(req, 0);
+}
+
+static int ccp_aes_xts_cra_init(struct crypto_tfm *tfm)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_ablkcipher *fallback_tfm;
+
+	ctx->complete = ccp_aes_xts_complete;
+	ctx->u.aes.key_len = 0;
+
+	fallback_tfm = crypto_alloc_ablkcipher(tfm->__crt_alg->cra_name, 0,
+					       CRYPTO_ALG_ASYNC |
+					       CRYPTO_ALG_NEED_FALLBACK);
+	if (IS_ERR(fallback_tfm)) {
+		pr_warn("could not load fallback driver %s\n",
+			tfm->__crt_alg->cra_name);
+		return PTR_ERR(fallback_tfm);
+	}
+	ctx->u.aes.tfm_ablkcipher = fallback_tfm;
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx) +
+				      fallback_tfm->base.crt_ablkcipher.reqsize;
+
+	return 0;
+}
+
+static void ccp_aes_xts_cra_exit(struct crypto_tfm *tfm)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	if (ctx->u.aes.tfm_ablkcipher)
+		crypto_free_ablkcipher(ctx->u.aes.tfm_ablkcipher);
+	ctx->u.aes.tfm_ablkcipher = NULL;
+}
+
+
+static int ccp_register_aes_xts_alg(struct list_head *head,
+				    const struct ccp_aes_xts_def *def)
+{
+	struct ccp_crypto_ablkcipher_alg *ccp_alg;
+	struct crypto_alg *alg;
+	int ret;
+
+	ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
+	if (!ccp_alg)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&ccp_alg->entry);
+
+	alg = &ccp_alg->alg;
+
+	snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+	snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+		 def->drv_name);
+	alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC |
+			 CRYPTO_ALG_KERN_DRIVER_ONLY |
+			 CRYPTO_ALG_NEED_FALLBACK;
+	alg->cra_blocksize = AES_BLOCK_SIZE;
+	alg->cra_ctxsize = sizeof(struct ccp_ctx);
+	alg->cra_priority = CCP_CRA_PRIORITY;
+	alg->cra_type = &crypto_ablkcipher_type;
+	alg->cra_ablkcipher.setkey = ccp_aes_xts_setkey;
+	alg->cra_ablkcipher.encrypt = ccp_aes_xts_encrypt;
+	alg->cra_ablkcipher.decrypt = ccp_aes_xts_decrypt;
+	alg->cra_ablkcipher.min_keysize = AES_MIN_KEY_SIZE * 2;
+	alg->cra_ablkcipher.max_keysize = AES_MAX_KEY_SIZE * 2;
+	alg->cra_ablkcipher.ivsize = AES_BLOCK_SIZE;
+	alg->cra_init = ccp_aes_xts_cra_init;
+	alg->cra_exit = ccp_aes_xts_cra_exit;
+	alg->cra_module = THIS_MODULE;
+
+	ret = crypto_register_alg(alg);
+	if (ret) {
+		pr_err("%s ablkcipher algorithm registration error (%d)\n",
+			alg->cra_name, ret);
+		kfree(ccp_alg);
+		return ret;
+	}
+
+	list_add(&ccp_alg->entry, head);
+
+	return 0;
+}
+
+int ccp_register_aes_xts_algs(struct list_head *head)
+{
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(aes_xts_algs); i++) {
+		ret = ccp_register_aes_xts_alg(head, &aes_xts_algs[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}

^ permalink raw reply related

* [PATCH 09/10] crytpo: CCP device driver build files
From: Tom Lendacky @ 2013-11-12 17:46 UTC (permalink / raw)
  To: davem, linux-crypto, herbert; +Cc: linux-kernel
In-Reply-To: <20131112174558.19746.47262.stgit@tlendack-t1.amdoffice.net>

These files provide the ability to configure and build the
AMD CCP device driver and crypto API support.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 drivers/crypto/Kconfig      |   12 ++++++++++++
 drivers/crypto/Makefile     |    1 +
 drivers/crypto/ccp/Kconfig  |   23 +++++++++++++++++++++++
 drivers/crypto/ccp/Makefile |   10 ++++++++++
 4 files changed, 46 insertions(+)
 create mode 100644 drivers/crypto/ccp/Kconfig
 create mode 100644 drivers/crypto/ccp/Makefile

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index f4fd837..4954d75 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -399,4 +399,16 @@ config CRYPTO_DEV_ATMEL_SHA
 	  To compile this driver as a module, choose M here: the module
 	  will be called atmel-sha.
 
+config CRYPTO_DEV_CCP
+	bool "Support for AMD Cryptographic Coprocessor"
+	depends on X86
+	default n
+	help
+	  The AMD Cryptographic Coprocessor provides hardware support
+	  for encryption, hashing and related operations.
+
+if CRYPTO_DEV_CCP
+	source "drivers/crypto/ccp/Kconfig"
+endif
+
 endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index b4946dd..8a6c86a 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_CRYPTO_DEV_NX) += nx/
 obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o
 obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o
 obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o
+obj-$(CONFIG_CRYPTO_DEV_CCP) += ccp/
diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig
new file mode 100644
index 0000000..335ed5c
--- /dev/null
+++ b/drivers/crypto/ccp/Kconfig
@@ -0,0 +1,23 @@
+config CRYPTO_DEV_CCP_DD
+	tristate "Cryptographic Coprocessor device driver"
+	depends on CRYPTO_DEV_CCP
+	default m
+	help
+	  Provides the interface to use the AMD Cryptographic Coprocessor
+	  which can be used to accelerate or offload encryption operations
+	  such as SHA, AES and more. If you choose 'M' here, this module
+	  will be called ccp.
+
+config CRYPTO_DEV_CCP_CRYPTO
+	tristate "Encryption and hashing acceleration support"
+	depends on CRYPTO_DEV_CCP_DD
+	default m
+	select CRYPTO_ALGAPI
+	select CRYPTO_HASH
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_AUTHENC
+	help
+	  Support for using the cryptographic API with the AMD Cryptographic
+	  Coprocessor. This module supports acceleration and offload of SHA
+	  and AES algorithms.  If you choose 'M' here, this module will be
+	  called ccp_crypto.
diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
new file mode 100644
index 0000000..d3505a0
--- /dev/null
+++ b/drivers/crypto/ccp/Makefile
@@ -0,0 +1,10 @@
+obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
+ccp-objs := ccp-dev.o ccp-ops.o
+ccp-objs += ccp-pci.o
+
+obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
+ccp-crypto-objs := ccp-crypto-main.o \
+		   ccp-crypto-aes.o \
+		   ccp-crypto-aes-cmac.o \
+		   ccp-crypto-aes-xts.o \
+		   ccp-crypto-sha.o

^ permalink raw reply related

* [PATCH 08/10] crypto: CCP SHA crypto API support
From: Tom Lendacky @ 2013-11-12 17:46 UTC (permalink / raw)
  To: davem, linux-crypto, herbert; +Cc: linux-kernel
In-Reply-To: <20131112174558.19746.47262.stgit@tlendack-t1.amdoffice.net>

These routines provide crypto API support for SHA1, SHA224 and SHA256
on the AMD CCP.  HMAC support for these SHA modes is also provided.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 drivers/crypto/ccp/ccp-crypto-sha.c |  497 +++++++++++++++++++++++++++++++++++
 1 file changed, 497 insertions(+)
 create mode 100644 drivers/crypto/ccp/ccp-crypto-sha.c

diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c
new file mode 100644
index 0000000..44ff00a
--- /dev/null
+++ b/drivers/crypto/ccp/ccp-crypto-sha.c
@@ -0,0 +1,497 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) SHA crypto API support
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/hash.h>
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+#include <crypto/scatterwalk.h>
+
+#include "ccp-crypto.h"
+
+
+struct ccp_sha_result {
+	struct completion completion;
+	int err;
+};
+
+static void ccp_sync_hash_complete(struct crypto_async_request *req, int err)
+{
+	struct ccp_sha_result *result = req->data;
+
+	if (err == -EINPROGRESS)
+		return;
+
+	result->err = err;
+	complete(&result->completion);
+}
+
+static int ccp_sync_hash(struct crypto_ahash *tfm, u8 *buf,
+			 struct scatterlist *sg, unsigned int len)
+{
+	struct ccp_sha_result result;
+	struct ahash_request *req;
+	int ret;
+
+	init_completion(&result.completion);
+
+	req = ahash_request_alloc(tfm, GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+				   ccp_sync_hash_complete, &result);
+	ahash_request_set_crypt(req, sg, buf, len);
+
+	ret = crypto_ahash_digest(req);
+	if ((ret == -EINPROGRESS) || (ret == -EBUSY)) {
+		ret = wait_for_completion_interruptible(&result.completion);
+		if (!ret)
+			ret = result.err;
+	}
+
+	ahash_request_free(req);
+
+	return ret;
+}
+
+static int ccp_sha_finish_hmac(struct crypto_async_request *async_req)
+{
+	struct ahash_request *req = ahash_request_cast(async_req);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
+	struct scatterlist sg[2];
+	unsigned int block_size =
+		crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+	unsigned int digest_size = crypto_ahash_digestsize(tfm);
+
+	sg_init_table(sg, ARRAY_SIZE(sg));
+	sg_set_buf(&sg[0], ctx->u.sha.opad, block_size);
+	sg_set_buf(&sg[1], req->result, digest_size);
+
+	return ccp_sync_hash(ctx->u.sha.hmac_tfm, req->result, sg,
+			     block_size + digest_size);
+}
+
+static int ccp_sha_complete(struct crypto_async_request *async_req, int ret)
+{
+	struct ahash_request *req = ahash_request_cast(async_req);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
+	struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
+	unsigned int digest_size = crypto_ahash_digestsize(tfm);
+
+	if (ret)
+		goto e_free;
+
+	if (rctx->hash_rem) {
+		/* Save remaining data to buffer */
+		scatterwalk_map_and_copy(rctx->buf, rctx->cmd.u.sha.src,
+					 rctx->hash_cnt, rctx->hash_rem, 0);
+		rctx->buf_count = rctx->hash_rem;
+	} else
+		rctx->buf_count = 0;
+
+	memcpy(req->result, rctx->ctx, digest_size);
+
+	/* If we're doing an HMAC, we need to perform that on the final op */
+	if (rctx->final && ctx->u.sha.key_len)
+		ret = ccp_sha_finish_hmac(async_req);
+
+e_free:
+	sg_free_table(&rctx->data_sg);
+
+	return ret;
+}
+
+static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes,
+			     unsigned int final)
+{
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
+	struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
+	struct scatterlist *sg;
+	unsigned int block_size =
+		crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+	unsigned int len, sg_count;
+	int ret;
+
+	if (!final && ((nbytes + rctx->buf_count) <= block_size)) {
+		scatterwalk_map_and_copy(rctx->buf + rctx->buf_count, req->src,
+					 0, nbytes, 0);
+		rctx->buf_count += nbytes;
+
+		return 0;
+	}
+
+	len = rctx->buf_count + nbytes;
+
+	rctx->final = final;
+	rctx->hash_cnt = final ? len : len & ~(block_size - 1);
+	rctx->hash_rem = final ?   0 : len &  (block_size - 1);
+	if (!final && (rctx->hash_cnt == len)) {
+		/* CCP can't do zero length final, so keep some data around */
+		rctx->hash_cnt -= block_size;
+		rctx->hash_rem = block_size;
+	}
+
+	/* Initialize the context scatterlist */
+	sg_init_one(&rctx->ctx_sg, rctx->ctx, sizeof(rctx->ctx));
+
+	/* Build the data scatterlist table - allocate enough entries for all
+	 * possible data pieces (hmac ipad, buffer, input data)
+	 */
+	sg_count = (nbytes) ? sg_nents(req->src) + 2 : 2;
+	ret = sg_alloc_table(&rctx->data_sg, sg_count, GFP_KERNEL);
+	if (ret)
+		return ret;
+
+	sg = NULL;
+	if (rctx->first && ctx->u.sha.key_len) {
+		rctx->hash_cnt += block_size;
+
+		sg_init_one(&rctx->pad_sg, ctx->u.sha.ipad, block_size);
+		sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->pad_sg);
+	}
+
+	if (rctx->buf_count) {
+		sg_init_one(&rctx->buf_sg, rctx->buf, rctx->buf_count);
+		sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->buf_sg);
+	}
+
+	if (nbytes)
+		sg = ccp_crypto_sg_table_add(&rctx->data_sg, req->src);
+
+	if (sg)
+		sg_mark_end(sg);
+
+	rctx->msg_bits += (rctx->hash_cnt << 3);	/* Total in bits */
+
+	memset(&rctx->cmd, 0, sizeof(rctx->cmd));
+	INIT_LIST_HEAD(&rctx->cmd.entry);
+	rctx->cmd.engine = CCP_ENGINE_SHA;
+	rctx->cmd.u.sha.type = rctx->type;
+	rctx->cmd.u.sha.ctx = &rctx->ctx_sg;
+	rctx->cmd.u.sha.ctx_len = sizeof(rctx->ctx);
+	rctx->cmd.u.sha.src = (sg) ? rctx->data_sg.sgl : NULL;
+	rctx->cmd.u.sha.src_len = rctx->hash_cnt;
+	rctx->cmd.u.sha.final = rctx->final;
+	rctx->cmd.u.sha.msg_bits = rctx->msg_bits;
+
+	rctx->first = 0;
+
+	ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
+
+	return ret;
+}
+
+static int ccp_sha_init(struct ahash_request *req)
+{
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
+	struct ccp_crypto_ahash_alg *alg =
+		ccp_crypto_ahash_alg(crypto_ahash_tfm(tfm));
+
+	memset(rctx, 0, sizeof(*rctx));
+
+	memcpy(rctx->ctx, alg->init, sizeof(rctx->ctx));
+	rctx->type = alg->type;
+	rctx->first = 1;
+
+	return 0;
+}
+
+static int ccp_sha_update(struct ahash_request *req)
+{
+	return ccp_do_sha_update(req, req->nbytes, 0);
+}
+
+static int ccp_sha_final(struct ahash_request *req)
+{
+	return ccp_do_sha_update(req, 0, 1);
+}
+
+static int ccp_sha_finup(struct ahash_request *req)
+{
+	return ccp_do_sha_update(req, req->nbytes, 1);
+}
+
+static int ccp_sha_digest(struct ahash_request *req)
+{
+	ccp_sha_init(req);
+
+	return ccp_do_sha_update(req, req->nbytes, 1);
+}
+
+static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key,
+			  unsigned int key_len)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
+	struct scatterlist sg;
+	unsigned int block_size =
+		crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+	unsigned int digest_size = crypto_ahash_digestsize(tfm);
+	int i, ret;
+
+	/* Set to zero until complete */
+	ctx->u.sha.key_len = 0;
+
+	/* Clear key area to provide zero padding for keys smaller
+	 * than the block size
+	 */
+	memset(ctx->u.sha.key, 0, sizeof(ctx->u.sha.key));
+
+	if (key_len > block_size) {
+		/* Must hash the input key */
+		sg_init_one(&sg, key, key_len);
+		ret = ccp_sync_hash(tfm, ctx->u.sha.key, &sg, key_len);
+		if (ret) {
+			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+			return -EINVAL;
+		}
+
+		key_len = digest_size;
+	} else
+		memcpy(ctx->u.sha.key, key, key_len);
+
+	for (i = 0; i < block_size; i++) {
+		ctx->u.sha.ipad[i] = ctx->u.sha.key[i] ^ 0x36;
+		ctx->u.sha.opad[i] = ctx->u.sha.key[i] ^ 0x5c;
+	}
+
+	ctx->u.sha.key_len = key_len;
+
+	return 0;
+}
+
+static int ccp_sha_cra_init(struct crypto_tfm *tfm)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
+
+	ctx->complete = ccp_sha_complete;
+	ctx->u.sha.key_len = 0;
+
+	crypto_ahash_set_reqsize(ahash, sizeof(struct ccp_sha_req_ctx));
+
+	return 0;
+}
+
+static void ccp_sha_cra_exit(struct crypto_tfm *tfm)
+{
+}
+
+static int ccp_hmac_sha_cra_init(struct crypto_tfm *tfm)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct ccp_crypto_ahash_alg *alg = ccp_crypto_ahash_alg(tfm);
+	struct crypto_ahash *hmac_tfm;
+
+	hmac_tfm = crypto_alloc_ahash(alg->child_alg,
+				      CRYPTO_ALG_TYPE_AHASH, 0);
+	if (IS_ERR(hmac_tfm)) {
+		pr_warn("could not load driver %s need for HMAC support\n",
+			alg->child_alg);
+		return PTR_ERR(hmac_tfm);
+	}
+
+	ctx->u.sha.hmac_tfm = hmac_tfm;
+
+	return ccp_sha_cra_init(tfm);
+}
+
+static void ccp_hmac_sha_cra_exit(struct crypto_tfm *tfm)
+{
+	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	if (ctx->u.sha.hmac_tfm)
+		crypto_free_ahash(ctx->u.sha.hmac_tfm);
+
+	ccp_sha_cra_exit(tfm);
+}
+
+static const u32 sha1_init[CCP_SHA_CTXSIZE / sizeof(u32)] = {
+	cpu_to_be32(SHA1_H0), cpu_to_be32(SHA1_H1),
+	cpu_to_be32(SHA1_H2), cpu_to_be32(SHA1_H3),
+	cpu_to_be32(SHA1_H4), 0, 0, 0,
+};
+
+static const u32 sha224_init[CCP_SHA_CTXSIZE / sizeof(u32)] = {
+	cpu_to_be32(SHA224_H0), cpu_to_be32(SHA224_H1),
+	cpu_to_be32(SHA224_H2), cpu_to_be32(SHA224_H3),
+	cpu_to_be32(SHA224_H4), cpu_to_be32(SHA224_H5),
+	cpu_to_be32(SHA224_H6), cpu_to_be32(SHA224_H7),
+};
+
+static const u32 sha256_init[CCP_SHA_CTXSIZE / sizeof(u32)] = {
+	cpu_to_be32(SHA256_H0), cpu_to_be32(SHA256_H1),
+	cpu_to_be32(SHA256_H2), cpu_to_be32(SHA256_H3),
+	cpu_to_be32(SHA256_H4), cpu_to_be32(SHA256_H5),
+	cpu_to_be32(SHA256_H6), cpu_to_be32(SHA256_H7),
+};
+
+struct ccp_sha_def {
+	const char *name;
+	const char *drv_name;
+	const u32 *init;
+	enum ccp_sha_type type;
+	u32 digest_size;
+	u32 block_size;
+};
+
+static struct ccp_sha_def sha_algs[] = {
+	{
+		.name		= "sha1",
+		.drv_name	= "sha1-ccp",
+		.init		= sha1_init,
+		.type		= CCP_SHA_TYPE_1,
+		.digest_size	= SHA1_DIGEST_SIZE,
+		.block_size	= SHA1_BLOCK_SIZE,
+	},
+	{
+		.name		= "sha224",
+		.drv_name	= "sha224-ccp",
+		.init		= sha224_init,
+		.type		= CCP_SHA_TYPE_224,
+		.digest_size	= SHA224_DIGEST_SIZE,
+		.block_size	= SHA224_BLOCK_SIZE,
+	},
+	{
+		.name		= "sha256",
+		.drv_name	= "sha256-ccp",
+		.init		= sha256_init,
+		.type		= CCP_SHA_TYPE_256,
+		.digest_size	= SHA256_DIGEST_SIZE,
+		.block_size	= SHA256_BLOCK_SIZE,
+	},
+};
+
+static int ccp_register_hmac_alg(struct list_head *head,
+				 const struct ccp_sha_def *def,
+				 const struct ccp_crypto_ahash_alg *base_alg)
+{
+	struct ccp_crypto_ahash_alg *ccp_alg;
+	struct ahash_alg *alg;
+	struct hash_alg_common *halg;
+	struct crypto_alg *base;
+	int ret;
+
+	ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
+	if (!ccp_alg)
+		return -ENOMEM;
+
+	/* Copy the base algorithm and only change what's necessary */
+	memcpy(ccp_alg, base_alg, sizeof(*ccp_alg));
+	INIT_LIST_HEAD(&ccp_alg->entry);
+
+	strncpy(ccp_alg->child_alg, def->name, CRYPTO_MAX_ALG_NAME);
+
+	alg = &ccp_alg->alg;
+	alg->setkey = ccp_sha_setkey;
+
+	halg = &alg->halg;
+
+	base = &halg->base;
+	snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", def->name);
+	snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "hmac-%s",
+		 def->drv_name);
+	base->cra_init = ccp_hmac_sha_cra_init;
+	base->cra_exit = ccp_hmac_sha_cra_exit;
+
+	ret = crypto_register_ahash(alg);
+	if (ret) {
+		pr_err("%s ahash algorithm registration error (%d)\n",
+			base->cra_name, ret);
+		kfree(ccp_alg);
+		return ret;
+	}
+
+	list_add(&ccp_alg->entry, head);
+
+	return ret;
+}
+
+static int ccp_register_sha_alg(struct list_head *head,
+				const struct ccp_sha_def *def)
+{
+	struct ccp_crypto_ahash_alg *ccp_alg;
+	struct ahash_alg *alg;
+	struct hash_alg_common *halg;
+	struct crypto_alg *base;
+	int ret;
+
+	ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
+	if (!ccp_alg)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&ccp_alg->entry);
+
+	ccp_alg->init = def->init;
+	ccp_alg->type = def->type;
+
+	alg = &ccp_alg->alg;
+	alg->init = ccp_sha_init;
+	alg->update = ccp_sha_update;
+	alg->final = ccp_sha_final;
+	alg->finup = ccp_sha_finup;
+	alg->digest = ccp_sha_digest;
+
+	halg = &alg->halg;
+	halg->digestsize = def->digest_size;
+
+	base = &halg->base;
+	snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+	snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+		 def->drv_name);
+	base->cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC |
+			  CRYPTO_ALG_KERN_DRIVER_ONLY |
+			  CRYPTO_ALG_NEED_FALLBACK;
+	base->cra_blocksize = def->block_size;
+	base->cra_ctxsize = sizeof(struct ccp_ctx);
+	base->cra_priority = CCP_CRA_PRIORITY;
+	base->cra_type = &crypto_ahash_type;
+	base->cra_init = ccp_sha_cra_init;
+	base->cra_exit = ccp_sha_cra_exit;
+	base->cra_module = THIS_MODULE;
+
+	ret = crypto_register_ahash(alg);
+	if (ret) {
+		pr_err("%s ahash algorithm registration error (%d)\n",
+			base->cra_name, ret);
+		kfree(ccp_alg);
+		return ret;
+	}
+
+	list_add(&ccp_alg->entry, head);
+
+	ret = ccp_register_hmac_alg(head, def, ccp_alg);
+
+	return ret;
+}
+
+int ccp_register_sha_algs(struct list_head *head)
+{
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(sha_algs); i++) {
+		ret = ccp_register_sha_alg(head, &sha_algs[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}

^ permalink raw reply related

* [PATCH 10/10] crypto: CCP maintainer information
From: Tom Lendacky @ 2013-11-12 17:46 UTC (permalink / raw)
  To: davem, linux-crypto, herbert; +Cc: linux-kernel
In-Reply-To: <20131112174558.19746.47262.stgit@tlendack-t1.amdoffice.net>

Update the MAINTAINERS file for the AMD CCP device driver.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 MAINTAINERS |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 051e4dc..de22604 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -525,6 +525,13 @@ F:	drivers/tty/serial/altera_jtaguart.c
 F:	include/linux/altera_uart.h
 F:	include/linux/altera_jtaguart.h
 
+AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER
+M:	Tom Lendacky <thomas.lendacky@amd.com>
+L:	linux-crypto@vger.kernel.org
+S:	Supported
+F:	drivers/crypto/ccp/
+F:	include/linux/ccp.h
+
 AMD FAM15H PROCESSOR POWER MONITORING DRIVER
 M:	Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:	lm-sensors@lm-sensors.org

^ permalink raw reply related

* Re: Crypto Update for 3.13
From: Herbert Xu @ 2013-11-12 18:27 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Linus Torvalds, David S. Miller, Linux Kernel Mailing List,
	Linux Crypto Mailing List, James Morris
In-Reply-To: <20131112165934.GA13441@pd.tnic>

On Tue, Nov 12, 2013 at 05:59:34PM +0100, Borislav Petkov wrote:
> On Wed, Nov 13, 2013 at 12:41:52AM +0800, Herbert Xu wrote:
> > Hi Linus:
> > 
> > Here is the crypto update for 3.13:
> > 
> > * Made x86 ablk_helper generic for ARM.
> > * Phase out chainiv in favour of eseqiv (affects IPsec).
> > * Fixed aes-cbc IV corruption on s390.
> > * Added constant-time crypto_memneq which replaces memcmp.
> > 
> > * Fixed aes-ctr in omap-aes.
> > * Added OMAP3 ROM RNG support.
> > * Add PRNG support for MSM SoC's
> > * Add and use Job Ring API in caam.
> > 
> > * Misc fixes.
> 
> Maybe add this one to that:
> 
> http://marc.info/?l=linux-kernel&m=138078878205385&w=2
> 
> ?

I think this should probably go through James Morris's tree.

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

^ permalink raw reply

* [PATCH] crypto: omap-sham - Only release DMA channel if successfully requested
From: Mark A. Greer @ 2013-11-12 20:12 UTC (permalink / raw)
  To: linux-crypto
  Cc: Herbert Xu, Joel Fernandes, Mark A. Greer, linux-arm-kernel,
	linux-omap, David S. Miller, Dan Carpenter

In omap_sham_probe() and omap_sham_remove(), 'dd->dma_lch'
is released without checking to see if it was successfully
requested or not.  This is a bug and was identified and
reported by Dan Carpenter here:

	http://www.spinics.net/lists/devicetree/msg11023.html

Add code to only release 'dd->dma_lch' when its not NULL
(that is, when it was successfully requested).

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
CC: Joel Fernandes <joelf@ti.com>
Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
---
 drivers/crypto/omap-sham.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index e28104b..c6ad7d6 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -1970,7 +1970,8 @@ err_algs:
 			crypto_unregister_ahash(
 					&dd->pdata->algs_info[i].algs_list[j]);
 	pm_runtime_disable(dev);
-	dma_release_channel(dd->dma_lch);
+	if (dd->dma_lch)
+		dma_release_channel(dd->dma_lch);
 data_err:
 	dev_err(dev, "initialization failed.\n");
 
@@ -1994,7 +1995,9 @@ static int omap_sham_remove(struct platform_device *pdev)
 					&dd->pdata->algs_info[i].algs_list[j]);
 	tasklet_kill(&dd->done_task);
 	pm_runtime_disable(&pdev->dev);
-	dma_release_channel(dd->dma_lch);
+
+	if (dd->dma_lch)
+		dma_release_channel(dd->dma_lch);
 
 	return 0;
 }
-- 
1.8.3.4

^ permalink raw reply related

* Re: [PATCH 2/2] crypto: testmgr - make test_aead also test 'dst != src' code paths
From: Jussi Kivilinna @ 2013-11-12 21:54 UTC (permalink / raw)
  To: Horia Geantă, Jussi Kivilinna, linux-crypto
  Cc: Herbert Xu, David S. Miller
In-Reply-To: <52820CF9.3070406@freescale.com>

On 12.11.2013 13:11, Horia Geantă wrote:
> On 9/21/2012 10:26 AM, Jussi Kivilinna wrote:
>> Currrently test_aead uses same buffer for destination and source. However
>> in any places, 'dst != src' take different path than 'dst == src' case.
>>
>> Therefore make test_aead also run tests with destination buffer being
>> different than source buffer.
>>
>> Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
>> ---
>>   crypto/testmgr.c |  153 +++++++++++++++++++++++++++++++++++++-----------------
>>   1 file changed, 105 insertions(+), 48 deletions(-)
>>
>> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
>> index 00f54d5..941d75c 100644
>> --- a/crypto/testmgr.c
>> +++ b/crypto/testmgr.c
> 
>> @@ -442,18 +460,26 @@ static int test_aead(struct crypto_aead *tfm, int enc,
>>               authsize = abs(template[i].rlen - template[i].ilen);
>>               ret = crypto_aead_setauthsize(tfm, authsize);
>>               if (ret) {
>> -                printk(KERN_ERR "alg: aead: Failed to set "
>> -                       "authsize to %u on test %d for %s\n",
>> -                       authsize, j, algo);
>> +                pr_err("alg: aead%s: Failed to set authsize to %u on test %d for %s\n",
>> +                       d, authsize, j, algo);
>>                   goto out;
>>               }
>>                 sg_init_one(&sg[0], input,
>>                       template[i].ilen + (enc ? authsize : 0));
>>   +            if (diff_dst) {
>> +                output = xoutbuf[0];
>> +                sg_init_one(&sgout[0], output,
>> +                        template[i].ilen +
>> +                        (enc ? authsize : 0));
>> +            } else {
>> +                output = input;
>> +            }
> 
> In case of diff_dst (src != dst), is there any assumption / convention regarding allocation length of req->src and req->dst - are they supposed be equal, even if it's not needed?
> For example, in case of diff_dst && encryption, currently both req->src and req->dst have then length = template[i].ilen + authsize. Shouldn't length of req->src be template[i].ilen, i.e. no space allocated for ICV?

You're right, in diff_dst case, sg and sgout could be different size. That's what I thought at first, and so I changed the above part to:

			if (diff_dst) {
				output = xoutbuf[0];
				output += align_offset;
				sg_init_one(&sg[0], input, template[i].ilen);
				sg_init_one(&sgout[0], output,
					    template[i].rlen);
			} else {
				sg_init_one(&sg[0], input,
					    template[i].ilen +
						(enc ? authsize : 0));
				output = input;
			}

But this causes scatterwalk.c to throw BUG:

[   62.213960] ------------[ cut here ]------------
[   62.214031] kernel BUG at crypto/scatterwalk.c:37!
[   62.214065] invalid opcode: 0000 [#1] PREEMPT SMP 
[   62.214101] Modules linked in: zlib seed rmd320 rmd256 rmd128 cts ccm ghash_generic gcm salsa20_generic salsa20_x86_64 fcrypt pcbc tgr192 anubis wp512 khazad tea michael_mic arc4 cast6_generic seqiv md4 ecb tcrypt(+) deflate ctr twofish_generic twofish_x86_64_3way twofish_x86_64 twofish_common camellia_generic camellia_x86_64 serpent_sse2_x86_64 glue_helper lrw serpent_generic xts gf128mul blowfish_generic blowfish_x86_64 blowfish_common ablk_helper cryptd cast5_generic cast_common des_generic cbc cmac xcbc rmd160 sha512_ssse3 sha512_generic sha256_ssse3 sha256_generic sha1_ssse3 sha1_generic md5 hmac crypto_null af_key xfrm_algo dm_crypt dm_mod ppdev parport_pc ac ohci_pci ohci_hcd i2c_piix4 lp parport nfsd nfs_acl rpcsec_gss_krb5 auth_rpcgss oid_registry nfsv4 nfs lockd sunrpc btrfs raid6_pq xor libcrc32c floppy intel_agp intel_gtt agpgart button ata_piix e1000
[   62.214603] CPU: 1 PID: 2131 Comm: cryptomgr_test Not tainted 3.11.0-cryptotest-jk1+ #59
[   62.214661] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[   62.214720] task: ffff880037559c80 ti: ffff88003cb0c000 task.ti: ffff88003cb0c000
[   62.214776] RIP: 0010:[<ffffffff8122c730>]  [<ffffffff8122c730>] scatterwalk_bytes_sglen+0x70/0x70
[   62.214847] RSP: 0018:ffff88003cb0dae0  EFLAGS: 00010246
[   62.214880] RAX: 00000000000000f2 RBX: ffff8800376964b0 RCX: 0000000000000000
[   62.214916] RDX: ffff880037694800 RSI: ffff880037694800 RDI: ffff88003cb0db18
[   62.214952] RBP: ffff880037696c00 R08: 00000000d0597ff0 R09: 0000000000000000
[   62.214989] R10: 000000006b5d5311 R11: 00000000d1bd7079 R12: ffff880037696c00
[   62.215389] R13: 0000000000000000 R14: 0000000000002000 R15: 0000000000000000
[   62.215730] FS:  0000000000000000(0000) GS:ffff88003fd00000(0000) knlGS:0000000000000000
[   62.216411] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[   62.216659] CR2: 00007f8d50b79420 CR3: 000000003c8b2000 CR4: 00000000000006e0
[   62.217019] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   62.217247] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   62.217247] Stack:
[   62.217247]  ffffffff8122c758 ffffffffa0490418 ffff88003ca2a01e 000000003db65000
[   62.217247]  ffff88003cb0dfd8 ffff88003cb0dfd8 ffff8800376964c0 ffff880037694800
[   62.217247]  000000d000000020 ffff8800376964b0 ffff880037696458 ffff880037696c00
[   62.217247] Call Trace:
[   62.217247]  [<ffffffff8122c758>] ? scatterwalk_start+0x18/0x20
[   62.217247]  [<ffffffffa0490418>] ? get_data_to_compute+0x28/0x2b0 [ccm]
[   62.217247]  [<ffffffffa04907c7>] ? crypto_ccm_auth+0x127/0x190 [ccm]
[   62.217247]  [<ffffffffa049119a>] ? crypto_ccm_encrypt+0x6a/0x275 [ccm]
[   62.217247]  [<ffffffff8126c3b4>] ? sg_init_table+0x14/0x30
[   62.217247]  [<ffffffff81233f46>] ? __test_aead+0x3f6/0xf60
[   62.217247]  [<ffffffff8122c4c8>] ? crypto_spawn_tfm+0x38/0x70
[   62.217247]  [<ffffffff81131717>] ? __kmalloc+0x1d7/0x200
[   62.217247]  [<ffffffff8122a5c9>] ? __crypto_alloc_tfm+0xe9/0x160
[   62.217247]  [<ffffffff81234af9>] ? test_aead+0x49/0xa0
[   62.217247]  [<ffffffff81234b8a>] ? alg_test_aead+0x3a/0x90
[   62.217247]  [<ffffffff81232e03>] ? alg_test+0xc3/0x290
[   62.217247]  [<ffffffff8106f130>] ? finish_task_switch+0x40/0xc0
[   62.217247]  [<ffffffff81536947>] ? __schedule+0x287/0x760
[   62.217247]  [<ffffffff81231b30>] ? crypto_unregister_pcomp+0x10/0x10
[   62.217247]  [<ffffffff81231b68>] ? cryptomgr_test+0x38/0x40
[   62.217247]  [<ffffffff8106590f>] ? kthread+0xaf/0xc0
[   62.217247]  [<ffffffff81065860>] ? kthread_create_on_node+0x120/0x120
[   62.217247]  [<ffffffff8153902c>] ? ret_from_fork+0x7c/0xb0
[   62.217247]  [<ffffffff81065860>] ? kthread_create_on_node+0x120/0x120
[   62.217247] Code: ff ff ff ff 0f 1f 80 00 00 00 00 f3 c3 66 0f 1f 44 00 00 48 8b 7f 20 48 83 e7 fc 41 0f 94 c0 eb bb 66 2e 0f 1f 84 00 00 00 00 00 <0f> 0b 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 48 89 37 44 8b 
[   62.217247] RIP  [<ffffffff8122c730>] scatterwalk_bytes_sglen+0x70/0x70
[   62.217247]  RSP <ffff88003cb0dae0>
[   62.227458] ---[ end trace 338f2122cbee98de ]---
[   63.411157] ------------[ cut here ]------------


This should probably be fixed, right?

-Jussi

> 
> Thanks,
> Horia
> 
> 
> 
> 

^ permalink raw reply

* Error inserting sha256_ssse3: No such device
From: Turbo Fredriksson @ 2013-11-13  3:08 UTC (permalink / raw)
  To: linux-crypto

I've just upgraded from 3.9.0-rc6 because I needed new versions
of ZFS On Linux (because of a unknown problem with the previous
version which lead to it refusing to load).

I also have zfs-crypto by zfsrogue and when trying to mount a
crypted filesystem, I get:

	filesystem 'share/home/turbo/Crypted' can not be mounted due to error 52
	cannot mount 'share/home/turbo/Crypted': Invalid argument

This leads to the following in the logs:

	Nov 13 03:24:53 Celia modprobe: WARNING: Error inserting ghash_clmulni_intel (/lib/modules/3.12.0+scst+tf.1/kernel/arch/x86/crypto/ghash-clmulni-intel.ko): No such device
	Nov 13 03:24:54 Celia kernel: [ 2053.440315] spl-crypto: Cipher test 'CKM_AES_GCM' -> 'sun-gcm(aes)' successful.
	Nov 13 03:25:01 Celia kernel: [ 2061.223198] sha256_ssse3: Neither AVX nor SSSE3 is available/usable.
	Nov 13 03:25:01 Celia modprobe: WARNING: Error inserting sha256_ssse3 (/lib/modules/3.12.0+scst+tf.1/kernel/arch/x86/crypto/sha256-ssse3.ko): No such device
	Nov 13 03:25:01 Celia modprobe: FATAL: Error inserting padlock_sha (/lib/modules/3.12.0+scst+tf.1/kernel/drivers/crypto/padlock-sha.ko): No such device

Trying to load the module sha256_ssse3 manually, I get:

	celia:/lib/modules/3.12.0+scst+tf.1/kernel# modprobe sha256_ssse3
	FATAL: Error inserting sha256_ssse3 (/lib/modules/3.12.0+scst+tf.1/kernel/arch/x86/crypto/sha256-ssse3.ko): No such device

with the following in the logs:

	Nov 13 03:30:15 Celia kernel: [ 2375.004027] sha256_ssse3: Neither AVX nor SSSE3 is available/usable.


First time (in early spring) I tested this, when loading the sun-gcm module, I
got all kinds of problems (https://github.com/zfsrogue/zfs-crypto/issues/28).
Turned out I needed to load the gf128mul and ghash-generic kernel modules.

So I'm assuming it's the same thing again, a module doesn't get autoloader
by mod probe...


Any ideas?
--
Imagine you're an idiot and then imagine you're in
the government. Oh, sorry. Now I'm repeating myself
- Mark Twain

^ permalink raw reply

* Re: [PATCH] CPU Jitter RNG: inclusion into kernel crypto API and /dev/random
From: Stephan Mueller @ 2013-11-13  3:12 UTC (permalink / raw)
  To: Clemens Ladisch
  Cc: Theodore Ts'o, Pavel Machek, sandy harris, linux-kernel,
	linux-crypto, Nicholas Mc Guire
In-Reply-To: <527FEC56.5070306@ladisch.de>

Am Sonntag, 10. November 2013, 21:28:06 schrieb Clemens Ladisch:

Hi Clemens,

> Stephan Mueller wrote:
> > Am Sonntag, 10. November 2013, 17:31:07 schrieb Clemens Ladisch:
> >> In the case of CPUs, the jitter you observe in delta
> >> times results in part from the complexities of the inner state, and in
> >> part from real random noise.  The first part is deterministic and might
> >> be predicted by anyone who has enough knowledge about the CPU's
> >> internals.
> > 
> > Right, and that is why I tried to eliminate the CPU mechanisms that may be
> > having a deterministic impact. If I miss a mechanism or your have other
> > suggestions, please help me.
> 
> Many CPUs allow to disable branch prediction, but this is very vendor
> specific (try to find MSR documentation).  The biggest offender probably
> is the out-of-order execution engine, which cannot be disabled.

I was also digging around in this area. My research showed so far that only on 
ARM one can disable the branch prediction unit. Unfortunately, I do not have 
an ARM available where I can do that. I have my Samsung phone, but that runs 
Android and I am not sure how to generate a kernel module here.

For x86, I have not found a way to disable the unit. Nonetheless, I tried to 
bring down the effect by "warming" the caches and the branch prediction up 
(see section 6.1.1 of the new version of the documentation). There I execute 
the testing 1000 times and use only the last result for further analysis.
> 
> >>> When you ask for testing of stuck values, what shall I really test for?
> >>> Shall I test adjacent measurements for the same or alternating values?
> >> 
> >> Same or alternating delta time values happen even on random CPUs.  You
> >> need a theory of how random and non-random CPUs work, and how this
> >> difference affects the delta times, before you can test for that.
> > 
> > Are you telling me that I should invent a formula and apply it?
> 
> I was not implying that the theory has nothing to do with the physical
> device.  It must correctly _describe_ the relevant physical processes.

Right, but currently I am not sure how I can find such description. In 
particular, I created a new round of testing which is even more interesting as 
the results do not allow to pinpoint the exact root cause. More to that in a 
separate email.

Do you have an idea?
> 
> >>> The test for the same values is caught with the Von-Neumann unbiaser.
> >> 
> >> No, the von Neumann unbiaser is run on the whitened bitstream, i.e.,
> >> _after_ the folding operation.
> > 
> > The folding is whitened? How do you reach that conclusion? Yes, the
> > folding is my (very simple) post-processing. But I am not calling it
> > whitened as all statistical problems the underlying variations have
> > *will* be still visible in the folded value.
> 
> If you don't want to call it "whitening", call it "randomness extraction"
> instead.  But its input is a series of delta times like this:
>   00000000000000000000000001010011
>   00000000000000000000000010011010
>   00000000000000000000000001011011
>   00000000000000000000000001100100
>   00000000000000000000000010111000
> and the purpose of the folding is to remove these zero patterns.

Not quite. Let me explain the motive behind the folding loop. To maintain 
entropy mathematically, there are only a few operations allowed. One of them 
is a bijective operation which implies that two strings combined with a 
bijective operation will form a new string which contains the maximum entropy 
of the initial strings. XOR is a bijective operation.

Hence, if you have a string with 10 bits that holds 5 bits of entropy and XOR 
it with a 20 bit string that holds 2 bits of entropy, you receive a string 
that is 20 bits in length and holds 5 bits of entropy.

In any case, with the bijective operation, it is not possible to loose entropy 
even when you use the bijective operation to add fully deterministic values to 
a bit stream that is believed to have entropy.

That said, the folding loop uses that line of thought. The loop XORs each bit 
with every other bit to receive one bit at the end. The idea is to collapse 
the initial bit stream by still retaining the entropy present in each 
individual bit. The goal is now that the resulting bit will hold one bit of 
entropy by "collecting" the combined entropy found in the individual bits.

That folding operation will loose entropy, if the overall entropy in the 
folded bit stream is more than one bit. But that point is our advantage, 
because it provides a safety margin, if the value to be folded really holds 
more than one bit of entropy. All my measurements in section 5.1 and appendix 
F just try to show that on every CPU there is always more than one bit of 
entropy.

There is a catch, however: what happens if each individual bit of the bit 
stream holds less than one bit? I.e. the entire bit stream may hold more than 
one bit, but when chopping the bit stream, the none of the individual bits may 
have one bit of entropy. As XOR only retains entropy but never enlarges 
entropy (like a concatenation would do), this would be a problem for the RNG. 
However, measurements and analyses given in section 5.2.1 come to the rescue: 
The measurements show that the folded value behaves like having one bit of 
entropy.

To support that conclusion, the folding loop is sometimes executed in 
multiples of 64. This looks strange at first look, but these multiples ensure 
that the distribution of the folding loop bits discussed in section 5.2.1 
stabilizes quickly. And with these multiple execution of the folding loop, the 
upper boundary of the entropy is defined.

Now coming back to your concern: It is surely possible to put the Von-Neumann 
unbiaser before the folding loop. But considering the argument above, no 
information is lost apart from entropy exceeding one bit due to the use of a 
bijective operation. This means, it would not matter whether to put the Von-
Neumann unbiaser before or after the folding. However, when putting it after 
the folding, the unbiaser will throw away more values and it would be more 
conservative with this approach (it is more likely to find adjacent 0 0 or 1 1 
combinations than identical adjacent time deltas).

Finally, the Von-Neumann unbiaser applies to individual bits. I am unsure how 
that would fit to the 64 bit time delta value that is the input to the folding 
loop.

> > There are so many assessments on entropy I make, I am surprised that I
> > am said to have no entropy assessment.
> 
> Again: Shannon entropy assumes that you have a sequence of independent
> and identically distributed random variables.  And you cannot prove
> these properties from the output; you need to know the process that
> generates the values.

I am absolutely on your side here. And as we cannot (yet?) fully conclude that 
the observations are independent, a safety margin must always be considered. 
The RNG has the following safety margins where it is more conservative than 
measurements indicate:

- the folding loop produces one bit where measurements of the time deltas that 
go into the folding loop are typically above 2 bits with the lower boundary. 
The upper boundary is typical at 6 bits or higher. Some systems (especially 
older CPUs) show variations that are less than 2 bits with the lower boundary. 
But all of them are well above one bit. (note, my first designs had a folding 
loop that results in three bits, but then I reduced it to two and finally to 
one bit to ensure a safety margin)

- the placement of the Von-Neumann unbiaser will throw away more bits than it 
would when it would be placed before the folding loop. That means that the 
noise source must produce more bits which are assembled into the final random 
number

- the execution of the folding loop with multiples of 64 chosen with another 
time stamp adds more uncertainty over the folding timing -- therefore we have 
an upper boundary for the entropy estimation. I am almost certain that the 
selection of the multiplier value is not independent of the time stamps 
gathered for the time delta measurement (due to using the four lowest bits of 
that time stamp to determine the multiplexer value). That means that the upper 
boundary calculated with the Shannon Entropy formula is certainly too high. 
But the "real" value is above the lower boundary.

Thanks for your thoughts.

Ciao
Stephan
-- 
| Cui bono? |

^ permalink raw reply

* Re: Error inserting sha256_ssse3: No such device
From: Turbo Fredriksson @ 2013-11-13  3:33 UTC (permalink / raw)
  To: linux-crypto
In-Reply-To: <0125C288-B77D-42DA-B018-FAD56CA0FAAC@bayour.com>

On Nov 13, 2013, at 4:08 AM, Turbo Fredriksson wrote:

> 	FATAL: Error inserting sha256_ssse3 (/lib/modules/3.12.0+scst+tf.1/kernel/arch/x86/crypto/sha256-ssse3.ko): No such 

Ok, so digging through the kernel source, I noticed that SSE? is apparently
a CPU feature. This is an AMD Phenom II X6 1100T which seems to only support
SSE and SSE2 (according to /proc/cpuinfo) which might explain the No such
device.

Now my question instead is, why did it try to load sha256_ssse3 in the first
place?
-- 
I love deadlines. I love the whooshing noise they
make as they go by.
- Douglas Adams

^ permalink raw reply

* Re: [PATCH] CPU Jitter RNG: Executing time variation tests on bare metal
From: Stephan Mueller @ 2013-11-13  3:37 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: sandy harris, linux-kernel, linux-crypto, Nicholas Mc Guire,
	Clemens Ladisch, Pavel Machek
In-Reply-To: <20131029132448.GB691@thunk.org>

Am Dienstag, 29. Oktober 2013, 09:24:48 schrieb Theodore Ts'o:

Hi Theodore,

> On Tue, Oct 29, 2013 at 09:42:30AM +0100, Stephan Mueller wrote:
> > Based on this suggestion, I now added the tests in Appendix F.46.8 where
> > I disable the caches and the tests in Appendix F.46.9 where I disable
> > the caches and interrupts.
> 
> What you've added in F.46 is a good start, but as a suggestiom,
> instead of disabling one thing at a time, try disabling *everything*
> and then see what you get, and then enabling one thing at a time.  The
> best thing is if you can get to the point where the amount of entropy
> is close to zero.  Then as you add things back, there's a much better
> sense of where the unpredictability might be coming from, and whether
> the unpredictability is coming from something which is fundamentally
> arising from something which is chaotic or quantum effect, or just
> because we don't have a good way of modelling the behavior of the
> L1/L2 cache (for example) and that is spoofing your entropy estimator.

I was now able to implement two more test buckets that were in my mind for 
quite some time. They are documented in the new sections 6.3 and 6.4 in [1].

The tests for the time variation measurements are now executed on bare metal, 
i.e. without *any* operating system underneath. For achieving that, I used the 
memtest86+ tool, ripped out the memory tests and added the time variation 
testing into it.

The time variation tests now execute single threaded without any interference 
from an underlying operating system. Again, I added all the variations of 
disabling CPU support (TLB flushes, L1/2 flushes, cache disabling, ...).

And, surprise: all the jitter is still there.

Furthermore, I use the same vehicle to just measure the variations by 
obtaining two timestamps immediately after each other and calculate the 
difference. As before, there are various tests which disable the different CPU 
mechanisms.

And, surprise: there is still variations visible. Granted, these variations 
are smaller than the ones for the folding loop. But the smallest variations 
still have way more than 1 bit when applying the Shannon Entropy formula.

The code is uploaded to [2] and can be used to play with.

In addition, I added test resutls with varying loads as explained in section 
6.2 (thanks to Nicholas Mc Guire for helping here).

[1] http://www.chronox.de/jent/doc/CPU-Jitter-NPTRNG.html

[2] http://www.chronox.de/

Ciao
Stephan
-- 
| Cui bono? |

^ permalink raw reply

* [PATCH] crypto: talitos - fix locating offending descriptor in error path
From: Horia Geanta @ 2013-11-13 10:20 UTC (permalink / raw)
  To: linux-crypto; +Cc: Herbert Xu, David S. Miller, Kim Phillips, Lei Xu

Commit 3e721aeb3df3816e283ab18e327cd4652972e213
("crypto: talitos - handle descriptor not found in error path")
tried to address the fact that CDPR (Current Descriptor Pointer Register)
is unreliable.

As it turns out, there are still issues in the function detecting the
offending descriptor:
-only 32 bits of the descriptor address are read, however the address is
36-bit - since reset_channel() initializes channels with EAE (extended
address) bit set
-reading CDPR can return zero in cur_desc; when searching the channel
fifo for this address, cur_desc == dma_desc (= 0) case might happen,
leading to an oops when trying to return desc->hdr (desc is zero)
-read channel's .tail only once; the tail is a moving target; use a
local variable for the end of search condition

Signed-off-by: Lei Xu <Lei.Xu@freescale.com>
Signed-off-by: Horia Geanta <horia.geanta@freescale.com>
Tested-by: Kalyani Chowdhury <Kalyani.Chowdhury@freescale.com>
---
 drivers/crypto/talitos.c |   21 +++++++++++++++------
 1 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index f6f7c68..04c5de3b 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -336,20 +336,29 @@ DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE)
 static u32 current_desc_hdr(struct device *dev, int ch)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
-	int tail = priv->chan[ch].tail;
+	int tail, iter;
 	dma_addr_t cur_desc;
 
-	cur_desc = in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
+	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
+	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
 
-	while (priv->chan[ch].fifo[tail].dma_desc != cur_desc) {
-		tail = (tail + 1) & (priv->fifo_len - 1);
-		if (tail == priv->chan[ch].tail) {
+	if (!cur_desc) {
+		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
+		return 0;
+	}
+
+	tail = priv->chan[ch].tail;
+
+	iter = tail;
+	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) {
+		iter = (iter + 1) & (priv->fifo_len - 1);
+		if (iter == tail) {
 			dev_err(dev, "couldn't locate current descriptor\n");
 			return 0;
 		}
 	}
 
-	return priv->chan[ch].fifo[tail].desc->hdr;
+	return priv->chan[ch].fifo[iter].desc->hdr;
 }
 
 /*
-- 
1.7.7.6

^ permalink raw reply related

* Re: [PATCH] CPU Jitter RNG: inclusion into kernel crypto API and /dev/random
From: Clemens Ladisch @ 2013-11-13 11:51 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Theodore Ts'o, Pavel Machek, sandy harris, linux-kernel,
	linux-crypto, Nicholas Mc Guire
In-Reply-To: <1391779.T98KINxAMQ@myon.chronox.de>

Stephan Mueller wrote:
> Am Sonntag, 10. November 2013, 21:28:06 schrieb Clemens Ladisch:
>> Many CPUs allow to disable branch prediction, but this is very vendor
>> specific (try to find MSR documentation).  The biggest offender probably
>> is the out-of-order execution engine, which cannot be disabled.
>
> For x86, I have not found a way to disable the unit.

My AMD processor can do this in the IC_CFG/DC_CFG MSRs.  (See the BKDG.)

The Intel Core family has other settings (such as data prefetching) that
are configurable in the IA32_MISC_ENABLE MSR.

(And any setting that increases accesses to main memory is likey to
introduce more entropy due to clock drift between the processor and the
memory bus.  Or where do you assume the entropy comes from?)

BTW: MFENCE is not guaranteed to flush the instruction pipeline; you
need CPUID for that.

> XOR is a bijective operation.

Only XOR with a constant, which is not what you're doing.

>>> There are so many assessments on entropy I make, I am surprised that I
>>> am said to have no entropy assessment.
>>
>> Again: Shannon entropy assumes that you have a sequence of independent
>> and identically distributed random variables.  And you cannot prove
>> these properties from the output; you need to know the process that
>> generates the values.
>
> I am absolutely on your side here. And as we cannot (yet?) fully conclude that
> the observations are independent, a safety margin must always be considered.

If the observations are not independent, you cannot just assume that the
estimate is off by a certain factor.  It means that the estimate is not
applicable _at all_.

> The RNG has the following safety margins where it is more conservative than
> measurements indicate:

You _cannot_ measure entropy by looking at the output.  How would you
differentiate between /dev/random and /dev/urandom?


Regards,
Clemens

^ permalink raw reply

* Re: [PATCH] CPU Jitter RNG: inclusion into kernel crypto API and /dev/random
From: Stephan Mueller @ 2013-11-13 15:15 UTC (permalink / raw)
  To: Clemens Ladisch
  Cc: Theodore Ts'o, Pavel Machek, sandy harris, linux-kernel,
	linux-crypto, Nicholas Mc Guire
In-Reply-To: <528367D0.6010900@ladisch.de>

Am Mittwoch, 13. November 2013, 12:51:44 schrieb Clemens Ladisch:

Hi Clemens,

>Stephan Mueller wrote:
>> Am Sonntag, 10. November 2013, 21:28:06 schrieb Clemens Ladisch:
>>> Many CPUs allow to disable branch prediction, but this is very
>>> vendor
>>> specific (try to find MSR documentation).  The biggest offender
>>> probably is the out-of-order execution engine, which cannot be
>>> disabled.> 
>> For x86, I have not found a way to disable the unit.
>
>My AMD processor can do this in the IC_CFG/DC_CFG MSRs.  (See the
>BKDG.)

Thanks for the hint, I will look into that one.
>
>The Intel Core family has other settings (such as data prefetching)
>that are configurable in the IA32_MISC_ENABLE MSR.

Thanks for the hint, I will check that as well.
>
>(And any setting that increases accesses to main memory is likey to
>introduce more entropy due to clock drift between the processor and the
>memory bus.  Or where do you assume the entropy comes from?)

You nailed it. When I disable the caches using the CR0 setting, I get a 
massive increase in variations and thus entropy.
>
>BTW: MFENCE is not guaranteed to flush the instruction pipeline; you
>need CPUID for that.

I was not aware of that. Can I simply call the CPUID instruction to read 
it or do I have to do something special?
>
>> XOR is a bijective operation.
>
>Only XOR with a constant, which is not what you're doing.

If you want to regain the full 64 bit input bit stream, then you are 
right.

But still, XOR is bijective with respect to the two bits that go into 
the operation. Before I released the RNG work, I had the mathematical 
side and the entropy consideration analyzed by a mathematician who is 
specialized in the field of cryptography and statistics. She actually 
said that this folding based on XOR is an appropriate way to collapse 
the string and yet retain entropy.
>
>>>> There are so many assessments on entropy I make, I am surprised
>>>> that I
>>>> am said to have no entropy assessment.
>>> 
>>> Again: Shannon entropy assumes that you have a sequence of
>>> independent
>>> and identically distributed random variables.  And you cannot prove
>>> these properties from the output; you need to know the process that
>>> generates the values.
>> 
>> I am absolutely on your side here. And as we cannot (yet?) fully
>> conclude that the observations are independent, a safety margin must
>> always be considered.
>If the observations are not independent, you cannot just assume that
>the estimate is off by a certain factor.  It means that the estimate
>is not applicable _at all_.

Well, I am not so sure here. If there are concerns on independence 
(which I currently do not have, but more to that below), I have always 
seen that safety margins are put in place. And that is what I tried here 
as well.
>
>> The RNG has the following safety margins where it is more
>> conservative than
>> measurements indicate:
>You _cannot_ measure entropy by looking at the output.  How would you
>differentiate between /dev/random and /dev/urandom?

I think regarding the independence you can very well draw the conclusion 
based on the output, because any dependencies will ultimately form a 
pattern. That pattern would initially be visible in the measurements 
that go into the folding loop. What I now must show is that these 
measurements do not have a pattern.

In addition, we need to keep in mind that the independence claim is 
relative just like the entropy itself.

If you have an output string that has no detectable patterns, i.e. looks 
like white noise, you can only assume that the observations are 
independent of each other. If there are patterns, you know that there 
are dependencies.

That statement may *not* apply any more if you look at the internals of 
the RNG. In such a case, you may have even strong dependencies.

The best example on this matter are deterministic RNGs with a 
cryptographic output function. When you see the output string, you only 
see white noise. As you cannot detect a pattern, you have to assume that 
the string provides independent observations. At least for you who looks 
from the outside cannot draw any conclusions from observing some output 
bit stream which would be the future bit stream. Yet, when you know the 
state of the RNG, you entire future output bit stream has no 
independence.

Coming back to the jitter RNG: I applied a large array of statistical 
tests and all of them concluded that the output is white noise, as 
explained in the documentation. That means when looking from the 
outside, there are no dependencies visible. Now you may say that this 
conclusion does not mean that there are no dependencies -- but I reply 
again, if there would be any, none of the array of statistical tests can 
detect it. So, how would an attacker detect patterns? And again, I 
cannot prove it just like nobody else cannot prove it for other hardware 
noise sources.

In addition, when we conclude that the output bit stream has no 
dependencies due to the absence of patterns and considering the folding 
operation not disguising patterns from the underlying measurements, I 
draw the conclusion that there are no patterns in the underlying 
measurements. The "Anti-Tests" I outline in section 4.3 show that if 
there would be patterns in the underlying measurements, it is 
immediately visible in the output bit stream.
>
>
>Regards,
>Clemens


Ciao
Stephan

^ permalink raw reply

* Re: [PATCH] CPU Jitter RNG: inclusion into kernel crypto API and /dev/random
From: Pavel Machek @ 2013-11-13 17:14 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Clemens Ladisch, Theodore Ts'o, sandy harris, linux-kernel,
	linux-crypto, Nicholas Mc Guire
In-Reply-To: <27146362.bQgmetPpTV@tauon>

Hi!

> >BTW: MFENCE is not guaranteed to flush the instruction pipeline; you
> >need CPUID for that.
> 
> I was not aware of that. Can I simply call the CPUID instruction to read 
> it or do I have to do something special?

Simply call CPUID (warning, it clobbers some registers.).
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* Re: [PATCH] CPU Jitter RNG: inclusion into kernel crypto API and /dev/random
From: Clemens Ladisch @ 2013-11-14 10:51 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Theodore Ts'o, Pavel Machek, sandy harris, linux-kernel,
	linux-crypto, Nicholas Mc Guire
In-Reply-To: <27146362.bQgmetPpTV@tauon>

Stephan Mueller wrote:
> Am Mittwoch, 13. November 2013, 12:51:44 schrieb Clemens Ladisch:
>> (And any setting that increases accesses to main memory is likey to
>> introduce more entropy due to clock drift between the processor and the
>> memory bus.  Or where do you assume the entropy comes from?)
>
> You nailed it. When I disable the caches using the CR0 setting, I get a
> massive increase in variations and thus entropy.

Now this would be an opportunity to use the number of main memory
accesses to estimate entropy.  (And when you're running out of the
cache, i.e., deterministically, is there any entropy?)

>>> XOR is a bijective operation.
>>
>> Only XOR with a constant, which is not what you're doing.
>
> If you want to regain the full 64 bit input bit stream, then you are
> right.
>
> But still, XOR is bijective with respect to the two bits that go into
> the operation.

Please look up what "bijective" actually means:
<http://en.wikipedia.org/wiki/Bijection>

> folding based on XOR is an appropriate way to collapse the string and
> yet retain entropy.

Correct, but the reason for that is not being bijective.

>> If the observations are not independent, you cannot just assume that
>> the estimate is off by a certain factor.  It means that the estimate
>> is not applicable _at all_.
>
> Well, I am not so sure here.

So, what is the factor that you are saying is large enough?

>>> The RNG has the following safety margins where it is more conservative than
>>> measurements indicate:
>>
>> You _cannot_ measure entropy by looking at the output.  How would you
>> differentiate between /dev/random and /dev/urandom?
>
> I think regarding the independence you can very well draw the conclusion
> based on the output, because any dependencies will ultimately form a
> pattern.

The output of a pure PRNG (such as /dev/urandom without entropy) is
dependent on the internal state, but there are no patterns detectable
from the output alone.

> In addition, we need to keep in mind that the independence claim is
> relative

No, independence is a property of the process that generates the
samples.

> If you have an output string that has no detectable patterns, i.e. looks
> like white noise, you can only assume that the observations are
> independent of each other. If there are patterns, you know that there
> are dependencies.
>
> That statement may *not* apply any more if you look at the internals of
> the RNG. In such a case, you may have even strong dependencies.
>
> The best example on this matter are deterministic RNGs with a
> cryptographic output function. When you see the output string, you only
> see white noise. As you cannot detect a pattern, you have to assume that
> the string provides independent observations. At least for you who looks
> from the outside cannot draw any conclusions from observing some output
> bit stream which would be the future bit stream. Yet, when you know the
> state of the RNG, you entire future output bit stream has no
> independence.

You cannot restrict the analysis to observations from the outside;
there are many people who can know about the CPU's internal structure.

> Coming back to the jitter RNG: I applied a large array of statistical
> tests and all of them concluded that the output is white noise, as
> explained in the documentation. That means when looking from the
> outside, there are no dependencies visible. Now you may say that this
> conclusion does not mean that there are no dependencies -- but I reply
> again, if there would be any, none of the array of statistical tests can
> detect it. So, how would an attacker detect patterns?

An attacker would not try to detect patterns; he would apply knowledge
of the internals.

Statistical tests are useful only for detecting the absence of entropy,
not for the opposite.


All your arguments about the output of the CPU jitter RNG also apply to
the output of /dev/urandom.  So are you saying that it would be a good
idea to loop the output of /dev/urandom back into /dev/random?


Regards,
Clemens

^ permalink raw reply

* Re: crypto: s390 - Fix aes-cbc IV corruption
From: Jan Glauber @ 2013-11-14 16:10 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Linux Crypto Mailing List, Jan Glauber
In-Reply-To: <20131031032547.GA16528@gondor.apana.org.au>

On Thu, Oct 31, 2013 at 11:25:47AM +0800, Herbert Xu wrote:
> Hi:

Hi Herbert,

just seen this as my old email address is dead... Your patch looks
fine as it keeps the iv and the key together as required by the instruction.

However, I'm curious how this could be racy with threads. The encryption must
be serialized because of the chaining. The decryption could in theory happen
in parallel, but is this the case here?

--Jan

> The cbc-aes-s390 algorithm incorrectly places the IV in the tfm
> data structure.  As the tfm is shared between multiple threads,
> this introduces a possibility of data corruption.
> 
> This patch fixes this by moving the parameter block containing
> the IV and key onto the stack (the block is 48 bytes long).
> 
> The same bug exists elsewhere in the s390 crypto system and they
> will be fixed in subsequent patches.
> 
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> 
> diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
> index b4dbade..2e4b5be 100644
> --- a/arch/s390/crypto/aes_s390.c
> +++ b/arch/s390/crypto/aes_s390.c
> @@ -35,7 +35,6 @@ static u8 *ctrblk;
>  static char keylen_flag;
>  
>  struct s390_aes_ctx {
> -	u8 iv[AES_BLOCK_SIZE];
>  	u8 key[AES_MAX_KEY_SIZE];
>  	long enc;
>  	long dec;
> @@ -441,30 +440,36 @@ static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
>  	return aes_set_key(tfm, in_key, key_len);
>  }
>  
> -static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
> +static int cbc_aes_crypt(struct blkcipher_desc *desc, long func,
>  			 struct blkcipher_walk *walk)
>  {
> +	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
>  	int ret = blkcipher_walk_virt(desc, walk);
>  	unsigned int nbytes = walk->nbytes;
> +	struct {
> +		u8 iv[AES_BLOCK_SIZE];
> +		u8 key[AES_MAX_KEY_SIZE];
> +	} param;
>  
>  	if (!nbytes)
>  		goto out;
>  
> -	memcpy(param, walk->iv, AES_BLOCK_SIZE);
> +	memcpy(param.iv, walk->iv, AES_BLOCK_SIZE);
> +	memcpy(param.key, sctx->key, sctx->key_len);
>  	do {
>  		/* only use complete blocks */
>  		unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
>  		u8 *out = walk->dst.virt.addr;
>  		u8 *in = walk->src.virt.addr;
>  
> -		ret = crypt_s390_kmc(func, param, out, in, n);
> +		ret = crypt_s390_kmc(func, &param, out, in, n);
>  		if (ret < 0 || ret != n)
>  			return -EIO;
>  
>  		nbytes &= AES_BLOCK_SIZE - 1;
>  		ret = blkcipher_walk_done(desc, walk, nbytes);
>  	} while ((nbytes = walk->nbytes));
> -	memcpy(walk->iv, param, AES_BLOCK_SIZE);
> +	memcpy(walk->iv, param.iv, AES_BLOCK_SIZE);
>  
>  out:
>  	return ret;
> @@ -481,7 +486,7 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
>  		return fallback_blk_enc(desc, dst, src, nbytes);
>  
>  	blkcipher_walk_init(&walk, dst, src, nbytes);
> -	return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
> +	return cbc_aes_crypt(desc, sctx->enc, &walk);
>  }
>  
>  static int cbc_aes_decrypt(struct blkcipher_desc *desc,
> @@ -495,7 +500,7 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
>  		return fallback_blk_dec(desc, dst, src, nbytes);
>  
>  	blkcipher_walk_init(&walk, dst, src, nbytes);
> -	return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
> +	return cbc_aes_crypt(desc, sctx->dec, &walk);
>  }
>  
>  static struct crypto_alg cbc_aes_alg = {
> 
> Cheers,
> -- 
> Email: Herbert Xu <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] CPU Jitter RNG: inclusion into kernel crypto API and /dev/random
From: Stephan Mueller @ 2013-11-14 18:01 UTC (permalink / raw)
  To: Clemens Ladisch
  Cc: Theodore Ts'o, Pavel Machek, sandy harris, linux-kernel,
	linux-crypto, Nicholas Mc Guire
In-Reply-To: <5284AB17.5050802@ladisch.de>

Am Donnerstag, 14. November 2013, 11:51:03 schrieb Clemens Ladisch:

Hi Clemens,

>Stephan Mueller wrote:
>> Am Mittwoch, 13. November 2013, 12:51:44 schrieb Clemens Ladisch:
>>> (And any setting that increases accesses to main memory is likey to
>>> introduce more entropy due to clock drift between the processor and
>>> the memory bus.  Or where do you assume the entropy comes from?)
>> 
>> You nailed it. When I disable the caches using the CR0 setting, I get
>> a massive increase in variations and thus entropy.
>
>Now this would be an opportunity to use the number of main memory
>accesses to estimate entropy.  (And when you're running out of the
>cache, i.e., deterministically, is there any entropy?)
>

I seem to have found the root cause with my bare metal tester, but I am 
yet unable to make sense of it.

I will report back with more analyses.


>An attacker would not try to detect patterns; he would apply knowledge
>of the internals.

I do not buy that argument, because if an attacker can detect or deduce 
the internals of the CPU, he surely can detect the state of the 
input_pool or the other entropy pools behind /dev/random. And then, 
/dev/random is not so entropic any more for that attacker.
>
>Statistical tests are useful only for detecting the absence of entropy,
>not for the opposite.

Again, I fully agree. But it is equally important to understand that 
entropy is relative. And all I want and all I care about is that an 
attacker has only the knowledge and ability to make measurements that 
are less precise than 1 bit.

Ciao
Stephan

^ permalink raw reply

* Re: [PATCH] CPU Jitter RNG: inclusion into kernel crypto API and /dev/random
From: Clemens Ladisch @ 2013-11-14 18:30 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Theodore Ts'o, Pavel Machek, sandy harris, linux-kernel,
	linux-crypto, Nicholas Mc Guire
In-Reply-To: <3127174.i8ueAho43m@tauon>

Stephan Mueller wrote:
> Am Donnerstag, 14. November 2013, 11:51:03 schrieb Clemens Ladisch:
>> An attacker would not try to detect patterns; he would apply knowledge
>> of the internals.
>
> I do not buy that argument, because if an attacker can detect or deduce
> the internals of the CPU, he surely can detect the state of the
> input_pool or the other entropy pools behind /dev/random.

With "internals", I do not mean the actual state of the CPU, but the
behaviour of all the CPU's execution engines.

An Intel engineer might know how to affect the CPU so that the CPU
jitter code measures a deterministic pattern, but he will not know the
contents of my memory.

>> Statistical tests are useful only for detecting the absence of entropy,
>> not for the opposite.
>
> Again, I fully agree. But it is equally important to understand that
> entropy is relative.

In cryptography, we care about absolute entropy, i.e., _nobody_ must be
able to predict the RNG output, not even any CPU engineer.


Regards,
Clemens

^ permalink raw reply

* Re: [PATCH] CPU Jitter RNG: inclusion into kernel crypto API and /dev/random
From: Stephan Mueller @ 2013-11-14 18:34 UTC (permalink / raw)
  To: Clemens Ladisch
  Cc: Theodore Ts'o, Pavel Machek, sandy harris, linux-kernel,
	linux-crypto, Nicholas Mc Guire
In-Reply-To: <528516BE.2040204@ladisch.de>

Am Donnerstag, 14. November 2013, 19:30:22 schrieb Clemens Ladisch:

Hi Clemens,

>Stephan Mueller wrote:
>> Am Donnerstag, 14. November 2013, 11:51:03 schrieb Clemens Ladisch:
>>> An attacker would not try to detect patterns; he would apply
>>> knowledge
>>> of the internals.
>> 
>> I do not buy that argument, because if an attacker can detect or
>> deduce the internals of the CPU, he surely can detect the state of
>> the input_pool or the other entropy pools behind /dev/random.
>
>With "internals", I do not mean the actual state of the CPU, but the
>behaviour of all the CPU's execution engines.
>
>An Intel engineer might know how to affect the CPU so that the CPU
>jitter code measures a deterministic pattern, but he will not know the
>contents of my memory.

Here I agree fully.
>
>>> Statistical tests are useful only for detecting the absence of
>>> entropy, not for the opposite.
>> 
>> Again, I fully agree. But it is equally important to understand that
>> entropy is relative.
>
>In cryptography, we care about absolute entropy, i.e., _nobody_ must be
>able to predict the RNG output, not even any CPU engineer.

With your clarification above, I agree here fully.

And now my task is to verify the root cause which I seem to have found.

Let me do my homework.

Ciao
Stephan

^ permalink raw reply

* [PATCH] crypto: fix potential NULL pointer dereference in skcipher_alloc_sgl()
From: Jeff Liu @ 2013-11-15  2:31 UTC (permalink / raw)
  To: linux-crypto; +Cc: herbert, davem

From: Jie Liu <jeff.liu@oracle.com>

In skcipher_alloc_sgl(), there is a potential null pointer dereference
issue to retrieve the last item from ctx->tsgl list if the list is empty.

This patch fix it by checking if the list is empty or not at first.

Signed-off-by: Jie Liu <jeff.liu@oracle.com>
---
 crypto/algif_skcipher.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index a1c4f0a..bfa702e 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -73,9 +73,10 @@ static int skcipher_alloc_sgl(struct sock *sk)
 	struct skcipher_sg_list *sgl;
 	struct scatterlist *sg = NULL;
 
-	sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
-	if (!list_empty(&ctx->tsgl))
+	if (!list_empty(&ctx->tsgl)) {
+		sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
 		sg = sgl->sg;
+	}
 
 	if (!sg || sgl->cur >= MAX_SGL_ENTS) {
 		sgl = sock_kmalloc(sk, sizeof(*sgl) +
-- 
1.8.3.2

^ permalink raw reply related

* Re: [PATCH 16/51] DMA-API: ppc: vio.c: replace dma_set_mask()+dma_set_coherent_mask() with new helper
From: Cedric Le Goater @ 2013-11-15 16:16 UTC (permalink / raw)
  To: Russell King
  Cc: alsa-devel, b43-dev, devel, devicetree, dri-devel, e1000-devel,
	linux-arm-kernel, linux-crypto, linux-doc, linux-fbdev, linux-ide,
	linux-media, linux-mmc, linux-nvme, linux-omap, linuxppc-dev,
	linux-samsung-soc, linux-scsi, linux-tegra, linux-usb,
	linux-wireless, netdev, Solarflare linux maintainers,
	uclinux-dist-devel, Paul Mackerras, Benjamin Herrenschmidt
In-Reply-To: <E1VMly8-0007gy-Ru@rmk-PC.arm.linux.org.uk>

Hi, 

On 09/19/2013 11:41 PM, Russell King wrote:
> Replace the following sequence:
> 
> 	dma_set_mask(dev, mask);
> 	dma_set_coherent_mask(dev, mask);
> 
> with a call to the new helper dma_set_mask_and_coherent().
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  arch/powerpc/kernel/vio.c |    3 +--
>  1 files changed, 1 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
> index 78a3506..96b6c97 100644
> --- a/arch/powerpc/kernel/vio.c
> +++ b/arch/powerpc/kernel/vio.c
> @@ -1413,8 +1413,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
> 
>  		/* needed to ensure proper operation of coherent allocations
>  		 * later, in case driver doesn't set it explicitly */
> -		dma_set_mask(&viodev->dev, DMA_BIT_MASK(64));
> -		dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64));
> +		dma_set_mask_and_coherent(&viodev->dev, DMA_BIT_MASK(64));
>  	}
> 
>  	/* register with generic device framework */
> 

The new helper routine dma_set_mask_and_coherent() breaks the 
initialization of the pseries vio devices which do not have an 
initial dev->dma_mask. I think we need to use dma_coerce_mask_and_coherent()
instead.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 arch/powerpc/kernel/vio.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index e7d0c88f..76a6482 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -1419,7 +1419,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
 
 		/* needed to ensure proper operation of coherent allocations
 		 * later, in case driver doesn't set it explicitly */
-		dma_set_mask_and_coherent(&viodev->dev, DMA_BIT_MASK(64));
+		dma_coerce_mask_and_coherent(&viodev->dev, DMA_BIT_MASK(64));
 	}
 
 	/* register with generic device framework */
-- 
1.7.10.4

^ permalink raw reply related

* [RFC 08/23] crypto: omap-aes - raw read and write endian fix
From: Taras Kondratiuk @ 2013-11-16  0:01 UTC (permalink / raw)
  To: linux-omap
  Cc: linaro-networking, Victor Kamensky, Herbert Xu, David S. Miller,
	linux-crypto, linux-kernel
In-Reply-To: <1384560086-11994-1-git-send-email-taras.kondratiuk@linaro.org>

From: Victor Kamensky <victor.kamensky@linaro.org>

All OMAP IP blocks expect LE data, but CPU may operate in BE mode.
Need to use endian neutral functions to read/write h/w registers.
I.e instead of __raw_read[lw] and __raw_write[lw] functions code
need to use read[lw]_relaxed and write[lw]_relaxed functions.
If the first simply reads/writes register, the second will byteswap
it if host operates in BE mode.

Changes are trivial sed like replacement of __raw_xxx functions
with xxx_relaxed variant.

Signed-off-by: Victor Kamensky <victor.kamensky@linaro.org>
Signed-off-by: Taras Kondratiuk <taras.kondratiuk@linaro.org>
---
 drivers/crypto/omap-aes.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index ce791c2..777ae0a 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -195,7 +195,7 @@ static DEFINE_SPINLOCK(list_lock);
 #define omap_aes_read(dd, offset)				\
 ({								\
 	int _read_ret;						\
-	_read_ret = __raw_readl(dd->io_base + offset);		\
+	_read_ret = readl_relaxed(dd->io_base + offset);		\
 	pr_debug("omap_aes_read(" #offset "=%#x)= %#x\n",	\
 		 offset, _read_ret);				\
 	_read_ret;						\
@@ -203,7 +203,7 @@ static DEFINE_SPINLOCK(list_lock);
 #else
 static inline u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset)
 {
-	return __raw_readl(dd->io_base + offset);
+	return readl_relaxed(dd->io_base + offset);
 }
 #endif
 
@@ -212,13 +212,13 @@ static inline u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset)
 	do {								\
 		pr_debug("omap_aes_write(" #offset "=%#x) value=%#x\n",	\
 			 offset, value);				\
-		__raw_writel(value, dd->io_base + offset);		\
+		writel_relaxed(value, dd->io_base + offset);		\
 	} while (0)
 #else
 static inline void omap_aes_write(struct omap_aes_dev *dd, u32 offset,
 				  u32 value)
 {
-	__raw_writel(value, dd->io_base + offset);
+	writel_relaxed(value, dd->io_base + offset);
 }
 #endif
 
-- 
1.7.9.5

^ permalink raw reply related

* [RFC 09/23] crypto: omap-sham - raw read and write endian fix
From: Taras Kondratiuk @ 2013-11-16  0:01 UTC (permalink / raw)
  To: linux-omap
  Cc: linaro-networking, Victor Kamensky, Herbert Xu, David S. Miller,
	linux-crypto, linux-kernel
In-Reply-To: <1384560086-11994-1-git-send-email-taras.kondratiuk@linaro.org>

From: Victor Kamensky <victor.kamensky@linaro.org>

All OMAP IP blocks expect LE data, but CPU may operate in BE mode.
Need to use endian neutral functions to read/write h/w registers.
I.e instead of __raw_read[lw] and __raw_write[lw] functions code
need to use read[lw]_relaxed and write[lw]_relaxed functions.
If the first simply reads/writes register, the second will byteswap
it if host operates in BE mode.

Changes are trivial sed like replacement of __raw_xxx functions
with xxx_relaxed variant.

Signed-off-by: Victor Kamensky <victor.kamensky@linaro.org>
Signed-off-by: Taras Kondratiuk <taras.kondratiuk@linaro.org>
---
 drivers/crypto/omap-sham.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 8bdde57..b011b97 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -244,13 +244,13 @@ static struct omap_sham_drv sham = {
 
 static inline u32 omap_sham_read(struct omap_sham_dev *dd, u32 offset)
 {
-	return __raw_readl(dd->io_base + offset);
+	return readl_relaxed(dd->io_base + offset);
 }
 
 static inline void omap_sham_write(struct omap_sham_dev *dd,
 					u32 offset, u32 value)
 {
-	__raw_writel(value, dd->io_base + offset);
+	writel_relaxed(value, dd->io_base + offset);
 }
 
 static inline void omap_sham_write_mask(struct omap_sham_dev *dd, u32 address,
-- 
1.7.9.5


^ 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