Re: [PATCH 5/6] crypto: ccp - Enable support for AES GCM on v5 CCPs

2016-10-13 Thread Tom Lendacky
On 10/13/2016 09:53 AM, Gary R Hook wrote:
> A version 5 device provides the primitive commands
> required for AES GCM. This patch adds support for
> en/decryption.
> 
> Signed-off-by: Gary R Hook 
> ---
>  drivers/crypto/ccp/Makefile|1 
>  drivers/crypto/ccp/ccp-crypto-aes-galois.c |  252 +++
>  drivers/crypto/ccp/ccp-crypto-main.c   |   12 +
>  drivers/crypto/ccp/ccp-crypto.h|   14 +
>  drivers/crypto/ccp/ccp-dev-v5.c|2 
>  drivers/crypto/ccp/ccp-dev.h   |1 
>  drivers/crypto/ccp/ccp-ops.c   |  262 
> 
>  include/linux/ccp.h|9 +
>  8 files changed, 553 insertions(+)
>  create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-galois.c
> 
> diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
> index 23f89b7..fd77225 100644
> --- a/drivers/crypto/ccp/Makefile
> +++ b/drivers/crypto/ccp/Makefile
> @@ -13,4 +13,5 @@ ccp-crypto-objs := ccp-crypto-main.o \
>  ccp-crypto-aes-cmac.o \
>  ccp-crypto-aes-xts.o \
>  ccp-crypto-rsa.o \
> +ccp-crypto-aes-galois.o \
>  ccp-crypto-sha.o
> diff --git a/drivers/crypto/ccp/ccp-crypto-aes-galois.c 
> b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
> new file mode 100644
> index 000..5da324f
> --- /dev/null
> +++ b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
> @@ -0,0 +1,252 @@
> +/*
> + * AMD Cryptographic Coprocessor (CCP) AES crypto API support
> + *
> + * Copyright (C) 2013,2016 Advanced Micro Devices, Inc.
> + *
> + * Author: Tom Lendacky 

Maybe put your name here...

> + *
> + * 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 
> +#include 
> +#include 
> +
> +#include "ccp-crypto.h"
> +
> +#define  AES_GCM_IVSIZE  12
> +
> +static int ccp_aes_gcm_complete(struct crypto_async_request *async_req, int 
> ret)
> +{
> + return ret;
> +}
> +
> +static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
> +   unsigned int key_len)
> +{
> + struct ccp_ctx *ctx = crypto_aead_ctx(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_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
> + return -EINVAL;
> + }
> +
> + ctx->u.aes.mode = CCP_AES_MODE_GCM;
> + 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_gcm_setauthsize(struct crypto_aead *tfm,
> +unsigned int authsize)
> +{
> + return 0;
> +}
> +
> +static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
> +{
> + struct crypto_aead *tfm = crypto_aead_reqtfm(req);
> + struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
> + struct ccp_aes_req_ctx *rctx = aead_request_ctx(req);
> + struct scatterlist *iv_sg = NULL;
> + unsigned int iv_len = 0;
> + int i;
> + int ret = 0;
> +
> + if (!ctx->u.aes.key_len)
> + return -EINVAL;
> +
> + if (ctx->u.aes.mode != CCP_AES_MODE_GCM)
> + return -EINVAL;
> +
> + if (!req->iv)
> + return -EINVAL;
> +
> + /*
> +  * 5 parts:
> +  *   plaintext/ciphertext input
> +  *   AAD
> +  *   key
> +  *   IV
> +  *   Destination+tag buffer
> +  */
> +
> + /* Copy the IV and initialize a scatterlist */
> + memset(rctx->iv, 0, AES_BLOCK_SIZE);
> + memcpy(rctx->iv, req->iv, AES_GCM_IVSIZE);
> + for (i = 0; i < 3; i++)
> + rctx->iv[i + AES_GCM_IVSIZE] = 0;

Is this needed if you did the memset to zero above?

