xref: /OK3568_Linux_fs/kernel/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * sun4i-ss-cipher.c - hardware cryptographic accelerator for Allwinner A20 SoC
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * This file add support for AES cipher with 128,192,256 bits
8*4882a593Smuzhiyun  * keysize in CBC and ECB mode.
9*4882a593Smuzhiyun  * Add support also for DES and 3DES in CBC and ECB mode.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * You could find the datasheet in Documentation/arm/sunxi.rst
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun #include "sun4i-ss.h"
14*4882a593Smuzhiyun 
sun4i_ss_opti_poll(struct skcipher_request * areq)15*4882a593Smuzhiyun static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
18*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
19*4882a593Smuzhiyun 	struct sun4i_ss_ctx *ss = op->ss;
20*4882a593Smuzhiyun 	unsigned int ivsize = crypto_skcipher_ivsize(tfm);
21*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq);
22*4882a593Smuzhiyun 	u32 mode = ctx->mode;
23*4882a593Smuzhiyun 	void *backup_iv = NULL;
24*4882a593Smuzhiyun 	/* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */
25*4882a593Smuzhiyun 	u32 rx_cnt = SS_RX_DEFAULT;
26*4882a593Smuzhiyun 	u32 tx_cnt = 0;
27*4882a593Smuzhiyun 	u32 spaces;
28*4882a593Smuzhiyun 	u32 v;
29*4882a593Smuzhiyun 	int err = 0;
30*4882a593Smuzhiyun 	unsigned int i;
31*4882a593Smuzhiyun 	unsigned int ileft = areq->cryptlen;
32*4882a593Smuzhiyun 	unsigned int oleft = areq->cryptlen;
33*4882a593Smuzhiyun 	unsigned int todo;
34*4882a593Smuzhiyun 	unsigned long pi = 0, po = 0; /* progress for in and out */
35*4882a593Smuzhiyun 	bool miter_err;
36*4882a593Smuzhiyun 	struct sg_mapping_iter mi, mo;
37*4882a593Smuzhiyun 	unsigned int oi, oo; /* offset for in and out */
38*4882a593Smuzhiyun 	unsigned long flags;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	if (!areq->cryptlen)
41*4882a593Smuzhiyun 		return 0;
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	if (!areq->src || !areq->dst) {
44*4882a593Smuzhiyun 		dev_err_ratelimited(ss->dev, "ERROR: Some SGs are NULL\n");
45*4882a593Smuzhiyun 		return -EINVAL;
46*4882a593Smuzhiyun 	}
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) {
49*4882a593Smuzhiyun 		backup_iv = kzalloc(ivsize, GFP_KERNEL);
50*4882a593Smuzhiyun 		if (!backup_iv)
51*4882a593Smuzhiyun 			return -ENOMEM;
52*4882a593Smuzhiyun 		scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0);
53*4882a593Smuzhiyun 	}
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	spin_lock_irqsave(&ss->slock, flags);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	for (i = 0; i < op->keylen / 4; i++)
58*4882a593Smuzhiyun 		writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	if (areq->iv) {
61*4882a593Smuzhiyun 		for (i = 0; i < 4 && i < ivsize / 4; i++) {
62*4882a593Smuzhiyun 			v = *(u32 *)(areq->iv + i * 4);
63*4882a593Smuzhiyun 			writesl(ss->base + SS_IV0 + i * 4, &v, 1);
64*4882a593Smuzhiyun 		}
65*4882a593Smuzhiyun 	}
66*4882a593Smuzhiyun 	writel(mode, ss->base + SS_CTL);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	ileft = areq->cryptlen / 4;
70*4882a593Smuzhiyun 	oleft = areq->cryptlen / 4;
71*4882a593Smuzhiyun 	oi = 0;
72*4882a593Smuzhiyun 	oo = 0;
73*4882a593Smuzhiyun 	do {
74*4882a593Smuzhiyun 		if (ileft) {
75*4882a593Smuzhiyun 			sg_miter_start(&mi, areq->src, sg_nents(areq->src),
76*4882a593Smuzhiyun 					SG_MITER_FROM_SG | SG_MITER_ATOMIC);
77*4882a593Smuzhiyun 			if (pi)
78*4882a593Smuzhiyun 				sg_miter_skip(&mi, pi);
79*4882a593Smuzhiyun 			miter_err = sg_miter_next(&mi);
80*4882a593Smuzhiyun 			if (!miter_err || !mi.addr) {
81*4882a593Smuzhiyun 				dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
82*4882a593Smuzhiyun 				err = -EINVAL;
83*4882a593Smuzhiyun 				goto release_ss;
84*4882a593Smuzhiyun 			}
85*4882a593Smuzhiyun 			todo = min(rx_cnt, ileft);
86*4882a593Smuzhiyun 			todo = min_t(size_t, todo, (mi.length - oi) / 4);
87*4882a593Smuzhiyun 			if (todo) {
88*4882a593Smuzhiyun 				ileft -= todo;
89*4882a593Smuzhiyun 				writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo);
90*4882a593Smuzhiyun 				oi += todo * 4;
91*4882a593Smuzhiyun 			}
92*4882a593Smuzhiyun 			if (oi == mi.length) {
93*4882a593Smuzhiyun 				pi += mi.length;
94*4882a593Smuzhiyun 				oi = 0;
95*4882a593Smuzhiyun 			}
96*4882a593Smuzhiyun 			sg_miter_stop(&mi);
97*4882a593Smuzhiyun 		}
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 		spaces = readl(ss->base + SS_FCSR);
100*4882a593Smuzhiyun 		rx_cnt = SS_RXFIFO_SPACES(spaces);
101*4882a593Smuzhiyun 		tx_cnt = SS_TXFIFO_SPACES(spaces);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 		sg_miter_start(&mo, areq->dst, sg_nents(areq->dst),
104*4882a593Smuzhiyun 			       SG_MITER_TO_SG | SG_MITER_ATOMIC);
105*4882a593Smuzhiyun 		if (po)
106*4882a593Smuzhiyun 			sg_miter_skip(&mo, po);
107*4882a593Smuzhiyun 		miter_err = sg_miter_next(&mo);
108*4882a593Smuzhiyun 		if (!miter_err || !mo.addr) {
109*4882a593Smuzhiyun 			dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
110*4882a593Smuzhiyun 			err = -EINVAL;
111*4882a593Smuzhiyun 			goto release_ss;
112*4882a593Smuzhiyun 		}
113*4882a593Smuzhiyun 		todo = min(tx_cnt, oleft);
114*4882a593Smuzhiyun 		todo = min_t(size_t, todo, (mo.length - oo) / 4);
115*4882a593Smuzhiyun 		if (todo) {
116*4882a593Smuzhiyun 			oleft -= todo;
117*4882a593Smuzhiyun 			readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo);
118*4882a593Smuzhiyun 			oo += todo * 4;
119*4882a593Smuzhiyun 		}
120*4882a593Smuzhiyun 		if (oo == mo.length) {
121*4882a593Smuzhiyun 			oo = 0;
122*4882a593Smuzhiyun 			po += mo.length;
123*4882a593Smuzhiyun 		}
124*4882a593Smuzhiyun 		sg_miter_stop(&mo);
125*4882a593Smuzhiyun 	} while (oleft);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	if (areq->iv) {
128*4882a593Smuzhiyun 		if (mode & SS_DECRYPTION) {
129*4882a593Smuzhiyun 			memcpy(areq->iv, backup_iv, ivsize);
130*4882a593Smuzhiyun 			kfree_sensitive(backup_iv);
131*4882a593Smuzhiyun 		} else {
132*4882a593Smuzhiyun 			scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize,
133*4882a593Smuzhiyun 						 ivsize, 0);
134*4882a593Smuzhiyun 		}
135*4882a593Smuzhiyun 	}
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun release_ss:
138*4882a593Smuzhiyun 	writel(0, ss->base + SS_CTL);
139*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ss->slock, flags);
140*4882a593Smuzhiyun 	return err;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 
sun4i_ss_cipher_poll_fallback(struct skcipher_request * areq)144*4882a593Smuzhiyun static int noinline_for_stack sun4i_ss_cipher_poll_fallback(struct skcipher_request *areq)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
147*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
148*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq);
149*4882a593Smuzhiyun 	int err;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	skcipher_request_set_tfm(&ctx->fallback_req, op->fallback_tfm);
152*4882a593Smuzhiyun 	skcipher_request_set_callback(&ctx->fallback_req, areq->base.flags,
153*4882a593Smuzhiyun 				      areq->base.complete, areq->base.data);
154*4882a593Smuzhiyun 	skcipher_request_set_crypt(&ctx->fallback_req, areq->src, areq->dst,
155*4882a593Smuzhiyun 				   areq->cryptlen, areq->iv);
156*4882a593Smuzhiyun 	if (ctx->mode & SS_DECRYPTION)
157*4882a593Smuzhiyun 		err = crypto_skcipher_decrypt(&ctx->fallback_req);
158*4882a593Smuzhiyun 	else
159*4882a593Smuzhiyun 		err = crypto_skcipher_encrypt(&ctx->fallback_req);
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	return err;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun /* Generic function that support SG with size not multiple of 4 */
sun4i_ss_cipher_poll(struct skcipher_request * areq)165*4882a593Smuzhiyun static int sun4i_ss_cipher_poll(struct skcipher_request *areq)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
168*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
169*4882a593Smuzhiyun 	struct sun4i_ss_ctx *ss = op->ss;
170*4882a593Smuzhiyun 	int no_chunk = 1;
171*4882a593Smuzhiyun 	struct scatterlist *in_sg = areq->src;
172*4882a593Smuzhiyun 	struct scatterlist *out_sg = areq->dst;
173*4882a593Smuzhiyun 	unsigned int ivsize = crypto_skcipher_ivsize(tfm);
174*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq);
175*4882a593Smuzhiyun 	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
176*4882a593Smuzhiyun 	struct sun4i_ss_alg_template *algt;
177*4882a593Smuzhiyun 	u32 mode = ctx->mode;
178*4882a593Smuzhiyun 	/* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */
179*4882a593Smuzhiyun 	u32 rx_cnt = SS_RX_DEFAULT;
180*4882a593Smuzhiyun 	u32 tx_cnt = 0;
181*4882a593Smuzhiyun 	u32 v;
182*4882a593Smuzhiyun 	u32 spaces;
183*4882a593Smuzhiyun 	int err = 0;
184*4882a593Smuzhiyun 	unsigned int i;
185*4882a593Smuzhiyun 	unsigned int ileft = areq->cryptlen;
186*4882a593Smuzhiyun 	unsigned int oleft = areq->cryptlen;
187*4882a593Smuzhiyun 	unsigned int todo;
188*4882a593Smuzhiyun 	void *backup_iv = NULL;
189*4882a593Smuzhiyun 	struct sg_mapping_iter mi, mo;
190*4882a593Smuzhiyun 	unsigned long pi = 0, po = 0; /* progress for in and out */
191*4882a593Smuzhiyun 	bool miter_err;
192*4882a593Smuzhiyun 	unsigned int oi, oo;	/* offset for in and out */
193*4882a593Smuzhiyun 	unsigned int ob = 0;	/* offset in buf */
194*4882a593Smuzhiyun 	unsigned int obo = 0;	/* offset in bufo*/
195*4882a593Smuzhiyun 	unsigned int obl = 0;	/* length of data in bufo */
196*4882a593Smuzhiyun 	unsigned long flags;
197*4882a593Smuzhiyun 	bool need_fallback = false;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	if (!areq->cryptlen)
200*4882a593Smuzhiyun 		return 0;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	if (!areq->src || !areq->dst) {
203*4882a593Smuzhiyun 		dev_err_ratelimited(ss->dev, "ERROR: Some SGs are NULL\n");
204*4882a593Smuzhiyun 		return -EINVAL;
205*4882a593Smuzhiyun 	}
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	algt = container_of(alg, struct sun4i_ss_alg_template, alg.crypto);
208*4882a593Smuzhiyun 	if (areq->cryptlen % algt->alg.crypto.base.cra_blocksize)
209*4882a593Smuzhiyun 		need_fallback = true;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	/*
212*4882a593Smuzhiyun 	 * if we have only SGs with size multiple of 4,
213*4882a593Smuzhiyun 	 * we can use the SS optimized function
214*4882a593Smuzhiyun 	 */
215*4882a593Smuzhiyun 	while (in_sg && no_chunk == 1) {
216*4882a593Smuzhiyun 		if ((in_sg->length | in_sg->offset) & 3u)
217*4882a593Smuzhiyun 			no_chunk = 0;
218*4882a593Smuzhiyun 		in_sg = sg_next(in_sg);
219*4882a593Smuzhiyun 	}
220*4882a593Smuzhiyun 	while (out_sg && no_chunk == 1) {
221*4882a593Smuzhiyun 		if ((out_sg->length | out_sg->offset) & 3u)
222*4882a593Smuzhiyun 			no_chunk = 0;
223*4882a593Smuzhiyun 		out_sg = sg_next(out_sg);
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	if (no_chunk == 1 && !need_fallback)
227*4882a593Smuzhiyun 		return sun4i_ss_opti_poll(areq);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	if (need_fallback)
230*4882a593Smuzhiyun 		return sun4i_ss_cipher_poll_fallback(areq);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) {
233*4882a593Smuzhiyun 		backup_iv = kzalloc(ivsize, GFP_KERNEL);
234*4882a593Smuzhiyun 		if (!backup_iv)
235*4882a593Smuzhiyun 			return -ENOMEM;
236*4882a593Smuzhiyun 		scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0);
237*4882a593Smuzhiyun 	}
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	spin_lock_irqsave(&ss->slock, flags);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	for (i = 0; i < op->keylen / 4; i++)
242*4882a593Smuzhiyun 		writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	if (areq->iv) {
245*4882a593Smuzhiyun 		for (i = 0; i < 4 && i < ivsize / 4; i++) {
246*4882a593Smuzhiyun 			v = *(u32 *)(areq->iv + i * 4);
247*4882a593Smuzhiyun 			writesl(ss->base + SS_IV0 + i * 4, &v, 1);
248*4882a593Smuzhiyun 		}
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 	writel(mode, ss->base + SS_CTL);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	ileft = areq->cryptlen;
253*4882a593Smuzhiyun 	oleft = areq->cryptlen;
254*4882a593Smuzhiyun 	oi = 0;
255*4882a593Smuzhiyun 	oo = 0;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	while (oleft) {
258*4882a593Smuzhiyun 		if (ileft) {
259*4882a593Smuzhiyun 			sg_miter_start(&mi, areq->src, sg_nents(areq->src),
260*4882a593Smuzhiyun 				       SG_MITER_FROM_SG | SG_MITER_ATOMIC);
261*4882a593Smuzhiyun 			if (pi)
262*4882a593Smuzhiyun 				sg_miter_skip(&mi, pi);
263*4882a593Smuzhiyun 			miter_err = sg_miter_next(&mi);
264*4882a593Smuzhiyun 			if (!miter_err || !mi.addr) {
265*4882a593Smuzhiyun 				dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
266*4882a593Smuzhiyun 				err = -EINVAL;
267*4882a593Smuzhiyun 				goto release_ss;
268*4882a593Smuzhiyun 			}
269*4882a593Smuzhiyun 			/*
270*4882a593Smuzhiyun 			 * todo is the number of consecutive 4byte word that we
271*4882a593Smuzhiyun 			 * can read from current SG
272*4882a593Smuzhiyun 			 */
273*4882a593Smuzhiyun 			todo = min(rx_cnt, ileft / 4);
274*4882a593Smuzhiyun 			todo = min_t(size_t, todo, (mi.length - oi) / 4);
275*4882a593Smuzhiyun 			if (todo && !ob) {
276*4882a593Smuzhiyun 				writesl(ss->base + SS_RXFIFO, mi.addr + oi,
277*4882a593Smuzhiyun 					todo);
278*4882a593Smuzhiyun 				ileft -= todo * 4;
279*4882a593Smuzhiyun 				oi += todo * 4;
280*4882a593Smuzhiyun 			} else {
281*4882a593Smuzhiyun 				/*
282*4882a593Smuzhiyun 				 * not enough consecutive bytes, so we need to
283*4882a593Smuzhiyun 				 * linearize in buf. todo is in bytes
284*4882a593Smuzhiyun 				 * After that copy, if we have a multiple of 4
285*4882a593Smuzhiyun 				 * we need to be able to write all buf in one
286*4882a593Smuzhiyun 				 * pass, so it is why we min() with rx_cnt
287*4882a593Smuzhiyun 				 */
288*4882a593Smuzhiyun 				todo = min(rx_cnt * 4 - ob, ileft);
289*4882a593Smuzhiyun 				todo = min_t(size_t, todo, mi.length - oi);
290*4882a593Smuzhiyun 				memcpy(ss->buf + ob, mi.addr + oi, todo);
291*4882a593Smuzhiyun 				ileft -= todo;
292*4882a593Smuzhiyun 				oi += todo;
293*4882a593Smuzhiyun 				ob += todo;
294*4882a593Smuzhiyun 				if (!(ob % 4)) {
295*4882a593Smuzhiyun 					writesl(ss->base + SS_RXFIFO, ss->buf,
296*4882a593Smuzhiyun 						ob / 4);
297*4882a593Smuzhiyun 					ob = 0;
298*4882a593Smuzhiyun 				}
299*4882a593Smuzhiyun 			}
300*4882a593Smuzhiyun 			if (oi == mi.length) {
301*4882a593Smuzhiyun 				pi += mi.length;
302*4882a593Smuzhiyun 				oi = 0;
303*4882a593Smuzhiyun 			}
304*4882a593Smuzhiyun 			sg_miter_stop(&mi);
305*4882a593Smuzhiyun 		}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 		spaces = readl(ss->base + SS_FCSR);
308*4882a593Smuzhiyun 		rx_cnt = SS_RXFIFO_SPACES(spaces);
309*4882a593Smuzhiyun 		tx_cnt = SS_TXFIFO_SPACES(spaces);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 		if (!tx_cnt)
312*4882a593Smuzhiyun 			continue;
313*4882a593Smuzhiyun 		sg_miter_start(&mo, areq->dst, sg_nents(areq->dst),
314*4882a593Smuzhiyun 			       SG_MITER_TO_SG | SG_MITER_ATOMIC);
315*4882a593Smuzhiyun 		if (po)
316*4882a593Smuzhiyun 			sg_miter_skip(&mo, po);
317*4882a593Smuzhiyun 		miter_err = sg_miter_next(&mo);
318*4882a593Smuzhiyun 		if (!miter_err || !mo.addr) {
319*4882a593Smuzhiyun 			dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
320*4882a593Smuzhiyun 			err = -EINVAL;
321*4882a593Smuzhiyun 			goto release_ss;
322*4882a593Smuzhiyun 		}
323*4882a593Smuzhiyun 		/* todo in 4bytes word */
324*4882a593Smuzhiyun 		todo = min(tx_cnt, oleft / 4);
325*4882a593Smuzhiyun 		todo = min_t(size_t, todo, (mo.length - oo) / 4);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 		if (todo) {
328*4882a593Smuzhiyun 			readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo);
329*4882a593Smuzhiyun 			oleft -= todo * 4;
330*4882a593Smuzhiyun 			oo += todo * 4;
331*4882a593Smuzhiyun 			if (oo == mo.length) {
332*4882a593Smuzhiyun 				po += mo.length;
333*4882a593Smuzhiyun 				oo = 0;
334*4882a593Smuzhiyun 			}
335*4882a593Smuzhiyun 		} else {
336*4882a593Smuzhiyun 			/*
337*4882a593Smuzhiyun 			 * read obl bytes in bufo, we read at maximum for
338*4882a593Smuzhiyun 			 * emptying the device
339*4882a593Smuzhiyun 			 */
340*4882a593Smuzhiyun 			readsl(ss->base + SS_TXFIFO, ss->bufo, tx_cnt);
341*4882a593Smuzhiyun 			obl = tx_cnt * 4;
342*4882a593Smuzhiyun 			obo = 0;
343*4882a593Smuzhiyun 			do {
344*4882a593Smuzhiyun 				/*
345*4882a593Smuzhiyun 				 * how many bytes we can copy ?
346*4882a593Smuzhiyun 				 * no more than remaining SG size
347*4882a593Smuzhiyun 				 * no more than remaining buffer
348*4882a593Smuzhiyun 				 * no need to test against oleft
349*4882a593Smuzhiyun 				 */
350*4882a593Smuzhiyun 				todo = min_t(size_t,
351*4882a593Smuzhiyun 					     mo.length - oo, obl - obo);
352*4882a593Smuzhiyun 				memcpy(mo.addr + oo, ss->bufo + obo, todo);
353*4882a593Smuzhiyun 				oleft -= todo;
354*4882a593Smuzhiyun 				obo += todo;
355*4882a593Smuzhiyun 				oo += todo;
356*4882a593Smuzhiyun 				if (oo == mo.length) {
357*4882a593Smuzhiyun 					po += mo.length;
358*4882a593Smuzhiyun 					sg_miter_next(&mo);
359*4882a593Smuzhiyun 					oo = 0;
360*4882a593Smuzhiyun 				}
361*4882a593Smuzhiyun 			} while (obo < obl);
362*4882a593Smuzhiyun 			/* bufo must be fully used here */
363*4882a593Smuzhiyun 		}
364*4882a593Smuzhiyun 		sg_miter_stop(&mo);
365*4882a593Smuzhiyun 	}
366*4882a593Smuzhiyun 	if (areq->iv) {
367*4882a593Smuzhiyun 		if (mode & SS_DECRYPTION) {
368*4882a593Smuzhiyun 			memcpy(areq->iv, backup_iv, ivsize);
369*4882a593Smuzhiyun 			kfree_sensitive(backup_iv);
370*4882a593Smuzhiyun 		} else {
371*4882a593Smuzhiyun 			scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize,
372*4882a593Smuzhiyun 						 ivsize, 0);
373*4882a593Smuzhiyun 		}
374*4882a593Smuzhiyun 	}
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun release_ss:
377*4882a593Smuzhiyun 	writel(0, ss->base + SS_CTL);
378*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ss->slock, flags);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	return err;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun /* CBC AES */
sun4i_ss_cbc_aes_encrypt(struct skcipher_request * areq)384*4882a593Smuzhiyun int sun4i_ss_cbc_aes_encrypt(struct skcipher_request *areq)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
387*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
388*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	rctx->mode = SS_OP_AES | SS_CBC | SS_ENABLED | SS_ENCRYPTION |
391*4882a593Smuzhiyun 		op->keymode;
392*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
sun4i_ss_cbc_aes_decrypt(struct skcipher_request * areq)395*4882a593Smuzhiyun int sun4i_ss_cbc_aes_decrypt(struct skcipher_request *areq)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
398*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
399*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	rctx->mode = SS_OP_AES | SS_CBC | SS_ENABLED | SS_DECRYPTION |
402*4882a593Smuzhiyun 		op->keymode;
403*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun /* ECB AES */
sun4i_ss_ecb_aes_encrypt(struct skcipher_request * areq)407*4882a593Smuzhiyun int sun4i_ss_ecb_aes_encrypt(struct skcipher_request *areq)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
410*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
411*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	rctx->mode = SS_OP_AES | SS_ECB | SS_ENABLED | SS_ENCRYPTION |
414*4882a593Smuzhiyun 		op->keymode;
415*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun 
sun4i_ss_ecb_aes_decrypt(struct skcipher_request * areq)418*4882a593Smuzhiyun int sun4i_ss_ecb_aes_decrypt(struct skcipher_request *areq)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
421*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
422*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	rctx->mode = SS_OP_AES | SS_ECB | SS_ENABLED | SS_DECRYPTION |
425*4882a593Smuzhiyun 		op->keymode;
426*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun /* CBC DES */
sun4i_ss_cbc_des_encrypt(struct skcipher_request * areq)430*4882a593Smuzhiyun int sun4i_ss_cbc_des_encrypt(struct skcipher_request *areq)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
433*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
434*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	rctx->mode = SS_OP_DES | SS_CBC | SS_ENABLED | SS_ENCRYPTION |
437*4882a593Smuzhiyun 		op->keymode;
438*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun 
sun4i_ss_cbc_des_decrypt(struct skcipher_request * areq)441*4882a593Smuzhiyun int sun4i_ss_cbc_des_decrypt(struct skcipher_request *areq)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
444*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
445*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	rctx->mode = SS_OP_DES | SS_CBC | SS_ENABLED | SS_DECRYPTION |
448*4882a593Smuzhiyun 		op->keymode;
449*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun /* ECB DES */
sun4i_ss_ecb_des_encrypt(struct skcipher_request * areq)453*4882a593Smuzhiyun int sun4i_ss_ecb_des_encrypt(struct skcipher_request *areq)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
456*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
457*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	rctx->mode = SS_OP_DES | SS_ECB | SS_ENABLED | SS_ENCRYPTION |
460*4882a593Smuzhiyun 		op->keymode;
461*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun 
sun4i_ss_ecb_des_decrypt(struct skcipher_request * areq)464*4882a593Smuzhiyun int sun4i_ss_ecb_des_decrypt(struct skcipher_request *areq)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
467*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
468*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	rctx->mode = SS_OP_DES | SS_ECB | SS_ENABLED | SS_DECRYPTION |
471*4882a593Smuzhiyun 		op->keymode;
472*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun /* CBC 3DES */
sun4i_ss_cbc_des3_encrypt(struct skcipher_request * areq)476*4882a593Smuzhiyun int sun4i_ss_cbc_des3_encrypt(struct skcipher_request *areq)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
479*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
480*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	rctx->mode = SS_OP_3DES | SS_CBC | SS_ENABLED | SS_ENCRYPTION |
483*4882a593Smuzhiyun 		op->keymode;
484*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
sun4i_ss_cbc_des3_decrypt(struct skcipher_request * areq)487*4882a593Smuzhiyun int sun4i_ss_cbc_des3_decrypt(struct skcipher_request *areq)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
490*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
491*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	rctx->mode = SS_OP_3DES | SS_CBC | SS_ENABLED | SS_DECRYPTION |
494*4882a593Smuzhiyun 		op->keymode;
495*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun /* ECB 3DES */
sun4i_ss_ecb_des3_encrypt(struct skcipher_request * areq)499*4882a593Smuzhiyun int sun4i_ss_ecb_des3_encrypt(struct skcipher_request *areq)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
502*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
503*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	rctx->mode = SS_OP_3DES | SS_ECB | SS_ENABLED | SS_ENCRYPTION |
506*4882a593Smuzhiyun 		op->keymode;
507*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun 
sun4i_ss_ecb_des3_decrypt(struct skcipher_request * areq)510*4882a593Smuzhiyun int sun4i_ss_ecb_des3_decrypt(struct skcipher_request *areq)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);
513*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
514*4882a593Smuzhiyun 	struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq);
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	rctx->mode = SS_OP_3DES | SS_ECB | SS_ENABLED | SS_DECRYPTION |
517*4882a593Smuzhiyun 		op->keymode;
518*4882a593Smuzhiyun 	return sun4i_ss_cipher_poll(areq);
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun 
sun4i_ss_cipher_init(struct crypto_tfm * tfm)521*4882a593Smuzhiyun int sun4i_ss_cipher_init(struct crypto_tfm *tfm)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm);
524*4882a593Smuzhiyun 	struct sun4i_ss_alg_template *algt;
525*4882a593Smuzhiyun 	const char *name = crypto_tfm_alg_name(tfm);
526*4882a593Smuzhiyun 	int err;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	memset(op, 0, sizeof(struct sun4i_tfm_ctx));
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	algt = container_of(tfm->__crt_alg, struct sun4i_ss_alg_template,
531*4882a593Smuzhiyun 			    alg.crypto.base);
532*4882a593Smuzhiyun 	op->ss = algt->ss;
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	op->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK);
535*4882a593Smuzhiyun 	if (IS_ERR(op->fallback_tfm)) {
536*4882a593Smuzhiyun 		dev_err(op->ss->dev, "ERROR: Cannot allocate fallback for %s %ld\n",
537*4882a593Smuzhiyun 			name, PTR_ERR(op->fallback_tfm));
538*4882a593Smuzhiyun 		return PTR_ERR(op->fallback_tfm);
539*4882a593Smuzhiyun 	}
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm),
542*4882a593Smuzhiyun 				    sizeof(struct sun4i_cipher_req_ctx) +
543*4882a593Smuzhiyun 				    crypto_skcipher_reqsize(op->fallback_tfm));
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	err = pm_runtime_get_sync(op->ss->dev);
547*4882a593Smuzhiyun 	if (err < 0)
548*4882a593Smuzhiyun 		goto error_pm;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	return 0;
551*4882a593Smuzhiyun error_pm:
552*4882a593Smuzhiyun 	crypto_free_skcipher(op->fallback_tfm);
553*4882a593Smuzhiyun 	return err;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
sun4i_ss_cipher_exit(struct crypto_tfm * tfm)556*4882a593Smuzhiyun void sun4i_ss_cipher_exit(struct crypto_tfm *tfm)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	crypto_free_skcipher(op->fallback_tfm);
561*4882a593Smuzhiyun 	pm_runtime_put(op->ss->dev);
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun /* check and set the AES key, prepare the mode to be used */
sun4i_ss_aes_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)565*4882a593Smuzhiyun int sun4i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
566*4882a593Smuzhiyun 			unsigned int keylen)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
569*4882a593Smuzhiyun 	struct sun4i_ss_ctx *ss = op->ss;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	switch (keylen) {
572*4882a593Smuzhiyun 	case 128 / 8:
573*4882a593Smuzhiyun 		op->keymode = SS_AES_128BITS;
574*4882a593Smuzhiyun 		break;
575*4882a593Smuzhiyun 	case 192 / 8:
576*4882a593Smuzhiyun 		op->keymode = SS_AES_192BITS;
577*4882a593Smuzhiyun 		break;
578*4882a593Smuzhiyun 	case 256 / 8:
579*4882a593Smuzhiyun 		op->keymode = SS_AES_256BITS;
580*4882a593Smuzhiyun 		break;
581*4882a593Smuzhiyun 	default:
582*4882a593Smuzhiyun 		dev_dbg(ss->dev, "ERROR: Invalid keylen %u\n", keylen);
583*4882a593Smuzhiyun 		return -EINVAL;
584*4882a593Smuzhiyun 	}
585*4882a593Smuzhiyun 	op->keylen = keylen;
586*4882a593Smuzhiyun 	memcpy(op->key, key, keylen);
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	crypto_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK);
589*4882a593Smuzhiyun 	crypto_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK);
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	return crypto_skcipher_setkey(op->fallback_tfm, key, keylen);
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun /* check and set the DES key, prepare the mode to be used */
sun4i_ss_des_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)595*4882a593Smuzhiyun int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
596*4882a593Smuzhiyun 			unsigned int keylen)
597*4882a593Smuzhiyun {
598*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
599*4882a593Smuzhiyun 	int err;
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	err = verify_skcipher_des_key(tfm, key);
602*4882a593Smuzhiyun 	if (err)
603*4882a593Smuzhiyun 		return err;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	op->keylen = keylen;
606*4882a593Smuzhiyun 	memcpy(op->key, key, keylen);
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	crypto_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK);
609*4882a593Smuzhiyun 	crypto_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK);
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	return crypto_skcipher_setkey(op->fallback_tfm, key, keylen);
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun /* check and set the 3DES key, prepare the mode to be used */
sun4i_ss_des3_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)615*4882a593Smuzhiyun int sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key,
616*4882a593Smuzhiyun 			 unsigned int keylen)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun 	struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm);
619*4882a593Smuzhiyun 	int err;
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	err = verify_skcipher_des3_key(tfm, key);
622*4882a593Smuzhiyun 	if (err)
623*4882a593Smuzhiyun 		return err;
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	op->keylen = keylen;
626*4882a593Smuzhiyun 	memcpy(op->key, key, keylen);
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	crypto_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK);
629*4882a593Smuzhiyun 	crypto_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK);
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	return crypto_skcipher_setkey(op->fallback_tfm, key, keylen);
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun }
634