Re: [PATCH 6/6] crypto: ccp - Enable 3DES function on v5 CCPs

2016-10-13 Thread Tom Lendacky
On 10/13/2016 09:53 AM, Gary R Hook wrote:
> Wire up support for Triple DES in ECB mode.
> 
> Signed-off-by: Gary R Hook 
> ---
>  drivers/crypto/ccp/Makefile  |1 
>  drivers/crypto/ccp/ccp-crypto-des3.c |  254 
> ++
>  drivers/crypto/ccp/ccp-crypto-main.c |   10 +
>  drivers/crypto/ccp/ccp-crypto.h  |   25 +++
>  drivers/crypto/ccp/ccp-dev-v3.c  |1 
>  drivers/crypto/ccp/ccp-dev-v5.c  |   65 -
>  drivers/crypto/ccp/ccp-dev.h |   18 ++
>  drivers/crypto/ccp/ccp-ops.c |  201 +++
>  drivers/crypto/ccp/ccp-pci.c |2 
>  include/linux/ccp.h  |   57 +++-
>  10 files changed, 624 insertions(+), 10 deletions(-)
>  create mode 100644 drivers/crypto/ccp/ccp-crypto-des3.c
> 

...  ...

> --- a/drivers/crypto/ccp/ccp-crypto.h
> +++ b/drivers/crypto/ccp/ccp-crypto.h
> @@ -26,6 +26,8 @@
>  #include 
>  #include 
>  
> +#define  CCP_LOG_LEVEL   KERN_INFO
> +

Not used anywhere that I can tell.

