Re: [PATCH 6/6] crypto: ccp - Enable 3DES function on v5 CCPs
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
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 +