1*445a4aafSJia Jie Ho // SPDX-License-Identifier: GPL-2.0
2*445a4aafSJia Jie Ho /*
3*445a4aafSJia Jie Ho  * StarFive Public Key Algo acceleration driver
4*445a4aafSJia Jie Ho  *
5*445a4aafSJia Jie Ho  * Copyright (c) 2022 StarFive Technology
6*445a4aafSJia Jie Ho  */
7*445a4aafSJia Jie Ho 
8*445a4aafSJia Jie Ho #include <linux/crypto.h>
9*445a4aafSJia Jie Ho #include <linux/delay.h>
10*445a4aafSJia Jie Ho #include <linux/device.h>
11*445a4aafSJia Jie Ho #include <linux/dma-direct.h>
12*445a4aafSJia Jie Ho #include <linux/interrupt.h>
13*445a4aafSJia Jie Ho #include <linux/iopoll.h>
14*445a4aafSJia Jie Ho #include <linux/io.h>
15*445a4aafSJia Jie Ho #include <linux/mod_devicetable.h>
16*445a4aafSJia Jie Ho #include <crypto/akcipher.h>
17*445a4aafSJia Jie Ho #include <crypto/algapi.h>
18*445a4aafSJia Jie Ho #include <crypto/internal/akcipher.h>
19*445a4aafSJia Jie Ho #include <crypto/internal/rsa.h>
20*445a4aafSJia Jie Ho #include <crypto/scatterwalk.h>
21*445a4aafSJia Jie Ho 
22*445a4aafSJia Jie Ho #include "jh7110-cryp.h"
23*445a4aafSJia Jie Ho 
24*445a4aafSJia Jie Ho #define STARFIVE_PKA_REGS_OFFSET	0x400
25*445a4aafSJia Jie Ho #define STARFIVE_PKA_CACR_OFFSET	(STARFIVE_PKA_REGS_OFFSET + 0x0)
26*445a4aafSJia Jie Ho #define STARFIVE_PKA_CASR_OFFSET	(STARFIVE_PKA_REGS_OFFSET + 0x4)
27*445a4aafSJia Jie Ho #define STARFIVE_PKA_CAAR_OFFSET	(STARFIVE_PKA_REGS_OFFSET + 0x8)
28*445a4aafSJia Jie Ho #define STARFIVE_PKA_CAER_OFFSET	(STARFIVE_PKA_REGS_OFFSET + 0x108)
29*445a4aafSJia Jie Ho #define STARFIVE_PKA_CANR_OFFSET	(STARFIVE_PKA_REGS_OFFSET + 0x208)
30*445a4aafSJia Jie Ho 
31*445a4aafSJia Jie Ho // R^2 mod N and N0'
32*445a4aafSJia Jie Ho #define CRYPTO_CMD_PRE			0x0
33*445a4aafSJia Jie Ho // A * R mod N   ==> A
34*445a4aafSJia Jie Ho #define CRYPTO_CMD_ARN			0x5
35*445a4aafSJia Jie Ho // A * E * R mod N ==> A
36*445a4aafSJia Jie Ho #define CRYPTO_CMD_AERN			0x6
37*445a4aafSJia Jie Ho // A * A * R mod N ==> A
38*445a4aafSJia Jie Ho #define CRYPTO_CMD_AARN			0x7
39*445a4aafSJia Jie Ho 
40*445a4aafSJia Jie Ho #define STARFIVE_RSA_MAX_KEYSZ		256
41*445a4aafSJia Jie Ho #define STARFIVE_RSA_RESET		0x2
42*445a4aafSJia Jie Ho 
starfive_pka_wait_done(struct starfive_cryp_ctx * ctx)43*445a4aafSJia Jie Ho static inline int starfive_pka_wait_done(struct starfive_cryp_ctx *ctx)
44*445a4aafSJia Jie Ho {
45*445a4aafSJia Jie Ho 	struct starfive_cryp_dev *cryp = ctx->cryp;
46*445a4aafSJia Jie Ho 
47*445a4aafSJia Jie Ho 	return wait_for_completion_timeout(&cryp->pka_done,
48*445a4aafSJia Jie Ho 					   usecs_to_jiffies(100000));
49*445a4aafSJia Jie Ho }
50*445a4aafSJia Jie Ho 
starfive_pka_irq_mask_clear(struct starfive_cryp_ctx * ctx)51*445a4aafSJia Jie Ho static inline void starfive_pka_irq_mask_clear(struct starfive_cryp_ctx *ctx)
52*445a4aafSJia Jie Ho {
53*445a4aafSJia Jie Ho 	struct starfive_cryp_dev *cryp = ctx->cryp;
54*445a4aafSJia Jie Ho 	u32 stat;
55*445a4aafSJia Jie Ho 
56*445a4aafSJia Jie Ho 	stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
57*445a4aafSJia Jie Ho 	stat &= ~STARFIVE_IE_MASK_PKA_DONE;
58*445a4aafSJia Jie Ho 	writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET);
59*445a4aafSJia Jie Ho 
60*445a4aafSJia Jie Ho 	reinit_completion(&cryp->pka_done);
61*445a4aafSJia Jie Ho }
62*445a4aafSJia Jie Ho 
starfive_rsa_free_key(struct starfive_rsa_key * key)63*445a4aafSJia Jie Ho static void starfive_rsa_free_key(struct starfive_rsa_key *key)
64*445a4aafSJia Jie Ho {
65*445a4aafSJia Jie Ho 	if (key->d)
66*445a4aafSJia Jie Ho 		kfree_sensitive(key->d);
67*445a4aafSJia Jie Ho 	if (key->e)
68*445a4aafSJia Jie Ho 		kfree_sensitive(key->e);
69*445a4aafSJia Jie Ho 	if (key->n)
70*445a4aafSJia Jie Ho 		kfree_sensitive(key->n);
71*445a4aafSJia Jie Ho 	memset(key, 0, sizeof(*key));
72*445a4aafSJia Jie Ho }
73*445a4aafSJia Jie Ho 
starfive_rsa_get_nbit(u8 * pa,u32 snum,int key_sz)74*445a4aafSJia Jie Ho static unsigned int starfive_rsa_get_nbit(u8 *pa, u32 snum, int key_sz)
75*445a4aafSJia Jie Ho {
76*445a4aafSJia Jie Ho 	u32 i;
77*445a4aafSJia Jie Ho 	u8 value;
78*445a4aafSJia Jie Ho 
79*445a4aafSJia Jie Ho 	i = snum >> 3;
80*445a4aafSJia Jie Ho 
81*445a4aafSJia Jie Ho 	value = pa[key_sz - i - 1];
82*445a4aafSJia Jie Ho 	value >>= snum & 0x7;
83*445a4aafSJia Jie Ho 	value &= 0x1;
84*445a4aafSJia Jie Ho 
85*445a4aafSJia Jie Ho 	return value;
86*445a4aafSJia Jie Ho }
87*445a4aafSJia Jie Ho 
starfive_rsa_montgomery_form(struct starfive_cryp_ctx * ctx,u32 * out,u32 * in,u8 mont,u32 * mod,int bit_len)88*445a4aafSJia Jie Ho static int starfive_rsa_montgomery_form(struct starfive_cryp_ctx *ctx,
89*445a4aafSJia Jie Ho 					u32 *out, u32 *in, u8 mont,
90*445a4aafSJia Jie Ho 					u32 *mod, int bit_len)
91*445a4aafSJia Jie Ho {
92*445a4aafSJia Jie Ho 	struct starfive_cryp_dev *cryp = ctx->cryp;
93*445a4aafSJia Jie Ho 	struct starfive_cryp_request_ctx *rctx = ctx->rctx;
94*445a4aafSJia Jie Ho 	int count = rctx->total / sizeof(u32) - 1;
95*445a4aafSJia Jie Ho 	int loop;
96*445a4aafSJia Jie Ho 	u32 temp;
97*445a4aafSJia Jie Ho 	u8 opsize;
98*445a4aafSJia Jie Ho 
99*445a4aafSJia Jie Ho 	opsize = (bit_len - 1) >> 5;
100*445a4aafSJia Jie Ho 	rctx->csr.pka.v = 0;
101*445a4aafSJia Jie Ho 
102*445a4aafSJia Jie Ho 	writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
103*445a4aafSJia Jie Ho 
104*445a4aafSJia Jie Ho 	for (loop = 0; loop <= opsize; loop++)
105*445a4aafSJia Jie Ho 		writel(mod[opsize - loop], cryp->base + STARFIVE_PKA_CANR_OFFSET + loop * 4);
106*445a4aafSJia Jie Ho 
107*445a4aafSJia Jie Ho 	if (mont) {
108*445a4aafSJia Jie Ho 		rctx->csr.pka.v = 0;
109*445a4aafSJia Jie Ho 		rctx->csr.pka.cln_done = 1;
110*445a4aafSJia Jie Ho 		rctx->csr.pka.opsize = opsize;
111*445a4aafSJia Jie Ho 		rctx->csr.pka.exposize = opsize;
112*445a4aafSJia Jie Ho 		rctx->csr.pka.cmd = CRYPTO_CMD_PRE;
113*445a4aafSJia Jie Ho 		rctx->csr.pka.start = 1;
114*445a4aafSJia Jie Ho 		rctx->csr.pka.not_r2 = 1;
115*445a4aafSJia Jie Ho 		rctx->csr.pka.ie = 1;
116*445a4aafSJia Jie Ho 
117*445a4aafSJia Jie Ho 		starfive_pka_irq_mask_clear(ctx);
118*445a4aafSJia Jie Ho 		writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
119*445a4aafSJia Jie Ho 
120*445a4aafSJia Jie Ho 		if (!starfive_pka_wait_done(ctx))
121*445a4aafSJia Jie Ho 			return -ETIMEDOUT;
122*445a4aafSJia Jie Ho 
123*445a4aafSJia Jie Ho 		for (loop = 0; loop <= opsize; loop++)
124*445a4aafSJia Jie Ho 			writel(in[opsize - loop], cryp->base + STARFIVE_PKA_CAAR_OFFSET + loop * 4);
125*445a4aafSJia Jie Ho 
126*445a4aafSJia Jie Ho 		writel(0x1000000, cryp->base + STARFIVE_PKA_CAER_OFFSET);
127*445a4aafSJia Jie Ho 
128*445a4aafSJia Jie Ho 		for (loop = 1; loop <= opsize; loop++)
129*445a4aafSJia Jie Ho 			writel(0, cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4);
130*445a4aafSJia Jie Ho 
131*445a4aafSJia Jie Ho 		rctx->csr.pka.v = 0;
132*445a4aafSJia Jie Ho 		rctx->csr.pka.cln_done = 1;
133*445a4aafSJia Jie Ho 		rctx->csr.pka.opsize = opsize;
134*445a4aafSJia Jie Ho 		rctx->csr.pka.exposize = opsize;
135*445a4aafSJia Jie Ho 		rctx->csr.pka.cmd = CRYPTO_CMD_AERN;
136*445a4aafSJia Jie Ho 		rctx->csr.pka.start = 1;
137*445a4aafSJia Jie Ho 		rctx->csr.pka.ie = 1;
138*445a4aafSJia Jie Ho 
139*445a4aafSJia Jie Ho 		starfive_pka_irq_mask_clear(ctx);
140*445a4aafSJia Jie Ho 		writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
141*445a4aafSJia Jie Ho 
142*445a4aafSJia Jie Ho 		if (!starfive_pka_wait_done(ctx))
143*445a4aafSJia Jie Ho 			return -ETIMEDOUT;
144*445a4aafSJia Jie Ho 	} else {
145*445a4aafSJia Jie Ho 		rctx->csr.pka.v = 0;
146*445a4aafSJia Jie Ho 		rctx->csr.pka.cln_done = 1;
147*445a4aafSJia Jie Ho 		rctx->csr.pka.opsize = opsize;
148*445a4aafSJia Jie Ho 		rctx->csr.pka.exposize = opsize;
149*445a4aafSJia Jie Ho 		rctx->csr.pka.cmd = CRYPTO_CMD_PRE;
150*445a4aafSJia Jie Ho 		rctx->csr.pka.start = 1;
151*445a4aafSJia Jie Ho 		rctx->csr.pka.pre_expf = 1;
152*445a4aafSJia Jie Ho 		rctx->csr.pka.ie = 1;
153*445a4aafSJia Jie Ho 
154*445a4aafSJia Jie Ho 		starfive_pka_irq_mask_clear(ctx);
155*445a4aafSJia Jie Ho 		writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
156*445a4aafSJia Jie Ho 
157*445a4aafSJia Jie Ho 		if (!starfive_pka_wait_done(ctx))
158*445a4aafSJia Jie Ho 			return -ETIMEDOUT;
159*445a4aafSJia Jie Ho 
160*445a4aafSJia Jie Ho 		for (loop = 0; loop <= count; loop++)
161*445a4aafSJia Jie Ho 			writel(in[count - loop], cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4);
162*445a4aafSJia Jie Ho 
163*445a4aafSJia Jie Ho 		/*pad with 0 up to opsize*/
164*445a4aafSJia Jie Ho 		for (loop = count + 1; loop <= opsize; loop++)
165*445a4aafSJia Jie Ho 			writel(0, cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4);
166*445a4aafSJia Jie Ho 
167*445a4aafSJia Jie Ho 		rctx->csr.pka.v = 0;
168*445a4aafSJia Jie Ho 		rctx->csr.pka.cln_done = 1;
169*445a4aafSJia Jie Ho 		rctx->csr.pka.opsize = opsize;
170*445a4aafSJia Jie Ho 		rctx->csr.pka.exposize = opsize;
171*445a4aafSJia Jie Ho 		rctx->csr.pka.cmd = CRYPTO_CMD_ARN;
172*445a4aafSJia Jie Ho 		rctx->csr.pka.start = 1;
173*445a4aafSJia Jie Ho 		rctx->csr.pka.ie = 1;
174*445a4aafSJia Jie Ho 
175*445a4aafSJia Jie Ho 		starfive_pka_irq_mask_clear(ctx);
176*445a4aafSJia Jie Ho 		writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
177*445a4aafSJia Jie Ho 
178*445a4aafSJia Jie Ho 		if (!starfive_pka_wait_done(ctx))
179*445a4aafSJia Jie Ho 			return -ETIMEDOUT;
180*445a4aafSJia Jie Ho 	}
181*445a4aafSJia Jie Ho 
182*445a4aafSJia Jie Ho 	for (loop = 0; loop <= opsize; loop++) {
183*445a4aafSJia Jie Ho 		temp = readl(cryp->base + STARFIVE_PKA_CAAR_OFFSET + 0x4 * loop);
184*445a4aafSJia Jie Ho 		out[opsize - loop] = temp;
185*445a4aafSJia Jie Ho 	}
186*445a4aafSJia Jie Ho 
187*445a4aafSJia Jie Ho 	return 0;
188*445a4aafSJia Jie Ho }
189*445a4aafSJia Jie Ho 
starfive_rsa_cpu_start(struct starfive_cryp_ctx * ctx,u32 * result,u8 * de,u32 * n,int key_sz)190*445a4aafSJia Jie Ho static int starfive_rsa_cpu_start(struct starfive_cryp_ctx *ctx, u32 *result,
191*445a4aafSJia Jie Ho 				  u8 *de, u32 *n, int key_sz)
192*445a4aafSJia Jie Ho {
193*445a4aafSJia Jie Ho 	struct starfive_cryp_dev *cryp = ctx->cryp;
194*445a4aafSJia Jie Ho 	struct starfive_cryp_request_ctx *rctx = ctx->rctx;
195*445a4aafSJia Jie Ho 	struct starfive_rsa_key *key = &ctx->rsa_key;
196*445a4aafSJia Jie Ho 	u32 temp;
197*445a4aafSJia Jie Ho 	int ret = 0;
198*445a4aafSJia Jie Ho 	int opsize, mlen, loop;
199*445a4aafSJia Jie Ho 	unsigned int *mta;
200*445a4aafSJia Jie Ho 
201*445a4aafSJia Jie Ho 	opsize = (key_sz - 1) >> 2;
202*445a4aafSJia Jie Ho 
203*445a4aafSJia Jie Ho 	mta = kmalloc(key_sz, GFP_KERNEL);
204*445a4aafSJia Jie Ho 	if (!mta)
205*445a4aafSJia Jie Ho 		return -ENOMEM;
206*445a4aafSJia Jie Ho 
207*445a4aafSJia Jie Ho 	ret = starfive_rsa_montgomery_form(ctx, mta, (u32 *)rctx->rsa_data,
208*445a4aafSJia Jie Ho 					   0, n, key_sz << 3);
209*445a4aafSJia Jie Ho 	if (ret) {
210*445a4aafSJia Jie Ho 		dev_err_probe(cryp->dev, ret, "Conversion to Montgomery failed");
211*445a4aafSJia Jie Ho 		goto rsa_err;
212*445a4aafSJia Jie Ho 	}
213*445a4aafSJia Jie Ho 
214*445a4aafSJia Jie Ho 	for (loop = 0; loop <= opsize; loop++)
215*445a4aafSJia Jie Ho 		writel(mta[opsize - loop],
216*445a4aafSJia Jie Ho 		       cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4);
217*445a4aafSJia Jie Ho 
218*445a4aafSJia Jie Ho 	for (loop = key->bitlen - 1; loop > 0; loop--) {
219*445a4aafSJia Jie Ho 		mlen = starfive_rsa_get_nbit(de, loop - 1, key_sz);
220*445a4aafSJia Jie Ho 
221*445a4aafSJia Jie Ho 		rctx->csr.pka.v = 0;
222*445a4aafSJia Jie Ho 		rctx->csr.pka.cln_done = 1;
223*445a4aafSJia Jie Ho 		rctx->csr.pka.opsize = opsize;
224*445a4aafSJia Jie Ho 		rctx->csr.pka.exposize = opsize;
225*445a4aafSJia Jie Ho 		rctx->csr.pka.cmd = CRYPTO_CMD_AARN;
226*445a4aafSJia Jie Ho 		rctx->csr.pka.start = 1;
227*445a4aafSJia Jie Ho 		rctx->csr.pka.ie = 1;
228*445a4aafSJia Jie Ho 
229*445a4aafSJia Jie Ho 		starfive_pka_irq_mask_clear(ctx);
230*445a4aafSJia Jie Ho 		writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
231*445a4aafSJia Jie Ho 
232*445a4aafSJia Jie Ho 		ret = -ETIMEDOUT;
233*445a4aafSJia Jie Ho 		if (!starfive_pka_wait_done(ctx))
234*445a4aafSJia Jie Ho 			goto rsa_err;
235*445a4aafSJia Jie Ho 
236*445a4aafSJia Jie Ho 		if (mlen) {
237*445a4aafSJia Jie Ho 			rctx->csr.pka.v = 0;
238*445a4aafSJia Jie Ho 			rctx->csr.pka.cln_done = 1;
239*445a4aafSJia Jie Ho 			rctx->csr.pka.opsize = opsize;
240*445a4aafSJia Jie Ho 			rctx->csr.pka.exposize = opsize;
241*445a4aafSJia Jie Ho 			rctx->csr.pka.cmd = CRYPTO_CMD_AERN;
242*445a4aafSJia Jie Ho 			rctx->csr.pka.start = 1;
243*445a4aafSJia Jie Ho 			rctx->csr.pka.ie = 1;
244*445a4aafSJia Jie Ho 
245*445a4aafSJia Jie Ho 			starfive_pka_irq_mask_clear(ctx);
246*445a4aafSJia Jie Ho 			writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
247*445a4aafSJia Jie Ho 
248*445a4aafSJia Jie Ho 			if (!starfive_pka_wait_done(ctx))
249*445a4aafSJia Jie Ho 				goto rsa_err;
250*445a4aafSJia Jie Ho 		}
251*445a4aafSJia Jie Ho 	}
252*445a4aafSJia Jie Ho 
253*445a4aafSJia Jie Ho 	for (loop = 0; loop <= opsize; loop++) {
254*445a4aafSJia Jie Ho 		temp = readl(cryp->base + STARFIVE_PKA_CAAR_OFFSET + 0x4 * loop);
255*445a4aafSJia Jie Ho 		result[opsize - loop] = temp;
256*445a4aafSJia Jie Ho 	}
257*445a4aafSJia Jie Ho 
258*445a4aafSJia Jie Ho 	ret = starfive_rsa_montgomery_form(ctx, result, result, 1, n, key_sz << 3);
259*445a4aafSJia Jie Ho 	if (ret)
260*445a4aafSJia Jie Ho 		dev_err_probe(cryp->dev, ret, "Conversion from Montgomery failed");
261*445a4aafSJia Jie Ho rsa_err:
262*445a4aafSJia Jie Ho 	kfree(mta);
263*445a4aafSJia Jie Ho 	return ret;
264*445a4aafSJia Jie Ho }
265*445a4aafSJia Jie Ho 
starfive_rsa_start(struct starfive_cryp_ctx * ctx,u8 * result,u8 * de,u8 * n,int key_sz)266*445a4aafSJia Jie Ho static int starfive_rsa_start(struct starfive_cryp_ctx *ctx, u8 *result,
267*445a4aafSJia Jie Ho 			      u8 *de, u8 *n, int key_sz)
268*445a4aafSJia Jie Ho {
269*445a4aafSJia Jie Ho 	return starfive_rsa_cpu_start(ctx, (u32 *)result, de, (u32 *)n, key_sz);
270*445a4aafSJia Jie Ho }
271*445a4aafSJia Jie Ho 
starfive_rsa_enc_core(struct starfive_cryp_ctx * ctx,int enc)272*445a4aafSJia Jie Ho static int starfive_rsa_enc_core(struct starfive_cryp_ctx *ctx, int enc)
273*445a4aafSJia Jie Ho {
274*445a4aafSJia Jie Ho 	struct starfive_cryp_dev *cryp = ctx->cryp;
275*445a4aafSJia Jie Ho 	struct starfive_cryp_request_ctx *rctx = ctx->rctx;
276*445a4aafSJia Jie Ho 	struct starfive_rsa_key *key = &ctx->rsa_key;
277*445a4aafSJia Jie Ho 	int ret = 0;
278*445a4aafSJia Jie Ho 
279*445a4aafSJia Jie Ho 	writel(STARFIVE_RSA_RESET, cryp->base + STARFIVE_PKA_CACR_OFFSET);
280*445a4aafSJia Jie Ho 
281*445a4aafSJia Jie Ho 	rctx->total = sg_copy_to_buffer(rctx->in_sg, rctx->nents,
282*445a4aafSJia Jie Ho 					rctx->rsa_data, rctx->total);
283*445a4aafSJia Jie Ho 
284*445a4aafSJia Jie Ho 	if (enc) {
285*445a4aafSJia Jie Ho 		key->bitlen = key->e_bitlen;
286*445a4aafSJia Jie Ho 		ret = starfive_rsa_start(ctx, rctx->rsa_data, key->e,
287*445a4aafSJia Jie Ho 					 key->n, key->key_sz);
288*445a4aafSJia Jie Ho 	} else {
289*445a4aafSJia Jie Ho 		key->bitlen = key->d_bitlen;
290*445a4aafSJia Jie Ho 		ret = starfive_rsa_start(ctx, rctx->rsa_data, key->d,
291*445a4aafSJia Jie Ho 					 key->n, key->key_sz);
292*445a4aafSJia Jie Ho 	}
293*445a4aafSJia Jie Ho 
294*445a4aafSJia Jie Ho 	if (ret)
295*445a4aafSJia Jie Ho 		goto err_rsa_crypt;
296*445a4aafSJia Jie Ho 
297*445a4aafSJia Jie Ho 	sg_copy_buffer(rctx->out_sg, sg_nents(rctx->out_sg),
298*445a4aafSJia Jie Ho 		       rctx->rsa_data, key->key_sz, 0, 0);
299*445a4aafSJia Jie Ho 
300*445a4aafSJia Jie Ho err_rsa_crypt:
301*445a4aafSJia Jie Ho 	writel(STARFIVE_RSA_RESET, cryp->base + STARFIVE_PKA_CACR_OFFSET);
302*445a4aafSJia Jie Ho 	kfree(rctx->rsa_data);
303*445a4aafSJia Jie Ho 	return ret;
304*445a4aafSJia Jie Ho }
305*445a4aafSJia Jie Ho 
starfive_rsa_enc(struct akcipher_request * req)306*445a4aafSJia Jie Ho static int starfive_rsa_enc(struct akcipher_request *req)
307*445a4aafSJia Jie Ho {
308*445a4aafSJia Jie Ho 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
309*445a4aafSJia Jie Ho 	struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
310*445a4aafSJia Jie Ho 	struct starfive_cryp_dev *cryp = ctx->cryp;
311*445a4aafSJia Jie Ho 	struct starfive_rsa_key *key = &ctx->rsa_key;
312*445a4aafSJia Jie Ho 	struct starfive_cryp_request_ctx *rctx = akcipher_request_ctx(req);
313*445a4aafSJia Jie Ho 	int ret;
314*445a4aafSJia Jie Ho 
315*445a4aafSJia Jie Ho 	if (!key->key_sz) {
316*445a4aafSJia Jie Ho 		akcipher_request_set_tfm(req, ctx->akcipher_fbk);
317*445a4aafSJia Jie Ho 		ret = crypto_akcipher_encrypt(req);
318*445a4aafSJia Jie Ho 		akcipher_request_set_tfm(req, tfm);
319*445a4aafSJia Jie Ho 		return ret;
320*445a4aafSJia Jie Ho 	}
321*445a4aafSJia Jie Ho 
322*445a4aafSJia Jie Ho 	if (unlikely(!key->n || !key->e))
323*445a4aafSJia Jie Ho 		return -EINVAL;
324*445a4aafSJia Jie Ho 
325*445a4aafSJia Jie Ho 	if (req->dst_len < key->key_sz)
326*445a4aafSJia Jie Ho 		return dev_err_probe(cryp->dev, -EOVERFLOW,
327*445a4aafSJia Jie Ho 				     "Output buffer length less than parameter n\n");
328*445a4aafSJia Jie Ho 
329*445a4aafSJia Jie Ho 	rctx->in_sg = req->src;
330*445a4aafSJia Jie Ho 	rctx->out_sg = req->dst;
331*445a4aafSJia Jie Ho 	rctx->total = req->src_len;
332*445a4aafSJia Jie Ho 	rctx->nents = sg_nents(rctx->in_sg);
333*445a4aafSJia Jie Ho 	ctx->rctx = rctx;
334*445a4aafSJia Jie Ho 
335*445a4aafSJia Jie Ho 	return starfive_rsa_enc_core(ctx, 1);
336*445a4aafSJia Jie Ho }
337*445a4aafSJia Jie Ho 
starfive_rsa_dec(struct akcipher_request * req)338*445a4aafSJia Jie Ho static int starfive_rsa_dec(struct akcipher_request *req)
339*445a4aafSJia Jie Ho {
340*445a4aafSJia Jie Ho 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
341*445a4aafSJia Jie Ho 	struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
342*445a4aafSJia Jie Ho 	struct starfive_cryp_dev *cryp = ctx->cryp;
343*445a4aafSJia Jie Ho 	struct starfive_rsa_key *key = &ctx->rsa_key;
344*445a4aafSJia Jie Ho 	struct starfive_cryp_request_ctx *rctx = akcipher_request_ctx(req);
345*445a4aafSJia Jie Ho 	int ret;
346*445a4aafSJia Jie Ho 
347*445a4aafSJia Jie Ho 	if (!key->key_sz) {
348*445a4aafSJia Jie Ho 		akcipher_request_set_tfm(req, ctx->akcipher_fbk);
349*445a4aafSJia Jie Ho 		ret = crypto_akcipher_decrypt(req);
350*445a4aafSJia Jie Ho 		akcipher_request_set_tfm(req, tfm);
351*445a4aafSJia Jie Ho 		return ret;
352*445a4aafSJia Jie Ho 	}
353*445a4aafSJia Jie Ho 
354*445a4aafSJia Jie Ho 	if (unlikely(!key->n || !key->d))
355*445a4aafSJia Jie Ho 		return -EINVAL;
356*445a4aafSJia Jie Ho 
357*445a4aafSJia Jie Ho 	if (req->dst_len < key->key_sz)
358*445a4aafSJia Jie Ho 		return dev_err_probe(cryp->dev, -EOVERFLOW,
359*445a4aafSJia Jie Ho 				     "Output buffer length less than parameter n\n");
360*445a4aafSJia Jie Ho 
361*445a4aafSJia Jie Ho 	rctx->in_sg = req->src;
362*445a4aafSJia Jie Ho 	rctx->out_sg = req->dst;
363*445a4aafSJia Jie Ho 	ctx->rctx = rctx;
364*445a4aafSJia Jie Ho 	rctx->total = req->src_len;
365*445a4aafSJia Jie Ho 
366*445a4aafSJia Jie Ho 	return starfive_rsa_enc_core(ctx, 0);
367*445a4aafSJia Jie Ho }
368*445a4aafSJia Jie Ho 
starfive_rsa_set_n(struct starfive_rsa_key * rsa_key,const char * value,size_t vlen)369*445a4aafSJia Jie Ho static int starfive_rsa_set_n(struct starfive_rsa_key *rsa_key,
370*445a4aafSJia Jie Ho 			      const char *value, size_t vlen)
371*445a4aafSJia Jie Ho {
372*445a4aafSJia Jie Ho 	const char *ptr = value;
373*445a4aafSJia Jie Ho 	unsigned int bitslen;
374*445a4aafSJia Jie Ho 	int ret;
375*445a4aafSJia Jie Ho 
376*445a4aafSJia Jie Ho 	while (!*ptr && vlen) {
377*445a4aafSJia Jie Ho 		ptr++;
378*445a4aafSJia Jie Ho 		vlen--;
379*445a4aafSJia Jie Ho 	}
380*445a4aafSJia Jie Ho 	rsa_key->key_sz = vlen;
381*445a4aafSJia Jie Ho 	bitslen = rsa_key->key_sz << 3;
382*445a4aafSJia Jie Ho 
383*445a4aafSJia Jie Ho 	/* check valid key size */
384*445a4aafSJia Jie Ho 	if (bitslen & 0x1f)
385*445a4aafSJia Jie Ho 		return -EINVAL;
386*445a4aafSJia Jie Ho 
387*445a4aafSJia Jie Ho 	ret = -ENOMEM;
388*445a4aafSJia Jie Ho 	rsa_key->n = kmemdup(ptr, rsa_key->key_sz, GFP_KERNEL);
389*445a4aafSJia Jie Ho 	if (!rsa_key->n)
390*445a4aafSJia Jie Ho 		goto err;
391*445a4aafSJia Jie Ho 
392*445a4aafSJia Jie Ho 	return 0;
393*445a4aafSJia Jie Ho  err:
394*445a4aafSJia Jie Ho 	rsa_key->key_sz = 0;
395*445a4aafSJia Jie Ho 	rsa_key->n = NULL;
396*445a4aafSJia Jie Ho 	starfive_rsa_free_key(rsa_key);
397*445a4aafSJia Jie Ho 	return ret;
398*445a4aafSJia Jie Ho }
399*445a4aafSJia Jie Ho 
starfive_rsa_set_e(struct starfive_rsa_key * rsa_key,const char * value,size_t vlen)400*445a4aafSJia Jie Ho static int starfive_rsa_set_e(struct starfive_rsa_key *rsa_key,
401*445a4aafSJia Jie Ho 			      const char *value, size_t vlen)
402*445a4aafSJia Jie Ho {
403*445a4aafSJia Jie Ho 	const char *ptr = value;
404*445a4aafSJia Jie Ho 	unsigned char pt;
405*445a4aafSJia Jie Ho 	int loop;
406*445a4aafSJia Jie Ho 
407*445a4aafSJia Jie Ho 	while (!*ptr && vlen) {
408*445a4aafSJia Jie Ho 		ptr++;
409*445a4aafSJia Jie Ho 		vlen--;
410*445a4aafSJia Jie Ho 	}
411*445a4aafSJia Jie Ho 	pt = *ptr;
412*445a4aafSJia Jie Ho 
413*445a4aafSJia Jie Ho 	if (!rsa_key->key_sz || !vlen || vlen > rsa_key->key_sz) {
414*445a4aafSJia Jie Ho 		rsa_key->e = NULL;
415*445a4aafSJia Jie Ho 		return -EINVAL;
416*445a4aafSJia Jie Ho 	}
417*445a4aafSJia Jie Ho 
418*445a4aafSJia Jie Ho 	rsa_key->e = kzalloc(rsa_key->key_sz, GFP_KERNEL);
419*445a4aafSJia Jie Ho 	if (!rsa_key->e)
420*445a4aafSJia Jie Ho 		return -ENOMEM;
421*445a4aafSJia Jie Ho 
422*445a4aafSJia Jie Ho 	for (loop = 8; loop > 0; loop--) {
423*445a4aafSJia Jie Ho 		if (pt >> (loop - 1))
424*445a4aafSJia Jie Ho 			break;
425*445a4aafSJia Jie Ho 	}
426*445a4aafSJia Jie Ho 
427*445a4aafSJia Jie Ho 	rsa_key->e_bitlen = (vlen - 1) * 8 + loop;
428*445a4aafSJia Jie Ho 
429*445a4aafSJia Jie Ho 	memcpy(rsa_key->e + (rsa_key->key_sz - vlen), ptr, vlen);
430*445a4aafSJia Jie Ho 
431*445a4aafSJia Jie Ho 	return 0;
432*445a4aafSJia Jie Ho }
433*445a4aafSJia Jie Ho 
starfive_rsa_set_d(struct starfive_rsa_key * rsa_key,const char * value,size_t vlen)434*445a4aafSJia Jie Ho static int starfive_rsa_set_d(struct starfive_rsa_key *rsa_key,
435*445a4aafSJia Jie Ho 			      const char *value, size_t vlen)
436*445a4aafSJia Jie Ho {
437*445a4aafSJia Jie Ho 	const char *ptr = value;
438*445a4aafSJia Jie Ho 	unsigned char pt;
439*445a4aafSJia Jie Ho 	int loop;
440*445a4aafSJia Jie Ho 	int ret;
441*445a4aafSJia Jie Ho 
442*445a4aafSJia Jie Ho 	while (!*ptr && vlen) {
443*445a4aafSJia Jie Ho 		ptr++;
444*445a4aafSJia Jie Ho 		vlen--;
445*445a4aafSJia Jie Ho 	}
446*445a4aafSJia Jie Ho 	pt = *ptr;
447*445a4aafSJia Jie Ho 
448*445a4aafSJia Jie Ho 	ret = -EINVAL;
449*445a4aafSJia Jie Ho 	if (!rsa_key->key_sz || !vlen || vlen > rsa_key->key_sz)
450*445a4aafSJia Jie Ho 		goto err;
451*445a4aafSJia Jie Ho 
452*445a4aafSJia Jie Ho 	ret = -ENOMEM;
453*445a4aafSJia Jie Ho 	rsa_key->d = kzalloc(rsa_key->key_sz, GFP_KERNEL);
454*445a4aafSJia Jie Ho 	if (!rsa_key->d)
455*445a4aafSJia Jie Ho 		goto err;
456*445a4aafSJia Jie Ho 
457*445a4aafSJia Jie Ho 	for (loop = 8; loop > 0; loop--) {
458*445a4aafSJia Jie Ho 		if (pt >> (loop - 1))
459*445a4aafSJia Jie Ho 			break;
460*445a4aafSJia Jie Ho 	}
461*445a4aafSJia Jie Ho 
462*445a4aafSJia Jie Ho 	rsa_key->d_bitlen = (vlen - 1) * 8 + loop;
463*445a4aafSJia Jie Ho 
464*445a4aafSJia Jie Ho 	memcpy(rsa_key->d + (rsa_key->key_sz - vlen), ptr, vlen);
465*445a4aafSJia Jie Ho 
466*445a4aafSJia Jie Ho 	return 0;
467*445a4aafSJia Jie Ho  err:
468*445a4aafSJia Jie Ho 	rsa_key->d = NULL;
469*445a4aafSJia Jie Ho 	return ret;
470*445a4aafSJia Jie Ho }
471*445a4aafSJia Jie Ho 
starfive_rsa_setkey(struct crypto_akcipher * tfm,const void * key,unsigned int keylen,bool private)472*445a4aafSJia Jie Ho static int starfive_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
473*445a4aafSJia Jie Ho 			       unsigned int keylen, bool private)
474*445a4aafSJia Jie Ho {
475*445a4aafSJia Jie Ho 	struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
476*445a4aafSJia Jie Ho 	struct rsa_key raw_key = {NULL};
477*445a4aafSJia Jie Ho 	struct starfive_rsa_key *rsa_key = &ctx->rsa_key;
478*445a4aafSJia Jie Ho 	int ret;
479*445a4aafSJia Jie Ho 
480*445a4aafSJia Jie Ho 	if (private)
481*445a4aafSJia Jie Ho 		ret = rsa_parse_priv_key(&raw_key, key, keylen);
482*445a4aafSJia Jie Ho 	else
483*445a4aafSJia Jie Ho 		ret = rsa_parse_pub_key(&raw_key, key, keylen);
484*445a4aafSJia Jie Ho 	if (ret < 0)
485*445a4aafSJia Jie Ho 		goto err;
486*445a4aafSJia Jie Ho 
487*445a4aafSJia Jie Ho 	starfive_rsa_free_key(rsa_key);
488*445a4aafSJia Jie Ho 
489*445a4aafSJia Jie Ho 	/* Use fallback for mod > 256 + 1 byte prefix */
490*445a4aafSJia Jie Ho 	if (raw_key.n_sz > STARFIVE_RSA_MAX_KEYSZ + 1)
491*445a4aafSJia Jie Ho 		return 0;
492*445a4aafSJia Jie Ho 
493*445a4aafSJia Jie Ho 	ret = starfive_rsa_set_n(rsa_key, raw_key.n, raw_key.n_sz);
494*445a4aafSJia Jie Ho 	if (ret)
495*445a4aafSJia Jie Ho 		return ret;
496*445a4aafSJia Jie Ho 
497*445a4aafSJia Jie Ho 	ret = starfive_rsa_set_e(rsa_key, raw_key.e, raw_key.e_sz);
498*445a4aafSJia Jie Ho 	if (ret)
499*445a4aafSJia Jie Ho 		goto err;
500*445a4aafSJia Jie Ho 
501*445a4aafSJia Jie Ho 	if (private) {
502*445a4aafSJia Jie Ho 		ret = starfive_rsa_set_d(rsa_key, raw_key.d, raw_key.d_sz);
503*445a4aafSJia Jie Ho 		if (ret)
504*445a4aafSJia Jie Ho 			goto err;
505*445a4aafSJia Jie Ho 	}
506*445a4aafSJia Jie Ho 
507*445a4aafSJia Jie Ho 	if (!rsa_key->n || !rsa_key->e) {
508*445a4aafSJia Jie Ho 		ret = -EINVAL;
509*445a4aafSJia Jie Ho 		goto err;
510*445a4aafSJia Jie Ho 	}
511*445a4aafSJia Jie Ho 
512*445a4aafSJia Jie Ho 	if (private && !rsa_key->d) {
513*445a4aafSJia Jie Ho 		ret = -EINVAL;
514*445a4aafSJia Jie Ho 		goto err;
515*445a4aafSJia Jie Ho 	}
516*445a4aafSJia Jie Ho 
517*445a4aafSJia Jie Ho 	return 0;
518*445a4aafSJia Jie Ho  err:
519*445a4aafSJia Jie Ho 	starfive_rsa_free_key(rsa_key);
520*445a4aafSJia Jie Ho 	return ret;
521*445a4aafSJia Jie Ho }
522*445a4aafSJia Jie Ho 
starfive_rsa_set_pub_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen)523*445a4aafSJia Jie Ho static int starfive_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
524*445a4aafSJia Jie Ho 				    unsigned int keylen)
525*445a4aafSJia Jie Ho {
526*445a4aafSJia Jie Ho 	struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
527*445a4aafSJia Jie Ho 	int ret;
528*445a4aafSJia Jie Ho 
529*445a4aafSJia Jie Ho 	ret = crypto_akcipher_set_pub_key(ctx->akcipher_fbk, key, keylen);
530*445a4aafSJia Jie Ho 	if (ret)
531*445a4aafSJia Jie Ho 		return ret;
532*445a4aafSJia Jie Ho 
533*445a4aafSJia Jie Ho 	return starfive_rsa_setkey(tfm, key, keylen, false);
534*445a4aafSJia Jie Ho }
535*445a4aafSJia Jie Ho 
starfive_rsa_set_priv_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen)536*445a4aafSJia Jie Ho static int starfive_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
537*445a4aafSJia Jie Ho 				     unsigned int keylen)
538*445a4aafSJia Jie Ho {
539*445a4aafSJia Jie Ho 	struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
540*445a4aafSJia Jie Ho 	int ret;
541*445a4aafSJia Jie Ho 
542*445a4aafSJia Jie Ho 	ret = crypto_akcipher_set_priv_key(ctx->akcipher_fbk, key, keylen);
543*445a4aafSJia Jie Ho 	if (ret)
544*445a4aafSJia Jie Ho 		return ret;
545*445a4aafSJia Jie Ho 
546*445a4aafSJia Jie Ho 	return starfive_rsa_setkey(tfm, key, keylen, true);
547*445a4aafSJia Jie Ho }
548*445a4aafSJia Jie Ho 
starfive_rsa_max_size(struct crypto_akcipher * tfm)549*445a4aafSJia Jie Ho static unsigned int starfive_rsa_max_size(struct crypto_akcipher *tfm)
550*445a4aafSJia Jie Ho {
551*445a4aafSJia Jie Ho 	struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
552*445a4aafSJia Jie Ho 
553*445a4aafSJia Jie Ho 	if (ctx->rsa_key.key_sz)
554*445a4aafSJia Jie Ho 		return ctx->rsa_key.key_sz;
555*445a4aafSJia Jie Ho 
556*445a4aafSJia Jie Ho 	return crypto_akcipher_maxsize(ctx->akcipher_fbk);
557*445a4aafSJia Jie Ho }
558*445a4aafSJia Jie Ho 
starfive_rsa_init_tfm(struct crypto_akcipher * tfm)559*445a4aafSJia Jie Ho static int starfive_rsa_init_tfm(struct crypto_akcipher *tfm)
560*445a4aafSJia Jie Ho {
561*445a4aafSJia Jie Ho 	struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
562*445a4aafSJia Jie Ho 
563*445a4aafSJia Jie Ho 	ctx->akcipher_fbk = crypto_alloc_akcipher("rsa-generic", 0, 0);
564*445a4aafSJia Jie Ho 	if (IS_ERR(ctx->akcipher_fbk))
565*445a4aafSJia Jie Ho 		return PTR_ERR(ctx->akcipher_fbk);
566*445a4aafSJia Jie Ho 
567*445a4aafSJia Jie Ho 	ctx->cryp = starfive_cryp_find_dev(ctx);
568*445a4aafSJia Jie Ho 	if (!ctx->cryp) {
569*445a4aafSJia Jie Ho 		crypto_free_akcipher(ctx->akcipher_fbk);
570*445a4aafSJia Jie Ho 		return -ENODEV;
571*445a4aafSJia Jie Ho 	}
572*445a4aafSJia Jie Ho 
573*445a4aafSJia Jie Ho 	akcipher_set_reqsize(tfm, sizeof(struct starfive_cryp_request_ctx) +
574*445a4aafSJia Jie Ho 			     sizeof(struct crypto_akcipher) + 32);
575*445a4aafSJia Jie Ho 
576*445a4aafSJia Jie Ho 	return 0;
577*445a4aafSJia Jie Ho }
578*445a4aafSJia Jie Ho 
starfive_rsa_exit_tfm(struct crypto_akcipher * tfm)579*445a4aafSJia Jie Ho static void starfive_rsa_exit_tfm(struct crypto_akcipher *tfm)
580*445a4aafSJia Jie Ho {
581*445a4aafSJia Jie Ho 	struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
582*445a4aafSJia Jie Ho 	struct starfive_rsa_key *key = (struct starfive_rsa_key *)&ctx->rsa_key;
583*445a4aafSJia Jie Ho 
584*445a4aafSJia Jie Ho 	crypto_free_akcipher(ctx->akcipher_fbk);
585*445a4aafSJia Jie Ho 	starfive_rsa_free_key(key);
586*445a4aafSJia Jie Ho }
587*445a4aafSJia Jie Ho 
588*445a4aafSJia Jie Ho static struct akcipher_alg starfive_rsa = {
589*445a4aafSJia Jie Ho 	.encrypt = starfive_rsa_enc,
590*445a4aafSJia Jie Ho 	.decrypt = starfive_rsa_dec,
591*445a4aafSJia Jie Ho 	.sign = starfive_rsa_dec,
592*445a4aafSJia Jie Ho 	.verify = starfive_rsa_enc,
593*445a4aafSJia Jie Ho 	.set_pub_key = starfive_rsa_set_pub_key,
594*445a4aafSJia Jie Ho 	.set_priv_key = starfive_rsa_set_priv_key,
595*445a4aafSJia Jie Ho 	.max_size = starfive_rsa_max_size,
596*445a4aafSJia Jie Ho 	.init = starfive_rsa_init_tfm,
597*445a4aafSJia Jie Ho 	.exit = starfive_rsa_exit_tfm,
598*445a4aafSJia Jie Ho 	.base = {
599*445a4aafSJia Jie Ho 		.cra_name = "rsa",
600*445a4aafSJia Jie Ho 		.cra_driver_name = "starfive-rsa",
601*445a4aafSJia Jie Ho 		.cra_flags = CRYPTO_ALG_TYPE_AKCIPHER |
602*445a4aafSJia Jie Ho 			     CRYPTO_ALG_NEED_FALLBACK,
603*445a4aafSJia Jie Ho 		.cra_priority = 3000,
604*445a4aafSJia Jie Ho 		.cra_module = THIS_MODULE,
605*445a4aafSJia Jie Ho 		.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
606*445a4aafSJia Jie Ho 	},
607*445a4aafSJia Jie Ho };
608*445a4aafSJia Jie Ho 
starfive_rsa_register_algs(void)609*445a4aafSJia Jie Ho int starfive_rsa_register_algs(void)
610*445a4aafSJia Jie Ho {
611*445a4aafSJia Jie Ho 	return crypto_register_akcipher(&starfive_rsa);
612*445a4aafSJia Jie Ho }
613*445a4aafSJia Jie Ho 
starfive_rsa_unregister_algs(void)614*445a4aafSJia Jie Ho void starfive_rsa_unregister_algs(void)
615*445a4aafSJia Jie Ho {
616*445a4aafSJia Jie Ho 	crypto_unregister_akcipher(&starfive_rsa);
617*445a4aafSJia Jie Ho }
618