[PATCH 07/10] crypto: CCP XTS-AES crypto API support

2013-11-12 Thread Tom Lendacky
These routines provide crypto API support for the XTS-AES mode of AES
on the AMD CCP.

Signed-off-by: Tom Lendacky 
---
 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 000..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 
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#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(>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);
+   

[PATCH 07/10] crypto: CCP XTS-AES crypto API support

2013-11-12 Thread Tom Lendacky
These routines provide crypto API support for the XTS-AES mode of AES
on the AMD CCP.

Signed-off-by: Tom Lendacky 
---
 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 000..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 
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#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(>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);
+   

[PATCH 07/10] crypto: CCP XTS-AES crypto API support

2013-11-12 Thread Tom Lendacky
These routines provide crypto API support for the XTS-AES mode of AES
on the AMD CCP.

Signed-off-by: Tom Lendacky thomas.lenda...@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 000..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.lenda...@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 

[PATCH 07/10] crypto: CCP XTS-AES crypto API support

2013-11-12 Thread Tom Lendacky
These routines provide crypto API support for the XTS-AES mode of AES
on the AMD CCP.

Signed-off-by: Tom Lendacky thomas.lenda...@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 000..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.lenda...@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