1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * AMD Cryptographic Coprocessor (CCP) DES3 crypto API support
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2016,2017 Advanced Micro Devices, Inc.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Gary R Hook <ghook@amd.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/sched.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/scatterlist.h>
14*4882a593Smuzhiyun #include <linux/crypto.h>
15*4882a593Smuzhiyun #include <crypto/algapi.h>
16*4882a593Smuzhiyun #include <crypto/scatterwalk.h>
17*4882a593Smuzhiyun #include <crypto/internal/des.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include "ccp-crypto.h"
20*4882a593Smuzhiyun
ccp_des3_complete(struct crypto_async_request * async_req,int ret)21*4882a593Smuzhiyun static int ccp_des3_complete(struct crypto_async_request *async_req, int ret)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun struct skcipher_request *req = skcipher_request_cast(async_req);
24*4882a593Smuzhiyun struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
25*4882a593Smuzhiyun struct ccp_des3_req_ctx *rctx = skcipher_request_ctx(req);
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun if (ret)
28*4882a593Smuzhiyun return ret;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun if (ctx->u.des3.mode != CCP_DES3_MODE_ECB)
31*4882a593Smuzhiyun memcpy(req->iv, rctx->iv, DES3_EDE_BLOCK_SIZE);
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun return 0;
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
ccp_des3_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int key_len)36*4882a593Smuzhiyun static int ccp_des3_setkey(struct crypto_skcipher *tfm, const u8 *key,
37*4882a593Smuzhiyun unsigned int key_len)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun struct ccp_crypto_skcipher_alg *alg = ccp_crypto_skcipher_alg(tfm);
40*4882a593Smuzhiyun struct ccp_ctx *ctx = crypto_skcipher_ctx(tfm);
41*4882a593Smuzhiyun int err;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun err = verify_skcipher_des3_key(tfm, key);
44*4882a593Smuzhiyun if (err)
45*4882a593Smuzhiyun return err;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* It's not clear that there is any support for a keysize of 112.
48*4882a593Smuzhiyun * If needed, the caller should make K1 == K3
49*4882a593Smuzhiyun */
50*4882a593Smuzhiyun ctx->u.des3.type = CCP_DES3_TYPE_168;
51*4882a593Smuzhiyun ctx->u.des3.mode = alg->mode;
52*4882a593Smuzhiyun ctx->u.des3.key_len = key_len;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun memcpy(ctx->u.des3.key, key, key_len);
55*4882a593Smuzhiyun sg_init_one(&ctx->u.des3.key_sg, ctx->u.des3.key, key_len);
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun return 0;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
ccp_des3_crypt(struct skcipher_request * req,bool encrypt)60*4882a593Smuzhiyun static int ccp_des3_crypt(struct skcipher_request *req, bool encrypt)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
63*4882a593Smuzhiyun struct ccp_ctx *ctx = crypto_skcipher_ctx(tfm);
64*4882a593Smuzhiyun struct ccp_des3_req_ctx *rctx = skcipher_request_ctx(req);
65*4882a593Smuzhiyun struct scatterlist *iv_sg = NULL;
66*4882a593Smuzhiyun unsigned int iv_len = 0;
67*4882a593Smuzhiyun int ret;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun if (!ctx->u.des3.key_len)
70*4882a593Smuzhiyun return -EINVAL;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun if (((ctx->u.des3.mode == CCP_DES3_MODE_ECB) ||
73*4882a593Smuzhiyun (ctx->u.des3.mode == CCP_DES3_MODE_CBC)) &&
74*4882a593Smuzhiyun (req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1)))
75*4882a593Smuzhiyun return -EINVAL;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun if (ctx->u.des3.mode != CCP_DES3_MODE_ECB) {
78*4882a593Smuzhiyun if (!req->iv)
79*4882a593Smuzhiyun return -EINVAL;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun memcpy(rctx->iv, req->iv, DES3_EDE_BLOCK_SIZE);
82*4882a593Smuzhiyun iv_sg = &rctx->iv_sg;
83*4882a593Smuzhiyun iv_len = DES3_EDE_BLOCK_SIZE;
84*4882a593Smuzhiyun sg_init_one(iv_sg, rctx->iv, iv_len);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun memset(&rctx->cmd, 0, sizeof(rctx->cmd));
88*4882a593Smuzhiyun INIT_LIST_HEAD(&rctx->cmd.entry);
89*4882a593Smuzhiyun rctx->cmd.engine = CCP_ENGINE_DES3;
90*4882a593Smuzhiyun rctx->cmd.u.des3.type = ctx->u.des3.type;
91*4882a593Smuzhiyun rctx->cmd.u.des3.mode = ctx->u.des3.mode;
92*4882a593Smuzhiyun rctx->cmd.u.des3.action = (encrypt)
93*4882a593Smuzhiyun ? CCP_DES3_ACTION_ENCRYPT
94*4882a593Smuzhiyun : CCP_DES3_ACTION_DECRYPT;
95*4882a593Smuzhiyun rctx->cmd.u.des3.key = &ctx->u.des3.key_sg;
96*4882a593Smuzhiyun rctx->cmd.u.des3.key_len = ctx->u.des3.key_len;
97*4882a593Smuzhiyun rctx->cmd.u.des3.iv = iv_sg;
98*4882a593Smuzhiyun rctx->cmd.u.des3.iv_len = iv_len;
99*4882a593Smuzhiyun rctx->cmd.u.des3.src = req->src;
100*4882a593Smuzhiyun rctx->cmd.u.des3.src_len = req->cryptlen;
101*4882a593Smuzhiyun rctx->cmd.u.des3.dst = req->dst;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun return ret;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
ccp_des3_encrypt(struct skcipher_request * req)108*4882a593Smuzhiyun static int ccp_des3_encrypt(struct skcipher_request *req)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun return ccp_des3_crypt(req, true);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
ccp_des3_decrypt(struct skcipher_request * req)113*4882a593Smuzhiyun static int ccp_des3_decrypt(struct skcipher_request *req)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun return ccp_des3_crypt(req, false);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
ccp_des3_init_tfm(struct crypto_skcipher * tfm)118*4882a593Smuzhiyun static int ccp_des3_init_tfm(struct crypto_skcipher *tfm)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun struct ccp_ctx *ctx = crypto_skcipher_ctx(tfm);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun ctx->complete = ccp_des3_complete;
123*4882a593Smuzhiyun ctx->u.des3.key_len = 0;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun crypto_skcipher_set_reqsize(tfm, sizeof(struct ccp_des3_req_ctx));
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun return 0;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun static const struct skcipher_alg ccp_des3_defaults = {
131*4882a593Smuzhiyun .setkey = ccp_des3_setkey,
132*4882a593Smuzhiyun .encrypt = ccp_des3_encrypt,
133*4882a593Smuzhiyun .decrypt = ccp_des3_decrypt,
134*4882a593Smuzhiyun .min_keysize = DES3_EDE_KEY_SIZE,
135*4882a593Smuzhiyun .max_keysize = DES3_EDE_KEY_SIZE,
136*4882a593Smuzhiyun .init = ccp_des3_init_tfm,
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun .base.cra_flags = CRYPTO_ALG_ASYNC |
139*4882a593Smuzhiyun CRYPTO_ALG_ALLOCATES_MEMORY |
140*4882a593Smuzhiyun CRYPTO_ALG_KERN_DRIVER_ONLY |
141*4882a593Smuzhiyun CRYPTO_ALG_NEED_FALLBACK,
142*4882a593Smuzhiyun .base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
143*4882a593Smuzhiyun .base.cra_ctxsize = sizeof(struct ccp_ctx),
144*4882a593Smuzhiyun .base.cra_priority = CCP_CRA_PRIORITY,
145*4882a593Smuzhiyun .base.cra_module = THIS_MODULE,
146*4882a593Smuzhiyun };
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun struct ccp_des3_def {
149*4882a593Smuzhiyun enum ccp_des3_mode mode;
150*4882a593Smuzhiyun unsigned int version;
151*4882a593Smuzhiyun const char *name;
152*4882a593Smuzhiyun const char *driver_name;
153*4882a593Smuzhiyun unsigned int blocksize;
154*4882a593Smuzhiyun unsigned int ivsize;
155*4882a593Smuzhiyun const struct skcipher_alg *alg_defaults;
156*4882a593Smuzhiyun };
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun static const struct ccp_des3_def des3_algs[] = {
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun .mode = CCP_DES3_MODE_ECB,
161*4882a593Smuzhiyun .version = CCP_VERSION(5, 0),
162*4882a593Smuzhiyun .name = "ecb(des3_ede)",
163*4882a593Smuzhiyun .driver_name = "ecb-des3-ccp",
164*4882a593Smuzhiyun .blocksize = DES3_EDE_BLOCK_SIZE,
165*4882a593Smuzhiyun .ivsize = 0,
166*4882a593Smuzhiyun .alg_defaults = &ccp_des3_defaults,
167*4882a593Smuzhiyun },
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun .mode = CCP_DES3_MODE_CBC,
170*4882a593Smuzhiyun .version = CCP_VERSION(5, 0),
171*4882a593Smuzhiyun .name = "cbc(des3_ede)",
172*4882a593Smuzhiyun .driver_name = "cbc-des3-ccp",
173*4882a593Smuzhiyun .blocksize = DES3_EDE_BLOCK_SIZE,
174*4882a593Smuzhiyun .ivsize = DES3_EDE_BLOCK_SIZE,
175*4882a593Smuzhiyun .alg_defaults = &ccp_des3_defaults,
176*4882a593Smuzhiyun },
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun
ccp_register_des3_alg(struct list_head * head,const struct ccp_des3_def * def)179*4882a593Smuzhiyun static int ccp_register_des3_alg(struct list_head *head,
180*4882a593Smuzhiyun const struct ccp_des3_def *def)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun struct ccp_crypto_skcipher_alg *ccp_alg;
183*4882a593Smuzhiyun struct skcipher_alg *alg;
184*4882a593Smuzhiyun int ret;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
187*4882a593Smuzhiyun if (!ccp_alg)
188*4882a593Smuzhiyun return -ENOMEM;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun INIT_LIST_HEAD(&ccp_alg->entry);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun ccp_alg->mode = def->mode;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /* Copy the defaults and override as necessary */
195*4882a593Smuzhiyun alg = &ccp_alg->alg;
196*4882a593Smuzhiyun *alg = *def->alg_defaults;
197*4882a593Smuzhiyun snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
198*4882a593Smuzhiyun snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
199*4882a593Smuzhiyun def->driver_name);
200*4882a593Smuzhiyun alg->base.cra_blocksize = def->blocksize;
201*4882a593Smuzhiyun alg->ivsize = def->ivsize;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun ret = crypto_register_skcipher(alg);
204*4882a593Smuzhiyun if (ret) {
205*4882a593Smuzhiyun pr_err("%s skcipher algorithm registration error (%d)\n",
206*4882a593Smuzhiyun alg->base.cra_name, ret);
207*4882a593Smuzhiyun kfree(ccp_alg);
208*4882a593Smuzhiyun return ret;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun list_add(&ccp_alg->entry, head);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun return 0;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
ccp_register_des3_algs(struct list_head * head)216*4882a593Smuzhiyun int ccp_register_des3_algs(struct list_head *head)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun int i, ret;
219*4882a593Smuzhiyun unsigned int ccpversion = ccp_version();
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(des3_algs); i++) {
222*4882a593Smuzhiyun if (des3_algs[i].version > ccpversion)
223*4882a593Smuzhiyun continue;
224*4882a593Smuzhiyun ret = ccp_register_des3_alg(head, &des3_algs[i]);
225*4882a593Smuzhiyun if (ret)
226*4882a593Smuzhiyun return ret;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun return 0;
230*4882a593Smuzhiyun }
231