> + rctx->iv[AES_BLOCK_SIZE - 1] = 1;
> + iv_sg = &rctx->iv_sg;
> + iv_len = AES_BLOCK_SIZE;
> + sg_init_one(iv_sg, rctx->iv, iv_len);
> +
> + /* The AAD + plaintext are concatenated in the src buffer */
> + 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-

[PATCH 5/6] crypto: ccp - Enable support for AES GCM on v5 CCPs

2016-10-13 Thread Gary R Hook
A version 5 device provides the primitive commands
required for AES GCM. This patch adds support for
en/decryption.

Signed-off-by: Gary R Hook 
---
 drivers/crypto/ccp/Makefile|1 
 drivers/crypto/ccp/ccp-crypto-aes-galois.c |  252 +++
 drivers/crypto/ccp/ccp-crypto-main.c   |   12 +
 drivers/crypto/ccp/ccp-crypto.h|   14 +
 drivers/crypto/ccp/ccp-dev-v5.c|2 
 drivers/crypto/ccp/ccp-dev.h   |1 
 drivers/crypto/ccp/ccp-ops.c   |  262 
 include/linux/ccp.h|9 +
 8 files changed, 553 insertions(+)
 create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-galois.c

diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
index 23f89b7..fd77225 100644
--- a/drivers/crypto/ccp/Makefile
+++ b/drivers/crypto/ccp/Makefile
@@ -13,4 +13,5 @@ ccp-crypto-objs := ccp-crypto-main.o \
   ccp-crypto-aes-cmac.o \
   ccp-crypto-aes-xts.o \
   ccp-crypto-rsa.o \
+  ccp-crypto-aes-galois.o \
   ccp-crypto-sha.o
diff --git a/drivers/crypto/ccp/ccp-crypto-aes-galois.c 
b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
new file mode 100644
index 000..5da324f
--- /dev/null
+++ b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
@@ -0,0 +1,252 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) AES crypto API support
+ *
+ * Copyright (C) 2013,2016 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 
+#include 
+#include 
+
+#include "ccp-crypto.h"
+
+#defineAES_GCM_IVSIZE  12
+
+static int ccp_aes_gcm_complete(struct crypto_async_request *async_req, int 
ret)
+{
+   return ret;
+}
+
+static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
+ unsigned int key_len)
+{
+   struct ccp_ctx *ctx = crypto_aead_ctx(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_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+   return -EINVAL;
+   }
+
+   ctx->u.aes.mode = CCP_AES_MODE_GCM;
+   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_gcm_setauthsize(struct crypto_aead *tfm,
+  unsigned int authsize)
+{
+   return 0;
+}
+
+static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
+{
+   struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+   struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
+   struct ccp_aes_req_ctx *rctx = aead_request_ctx(req);
+   struct scatterlist *iv_sg = NULL;
+   unsigned int iv_len = 0;
+   int i;
+   int ret = 0;
+
+   if (!ctx->u.aes.key_len)
+   return -EINVAL;
+
+   if (ctx->u.aes.mode != CCP_AES_MODE_GCM)
+   return -EINVAL;
+
+   if (!req->iv)
+   return -EINVAL;
+
+   /*
+* 5 parts:
+*   plaintext/ciphertext input
+*   AAD
+*   key
+*   IV
+*   Destination+tag buffer
+*/
+
+   /* Copy the IV and initialize a scatterlist */
+   memset(rctx->iv, 0, AES_BLOCK_SIZE);
+   memcpy(rctx->iv, req->iv, AES_GCM_IVSIZE);
+   for (i = 0; i < 3; i++)
+   rctx->iv[i + AES_GCM_IVSIZE] = 0;
+   rctx->iv[AES_BLOCK_SIZE - 1] = 1;
+   iv_sg = &rctx->iv_sg;
+   iv_len = AES_BLOCK_SIZE;
+   sg_init_one(iv_sg, rctx->iv, iv_len);
+
+   /* The AAD + plaintext are concatenated in the src buffer */
+   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->cryptlen;
+   rctx->cmd.u.aes.aad_len = req->assoclen;
+
+   /* The cipher text + the tag are in the dst buffer */
+   rctx->cmd.u.aes.ds