>  #define CCP_CRA_PRIORITY 300
>  
>  struct ccp_crypto_ablkcipher_alg {
> @@ -151,7 +153,26 @@ struct ccp_aes_cmac_exp_ctx {
>   u8 buf[AES_BLOCK_SIZE];
>  };
>  
> -/* SHA-related defines
> +/* 3DES related defines */
> +struct ccp_des3_ctx {
> + enum ccp_engine engine;
> + enum ccp_des3_type type;
> + enum ccp_des3_mode mode;
> +
> + struct scatterlist key_sg;
> + unsigned int key_len;
> + u8 key[AES_MAX_KEY_SIZE];
> +};
> +
> +struct ccp_des3_req_ctx {
> + struct scatterlist iv_sg;
> + u8 iv[AES_BLOCK_SIZE];
> +
> + struct ccp_cmd cmd;
> +};
> +
> +/*
> + * SHA-related defines
>   * These values must be large enough to accommodate any variant
>   */
>  #define MAX_SHA_CONTEXT_SIZE SHA512_DIGEST_SIZE
> @@ -236,6 +257,7 @@ struct ccp_ctx {
>   struct ccp_aes_ctx aes;
>   struct ccp_rsa_ctx rsa;
>   struct ccp_sha_ctx sha;
> + struct ccp_des3_ctx des3;
>   } u;
>  };
>  
> @@ -251,5 +273,6 @@ int ccp_register_aes_aeads(struct list_head *head);
>  int ccp_register_sha_algs(struct list_head *head);
>  int ccp_register_rsa_algs(void);
>  void ccp_unregister_rsa_algs(void);
> +int ccp_register_des3_algs(struct list_head *head);
>  
>  #endif
> diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c
> index 75a0978..fccca16 100644
> --- a/drivers/crypto/ccp/ccp-dev-v3.c
> +++ b/drivers/crypto/ccp/ccp-dev-v3.c
> @@ -595,6 +595,7 @@ static irqreturn_t ccp_irq_handler(int irq, void *data)
>  static const struct ccp_actions ccp3_actions = {
>   .aes = ccp_perform_aes,
>   .xts_aes = ccp_perform_xts_aes,
> + .des3 = NULL,
>   .sha = ccp_perform_sha,
>   .rsa = ccp_perform_rsa,
>   .passthru = ccp_perform_passthru,
> diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c
> index dcae391..85387dc 100644
> --- a/drivers/crypto/ccp/ccp-dev-v5.c
> +++ b/drivers/crypto/ccp/ccp-dev-v5.c
> @@ -101,6 +101,12 @@ union ccp_function {
>   u16 type:2;
>   } aes_xts;
>   struct {
> + u16 size:7;
> + u16 encrypt:1;
> + u16 mode:5;
> + u16 type:2;
> + } des3;
> + struct {
>   u16 rsvd1:10;
>   u16 type:4;
>   u16 rsvd2:1;
> @@ -132,6 +138,10 @@ union ccp_function {
>  #define  CCP_AES_TYPE(p) ((p)->aes.type)
>  #define  CCP_XTS_SIZE(p) ((p)->aes_xts.size)
>  #define  CCP_XTS_ENCRYPT(p)  ((p)->aes_xts.encrypt)
> +#define  CCP_DES3_SIZE(p)((p)->des3.size)
> +#define  CCP_DES3_ENCRYPT(p) ((p)->des3.encrypt)
> +#define  CCP_DES3_MODE(p)((p)->des3.mode)
> +#define  CCP_DES3_TYPE(p)((p)->des3.type)
>  #define  CCP_SHA_TYPE(p) ((p)->sha.type)
>  #define  CCP_RSA_SIZE(p) ((p)->rsa.size)
>  #define  CCP_PT_BYTESWAP(p)  ((p)->pt.byteswap)
> @@ -242,13 +252,16 @@ static int ccp5_do_cmd(struct ccp5_desc *desc,
>   /* Wait for the job to complete */
>   ret = wait_event_interruptible(cmd_q->int_queue,
>  cmd_q->int_rcvd);
> - if (ret || cmd_q->cmd_error) {
> + if (cmd_q->cmd_error) {
> + /*
> +  * Log the error and flush the queue by
> +  * moving the head pointer
> +  */

I don't think you wanted to remove the check for ret in the if
statement above.

>   if (cmd_q->cmd_error)
>   ccp_log_error(cmd_q->ccp,
> cmd_q->cmd_error);
> - /* A version 5 device doesn't use Job IDs... */
> - if (!ret)
> - ret = -EIO;
> + iowrite32(tail, cmd_q->reg_head_lo);
> + ret = -EIO;
>

[PATCH 6/6] crypto: ccp - Enable 3DES function on v5 CCPs

2016-10-13 Thread Gary R Hook
Wire up support for Triple DES in ECB mode.

Signed-off-by: Gary R Hook 
---
 drivers/crypto/ccp/Makefile  |1 
 drivers/crypto/ccp/ccp-crypto-des3.c |  254 ++
 drivers/crypto/ccp/ccp-crypto-main.c |   10 +
 drivers/crypto/ccp/ccp-crypto.h  |   25 +++
 drivers/crypto/ccp/ccp-dev-v3.c  |1 
 drivers/crypto/ccp/ccp-dev-v5.c  |   65 -
 drivers/crypto/ccp/ccp-dev.h |   18 ++
 drivers/crypto/ccp/ccp-ops.c |  201 +++
 drivers/crypto/ccp/ccp-pci.c |2 
 include/linux/ccp.h  |   57 +++-
 10 files changed, 624 insertions(+), 10 deletions(-)
 create mode 100644 drivers/crypto/ccp/ccp-crypto-des3.c

diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
index fd77225..563594a 100644
--- a/drivers/crypto/ccp/Makefile
+++ b/drivers/crypto/ccp/Makefile
@@ -14,4 +14,5 @@ ccp-crypto-objs := ccp-crypto-main.o \
   ccp-crypto-aes-xts.o \
   ccp-crypto-rsa.o \
   ccp-crypto-aes-galois.o \
+  ccp-crypto-des3.o \
   ccp-crypto-sha.o
diff --git a/drivers/crypto/ccp/ccp-crypto-des3.c 
b/drivers/crypto/ccp/ccp-crypto-des3.c
new file mode 100644
index 000..5af7347
--- /dev/null
+++ b/drivers/crypto/ccp/ccp-crypto-des3.c
@@ -0,0 +1,254 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) DES3 crypto API support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Gary R Hook 
+ *
+ * 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"
+
+static int ccp_des3_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_des3_req_ctx *rctx = ablkcipher_request_ctx(req);
+
+   if (ret)
+   return ret;
+
+   if (ctx->u.des3.mode != CCP_DES3_MODE_ECB)
+   memcpy(req->info, rctx->iv, DES3_EDE_BLOCK_SIZE);
+
+   return 0;
+}
+
+static int ccp_des3_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));
+   u32 *flags = &tfm->base.crt_flags;
+
+
+   /* From des_generic.c:
+*
+* RFC2451:
+*   If the first two or last two independent 64-bit keys are
+*   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
+*   same as DES.  Implementers MUST reject keys that exhibit this
+*   property.
+*/
+   const u32 *K = (const u32 *)key;
+
+   if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
+!((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
+(*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+   *flags |= CRYPTO_TFM_RES_WEAK_KEY;
+   return -EINVAL;
+   }
+
+   /* It's not clear that there is any support for a keysize of 112.
+* If needed, the caller should make K1 == K3
+*/
+   ctx->u.des3.type = CCP_DES3_TYPE_168;
+   ctx->u.des3.mode = alg->mode;
+   ctx->u.des3.key_len = key_len;
+
+   memcpy(ctx->u.des3.key, key, key_len);
+   sg_init_one(&ctx->u.des3.key_sg, ctx->u.des3.key, key_len);
+
+   return 0;
+}
+
+static int ccp_des3_crypt(struct ablkcipher_request *req, bool encrypt)
+{
+   struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+   struct ccp_des3_req_ctx *rctx = ablkcipher_request_ctx(req);
+   struct scatterlist *iv_sg = NULL;
+   unsigned int iv_len = 0;
+   int ret;
+
+   if (!ctx->u.des3.key_len)
+   return -EINVAL;
+
+   if (((ctx->u.des3.mode == CCP_DES3_MODE_ECB) ||
+(ctx->u.des3.mode == CCP_DES3_MODE_CBC)) &&
+   (req->nbytes & (DES3_EDE_BLOCK_SIZE - 1)))
+   return -EINVAL;
+
+   if (ctx->u.des3.mode != CCP_DES3_MODE_ECB) {
+   if (!req->info)
+   return -EINVAL;
+
+   memcpy(rctx->iv, req->info, DES3_EDE_BLOCK_SIZE);
+   iv_sg = &rctx->iv_sg;
+   iv_len = DES3_EDE_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_DES3;
+   rctx->cmd.u.des3.type = ctx->u.des3.type;
+   rctx->cmd.u.des3.mode = ctx->u.des3.mode;
+   rctx->cmd.u.des3.action = (encrypt)
+ ? CCP_DES3_ACTION_ENCRYPT
+