xref: /linux/drivers/crypto/inside-secure/eip93/eip93-common.c (revision 9739f5f93b7806a684713ba42e6ed2d1df7c8100)
1*9739f5f9SChristian Marangi // SPDX-License-Identifier: GPL-2.0
2*9739f5f9SChristian Marangi /*
3*9739f5f9SChristian Marangi  * Copyright (C) 2019 - 2021
4*9739f5f9SChristian Marangi  *
5*9739f5f9SChristian Marangi  * Richard van Schagen <vschagen@icloud.com>
6*9739f5f9SChristian Marangi  * Christian Marangi <ansuelsmth@gmail.com
7*9739f5f9SChristian Marangi  */
8*9739f5f9SChristian Marangi 
9*9739f5f9SChristian Marangi #include <crypto/aes.h>
10*9739f5f9SChristian Marangi #include <crypto/ctr.h>
11*9739f5f9SChristian Marangi #include <crypto/hmac.h>
12*9739f5f9SChristian Marangi #include <crypto/sha1.h>
13*9739f5f9SChristian Marangi #include <crypto/sha2.h>
14*9739f5f9SChristian Marangi #include <linux/kernel.h>
15*9739f5f9SChristian Marangi #include <linux/delay.h>
16*9739f5f9SChristian Marangi #include <linux/dma-mapping.h>
17*9739f5f9SChristian Marangi #include <linux/scatterlist.h>
18*9739f5f9SChristian Marangi 
19*9739f5f9SChristian Marangi #include "eip93-cipher.h"
20*9739f5f9SChristian Marangi #include "eip93-hash.h"
21*9739f5f9SChristian Marangi #include "eip93-common.h"
22*9739f5f9SChristian Marangi #include "eip93-main.h"
23*9739f5f9SChristian Marangi #include "eip93-regs.h"
24*9739f5f9SChristian Marangi 
25*9739f5f9SChristian Marangi int eip93_parse_ctrl_stat_err(struct eip93_device *eip93, int err)
26*9739f5f9SChristian Marangi {
27*9739f5f9SChristian Marangi 	u32 ext_err;
28*9739f5f9SChristian Marangi 
29*9739f5f9SChristian Marangi 	if (!err)
30*9739f5f9SChristian Marangi 		return 0;
31*9739f5f9SChristian Marangi 
32*9739f5f9SChristian Marangi 	switch (err & ~EIP93_PE_CTRL_PE_EXT_ERR_CODE) {
33*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_AUTH_ERR:
34*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_PAD_ERR:
35*9739f5f9SChristian Marangi 		return -EBADMSG;
36*9739f5f9SChristian Marangi 	/* let software handle anti-replay errors */
37*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_SEQNUM_ERR:
38*9739f5f9SChristian Marangi 		return 0;
39*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR:
40*9739f5f9SChristian Marangi 		break;
41*9739f5f9SChristian Marangi 	default:
42*9739f5f9SChristian Marangi 		dev_err(eip93->dev, "Unhandled error 0x%08x\n", err);
43*9739f5f9SChristian Marangi 		return -EINVAL;
44*9739f5f9SChristian Marangi 	}
45*9739f5f9SChristian Marangi 
46*9739f5f9SChristian Marangi 	/* Parse additional ext errors */
47*9739f5f9SChristian Marangi 	ext_err = FIELD_GET(EIP93_PE_CTRL_PE_EXT_ERR_CODE, err);
48*9739f5f9SChristian Marangi 	switch (ext_err) {
49*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR_BUS:
50*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR_PROCESSING:
51*9739f5f9SChristian Marangi 		return -EIO;
52*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR_DESC_OWNER:
53*9739f5f9SChristian Marangi 		return -EACCES;
54*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR_INVALID_CRYPTO_OP:
55*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR_INVALID_CRYPTO_ALGO:
56*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR_SPI:
57*9739f5f9SChristian Marangi 		return -EINVAL;
58*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR_ZERO_LENGTH:
59*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR_INVALID_PK_LENGTH:
60*9739f5f9SChristian Marangi 	case EIP93_PE_CTRL_PE_EXT_ERR_BLOCK_SIZE_ERR:
61*9739f5f9SChristian Marangi 		return -EBADMSG;
62*9739f5f9SChristian Marangi 	default:
63*9739f5f9SChristian Marangi 		dev_err(eip93->dev, "Unhandled ext error 0x%08x\n", ext_err);
64*9739f5f9SChristian Marangi 		return -EINVAL;
65*9739f5f9SChristian Marangi 	}
66*9739f5f9SChristian Marangi }
67*9739f5f9SChristian Marangi 
68*9739f5f9SChristian Marangi static void *eip93_ring_next_wptr(struct eip93_device *eip93,
69*9739f5f9SChristian Marangi 				  struct eip93_desc_ring *ring)
70*9739f5f9SChristian Marangi {
71*9739f5f9SChristian Marangi 	void *ptr = ring->write;
72*9739f5f9SChristian Marangi 
73*9739f5f9SChristian Marangi 	if ((ring->write == ring->read - ring->offset) ||
74*9739f5f9SChristian Marangi 	    (ring->read == ring->base && ring->write == ring->base_end))
75*9739f5f9SChristian Marangi 		return ERR_PTR(-ENOMEM);
76*9739f5f9SChristian Marangi 
77*9739f5f9SChristian Marangi 	if (ring->write == ring->base_end)
78*9739f5f9SChristian Marangi 		ring->write = ring->base;
79*9739f5f9SChristian Marangi 	else
80*9739f5f9SChristian Marangi 		ring->write += ring->offset;
81*9739f5f9SChristian Marangi 
82*9739f5f9SChristian Marangi 	return ptr;
83*9739f5f9SChristian Marangi }
84*9739f5f9SChristian Marangi 
85*9739f5f9SChristian Marangi static void *eip93_ring_next_rptr(struct eip93_device *eip93,
86*9739f5f9SChristian Marangi 				  struct eip93_desc_ring *ring)
87*9739f5f9SChristian Marangi {
88*9739f5f9SChristian Marangi 	void *ptr = ring->read;
89*9739f5f9SChristian Marangi 
90*9739f5f9SChristian Marangi 	if (ring->write == ring->read)
91*9739f5f9SChristian Marangi 		return ERR_PTR(-ENOENT);
92*9739f5f9SChristian Marangi 
93*9739f5f9SChristian Marangi 	if (ring->read == ring->base_end)
94*9739f5f9SChristian Marangi 		ring->read = ring->base;
95*9739f5f9SChristian Marangi 	else
96*9739f5f9SChristian Marangi 		ring->read += ring->offset;
97*9739f5f9SChristian Marangi 
98*9739f5f9SChristian Marangi 	return ptr;
99*9739f5f9SChristian Marangi }
100*9739f5f9SChristian Marangi 
101*9739f5f9SChristian Marangi int eip93_put_descriptor(struct eip93_device *eip93,
102*9739f5f9SChristian Marangi 			 struct eip93_descriptor *desc)
103*9739f5f9SChristian Marangi {
104*9739f5f9SChristian Marangi 	struct eip93_descriptor *cdesc;
105*9739f5f9SChristian Marangi 	struct eip93_descriptor *rdesc;
106*9739f5f9SChristian Marangi 
107*9739f5f9SChristian Marangi 	rdesc = eip93_ring_next_wptr(eip93, &eip93->ring->rdr);
108*9739f5f9SChristian Marangi 	if (IS_ERR(rdesc))
109*9739f5f9SChristian Marangi 		return -ENOENT;
110*9739f5f9SChristian Marangi 
111*9739f5f9SChristian Marangi 	cdesc = eip93_ring_next_wptr(eip93, &eip93->ring->cdr);
112*9739f5f9SChristian Marangi 	if (IS_ERR(cdesc))
113*9739f5f9SChristian Marangi 		return -ENOENT;
114*9739f5f9SChristian Marangi 
115*9739f5f9SChristian Marangi 	memset(rdesc, 0, sizeof(struct eip93_descriptor));
116*9739f5f9SChristian Marangi 
117*9739f5f9SChristian Marangi 	memcpy(cdesc, desc, sizeof(struct eip93_descriptor));
118*9739f5f9SChristian Marangi 
119*9739f5f9SChristian Marangi 	return 0;
120*9739f5f9SChristian Marangi }
121*9739f5f9SChristian Marangi 
122*9739f5f9SChristian Marangi void *eip93_get_descriptor(struct eip93_device *eip93)
123*9739f5f9SChristian Marangi {
124*9739f5f9SChristian Marangi 	struct eip93_descriptor *cdesc;
125*9739f5f9SChristian Marangi 	void *ptr;
126*9739f5f9SChristian Marangi 
127*9739f5f9SChristian Marangi 	cdesc = eip93_ring_next_rptr(eip93, &eip93->ring->cdr);
128*9739f5f9SChristian Marangi 	if (IS_ERR(cdesc))
129*9739f5f9SChristian Marangi 		return ERR_PTR(-ENOENT);
130*9739f5f9SChristian Marangi 
131*9739f5f9SChristian Marangi 	memset(cdesc, 0, sizeof(struct eip93_descriptor));
132*9739f5f9SChristian Marangi 
133*9739f5f9SChristian Marangi 	ptr = eip93_ring_next_rptr(eip93, &eip93->ring->rdr);
134*9739f5f9SChristian Marangi 	if (IS_ERR(ptr))
135*9739f5f9SChristian Marangi 		return ERR_PTR(-ENOENT);
136*9739f5f9SChristian Marangi 
137*9739f5f9SChristian Marangi 	return ptr;
138*9739f5f9SChristian Marangi }
139*9739f5f9SChristian Marangi 
140*9739f5f9SChristian Marangi static void eip93_free_sg_copy(const int len, struct scatterlist **sg)
141*9739f5f9SChristian Marangi {
142*9739f5f9SChristian Marangi 	if (!*sg || !len)
143*9739f5f9SChristian Marangi 		return;
144*9739f5f9SChristian Marangi 
145*9739f5f9SChristian Marangi 	free_pages((unsigned long)sg_virt(*sg), get_order(len));
146*9739f5f9SChristian Marangi 	kfree(*sg);
147*9739f5f9SChristian Marangi 	*sg = NULL;
148*9739f5f9SChristian Marangi }
149*9739f5f9SChristian Marangi 
150*9739f5f9SChristian Marangi static int eip93_make_sg_copy(struct scatterlist *src, struct scatterlist **dst,
151*9739f5f9SChristian Marangi 			      const u32 len, const bool copy)
152*9739f5f9SChristian Marangi {
153*9739f5f9SChristian Marangi 	void *pages;
154*9739f5f9SChristian Marangi 
155*9739f5f9SChristian Marangi 	*dst = kmalloc(sizeof(**dst), GFP_KERNEL);
156*9739f5f9SChristian Marangi 	if (!*dst)
157*9739f5f9SChristian Marangi 		return -ENOMEM;
158*9739f5f9SChristian Marangi 
159*9739f5f9SChristian Marangi 	pages = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA,
160*9739f5f9SChristian Marangi 					 get_order(len));
161*9739f5f9SChristian Marangi 	if (!pages) {
162*9739f5f9SChristian Marangi 		kfree(*dst);
163*9739f5f9SChristian Marangi 		*dst = NULL;
164*9739f5f9SChristian Marangi 		return -ENOMEM;
165*9739f5f9SChristian Marangi 	}
166*9739f5f9SChristian Marangi 
167*9739f5f9SChristian Marangi 	sg_init_table(*dst, 1);
168*9739f5f9SChristian Marangi 	sg_set_buf(*dst, pages, len);
169*9739f5f9SChristian Marangi 
170*9739f5f9SChristian Marangi 	/* copy only as requested */
171*9739f5f9SChristian Marangi 	if (copy)
172*9739f5f9SChristian Marangi 		sg_copy_to_buffer(src, sg_nents(src), pages, len);
173*9739f5f9SChristian Marangi 
174*9739f5f9SChristian Marangi 	return 0;
175*9739f5f9SChristian Marangi }
176*9739f5f9SChristian Marangi 
177*9739f5f9SChristian Marangi static bool eip93_is_sg_aligned(struct scatterlist *sg, u32 len,
178*9739f5f9SChristian Marangi 				const int blksize)
179*9739f5f9SChristian Marangi {
180*9739f5f9SChristian Marangi 	int nents;
181*9739f5f9SChristian Marangi 
182*9739f5f9SChristian Marangi 	for (nents = 0; sg; sg = sg_next(sg), ++nents) {
183*9739f5f9SChristian Marangi 		if (!IS_ALIGNED(sg->offset, 4))
184*9739f5f9SChristian Marangi 			return false;
185*9739f5f9SChristian Marangi 
186*9739f5f9SChristian Marangi 		if (len <= sg->length) {
187*9739f5f9SChristian Marangi 			if (!IS_ALIGNED(len, blksize))
188*9739f5f9SChristian Marangi 				return false;
189*9739f5f9SChristian Marangi 
190*9739f5f9SChristian Marangi 			return true;
191*9739f5f9SChristian Marangi 		}
192*9739f5f9SChristian Marangi 
193*9739f5f9SChristian Marangi 		if (!IS_ALIGNED(sg->length, blksize))
194*9739f5f9SChristian Marangi 			return false;
195*9739f5f9SChristian Marangi 
196*9739f5f9SChristian Marangi 		len -= sg->length;
197*9739f5f9SChristian Marangi 	}
198*9739f5f9SChristian Marangi 	return false;
199*9739f5f9SChristian Marangi }
200*9739f5f9SChristian Marangi 
201*9739f5f9SChristian Marangi int check_valid_request(struct eip93_cipher_reqctx *rctx)
202*9739f5f9SChristian Marangi {
203*9739f5f9SChristian Marangi 	struct scatterlist *src = rctx->sg_src;
204*9739f5f9SChristian Marangi 	struct scatterlist *dst = rctx->sg_dst;
205*9739f5f9SChristian Marangi 	u32 src_nents, dst_nents;
206*9739f5f9SChristian Marangi 	u32 textsize = rctx->textsize;
207*9739f5f9SChristian Marangi 	u32 authsize = rctx->authsize;
208*9739f5f9SChristian Marangi 	u32 blksize = rctx->blksize;
209*9739f5f9SChristian Marangi 	u32 totlen_src = rctx->assoclen + rctx->textsize;
210*9739f5f9SChristian Marangi 	u32 totlen_dst = rctx->assoclen + rctx->textsize;
211*9739f5f9SChristian Marangi 	u32 copy_len;
212*9739f5f9SChristian Marangi 	bool src_align, dst_align;
213*9739f5f9SChristian Marangi 	int err = -EINVAL;
214*9739f5f9SChristian Marangi 
215*9739f5f9SChristian Marangi 	if (!IS_CTR(rctx->flags)) {
216*9739f5f9SChristian Marangi 		if (!IS_ALIGNED(textsize, blksize))
217*9739f5f9SChristian Marangi 			return err;
218*9739f5f9SChristian Marangi 	}
219*9739f5f9SChristian Marangi 
220*9739f5f9SChristian Marangi 	if (authsize) {
221*9739f5f9SChristian Marangi 		if (IS_ENCRYPT(rctx->flags))
222*9739f5f9SChristian Marangi 			totlen_dst += authsize;
223*9739f5f9SChristian Marangi 		else
224*9739f5f9SChristian Marangi 			totlen_src += authsize;
225*9739f5f9SChristian Marangi 	}
226*9739f5f9SChristian Marangi 
227*9739f5f9SChristian Marangi 	src_nents = sg_nents_for_len(src, totlen_src);
228*9739f5f9SChristian Marangi 	dst_nents = sg_nents_for_len(dst, totlen_dst);
229*9739f5f9SChristian Marangi 
230*9739f5f9SChristian Marangi 	if (src == dst) {
231*9739f5f9SChristian Marangi 		src_nents = max(src_nents, dst_nents);
232*9739f5f9SChristian Marangi 		dst_nents = src_nents;
233*9739f5f9SChristian Marangi 		if (unlikely((totlen_src || totlen_dst) && src_nents <= 0))
234*9739f5f9SChristian Marangi 			return err;
235*9739f5f9SChristian Marangi 
236*9739f5f9SChristian Marangi 	} else {
237*9739f5f9SChristian Marangi 		if (unlikely(totlen_src && src_nents <= 0))
238*9739f5f9SChristian Marangi 			return err;
239*9739f5f9SChristian Marangi 
240*9739f5f9SChristian Marangi 		if (unlikely(totlen_dst && dst_nents <= 0))
241*9739f5f9SChristian Marangi 			return err;
242*9739f5f9SChristian Marangi 	}
243*9739f5f9SChristian Marangi 
244*9739f5f9SChristian Marangi 	if (authsize) {
245*9739f5f9SChristian Marangi 		if (dst_nents == 1 && src_nents == 1) {
246*9739f5f9SChristian Marangi 			src_align = eip93_is_sg_aligned(src, totlen_src, blksize);
247*9739f5f9SChristian Marangi 			if (src ==  dst)
248*9739f5f9SChristian Marangi 				dst_align = src_align;
249*9739f5f9SChristian Marangi 			else
250*9739f5f9SChristian Marangi 				dst_align = eip93_is_sg_aligned(dst, totlen_dst, blksize);
251*9739f5f9SChristian Marangi 		} else {
252*9739f5f9SChristian Marangi 			src_align = false;
253*9739f5f9SChristian Marangi 			dst_align = false;
254*9739f5f9SChristian Marangi 		}
255*9739f5f9SChristian Marangi 	} else {
256*9739f5f9SChristian Marangi 		src_align = eip93_is_sg_aligned(src, totlen_src, blksize);
257*9739f5f9SChristian Marangi 		if (src == dst)
258*9739f5f9SChristian Marangi 			dst_align = src_align;
259*9739f5f9SChristian Marangi 		else
260*9739f5f9SChristian Marangi 			dst_align = eip93_is_sg_aligned(dst, totlen_dst, blksize);
261*9739f5f9SChristian Marangi 	}
262*9739f5f9SChristian Marangi 
263*9739f5f9SChristian Marangi 	copy_len = max(totlen_src, totlen_dst);
264*9739f5f9SChristian Marangi 	if (!src_align) {
265*9739f5f9SChristian Marangi 		err = eip93_make_sg_copy(src, &rctx->sg_src, copy_len, true);
266*9739f5f9SChristian Marangi 		if (err)
267*9739f5f9SChristian Marangi 			return err;
268*9739f5f9SChristian Marangi 	}
269*9739f5f9SChristian Marangi 
270*9739f5f9SChristian Marangi 	if (!dst_align) {
271*9739f5f9SChristian Marangi 		err = eip93_make_sg_copy(dst, &rctx->sg_dst, copy_len, false);
272*9739f5f9SChristian Marangi 		if (err)
273*9739f5f9SChristian Marangi 			return err;
274*9739f5f9SChristian Marangi 	}
275*9739f5f9SChristian Marangi 
276*9739f5f9SChristian Marangi 	rctx->src_nents = sg_nents_for_len(rctx->sg_src, totlen_src);
277*9739f5f9SChristian Marangi 	rctx->dst_nents = sg_nents_for_len(rctx->sg_dst, totlen_dst);
278*9739f5f9SChristian Marangi 
279*9739f5f9SChristian Marangi 	return 0;
280*9739f5f9SChristian Marangi }
281*9739f5f9SChristian Marangi 
282*9739f5f9SChristian Marangi /*
283*9739f5f9SChristian Marangi  * Set sa_record function:
284*9739f5f9SChristian Marangi  * Even sa_record is set to "0", keep " = 0" for readability.
285*9739f5f9SChristian Marangi  */
286*9739f5f9SChristian Marangi void eip93_set_sa_record(struct sa_record *sa_record, const unsigned int keylen,
287*9739f5f9SChristian Marangi 			 const u32 flags)
288*9739f5f9SChristian Marangi {
289*9739f5f9SChristian Marangi 	/* Reset cmd word */
290*9739f5f9SChristian Marangi 	sa_record->sa_cmd0_word = 0;
291*9739f5f9SChristian Marangi 	sa_record->sa_cmd1_word = 0;
292*9739f5f9SChristian Marangi 
293*9739f5f9SChristian Marangi 	sa_record->sa_cmd0_word |= EIP93_SA_CMD_IV_FROM_STATE;
294*9739f5f9SChristian Marangi 	if (!IS_ECB(flags))
295*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_SAVE_IV;
296*9739f5f9SChristian Marangi 
297*9739f5f9SChristian Marangi 	sa_record->sa_cmd0_word |= EIP93_SA_CMD_OP_BASIC;
298*9739f5f9SChristian Marangi 
299*9739f5f9SChristian Marangi 	switch ((flags & EIP93_ALG_MASK)) {
300*9739f5f9SChristian Marangi 	case EIP93_ALG_AES:
301*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_AES;
302*9739f5f9SChristian Marangi 		sa_record->sa_cmd1_word |= FIELD_PREP(EIP93_SA_CMD_AES_KEY_LENGTH,
303*9739f5f9SChristian Marangi 						      keylen >> 3);
304*9739f5f9SChristian Marangi 		break;
305*9739f5f9SChristian Marangi 	case EIP93_ALG_3DES:
306*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_3DES;
307*9739f5f9SChristian Marangi 		break;
308*9739f5f9SChristian Marangi 	case EIP93_ALG_DES:
309*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_DES;
310*9739f5f9SChristian Marangi 		break;
311*9739f5f9SChristian Marangi 	default:
312*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_NULL;
313*9739f5f9SChristian Marangi 	}
314*9739f5f9SChristian Marangi 
315*9739f5f9SChristian Marangi 	switch ((flags & EIP93_HASH_MASK)) {
316*9739f5f9SChristian Marangi 	case EIP93_HASH_SHA256:
317*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_SHA256;
318*9739f5f9SChristian Marangi 		break;
319*9739f5f9SChristian Marangi 	case EIP93_HASH_SHA224:
320*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_SHA224;
321*9739f5f9SChristian Marangi 		break;
322*9739f5f9SChristian Marangi 	case EIP93_HASH_SHA1:
323*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_SHA1;
324*9739f5f9SChristian Marangi 		break;
325*9739f5f9SChristian Marangi 	case EIP93_HASH_MD5:
326*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_MD5;
327*9739f5f9SChristian Marangi 		break;
328*9739f5f9SChristian Marangi 	default:
329*9739f5f9SChristian Marangi 		sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_NULL;
330*9739f5f9SChristian Marangi 	}
331*9739f5f9SChristian Marangi 
332*9739f5f9SChristian Marangi 	sa_record->sa_cmd0_word |= EIP93_SA_CMD_PAD_ZERO;
333*9739f5f9SChristian Marangi 
334*9739f5f9SChristian Marangi 	switch ((flags & EIP93_MODE_MASK)) {
335*9739f5f9SChristian Marangi 	case EIP93_MODE_CBC:
336*9739f5f9SChristian Marangi 		sa_record->sa_cmd1_word |= EIP93_SA_CMD_CHIPER_MODE_CBC;
337*9739f5f9SChristian Marangi 		break;
338*9739f5f9SChristian Marangi 	case EIP93_MODE_CTR:
339*9739f5f9SChristian Marangi 		sa_record->sa_cmd1_word |= EIP93_SA_CMD_CHIPER_MODE_CTR;
340*9739f5f9SChristian Marangi 		break;
341*9739f5f9SChristian Marangi 	case EIP93_MODE_ECB:
342*9739f5f9SChristian Marangi 		sa_record->sa_cmd1_word |= EIP93_SA_CMD_CHIPER_MODE_ECB;
343*9739f5f9SChristian Marangi 		break;
344*9739f5f9SChristian Marangi 	}
345*9739f5f9SChristian Marangi 
346*9739f5f9SChristian Marangi 	sa_record->sa_cmd0_word |= EIP93_SA_CMD_DIGEST_3WORD;
347*9739f5f9SChristian Marangi 	if (IS_HASH(flags)) {
348*9739f5f9SChristian Marangi 		sa_record->sa_cmd1_word |= EIP93_SA_CMD_COPY_PAD;
349*9739f5f9SChristian Marangi 		sa_record->sa_cmd1_word |= EIP93_SA_CMD_COPY_DIGEST;
350*9739f5f9SChristian Marangi 	}
351*9739f5f9SChristian Marangi 
352*9739f5f9SChristian Marangi 	if (IS_HMAC(flags)) {
353*9739f5f9SChristian Marangi 		sa_record->sa_cmd1_word |= EIP93_SA_CMD_HMAC;
354*9739f5f9SChristian Marangi 		sa_record->sa_cmd1_word |= EIP93_SA_CMD_COPY_HEADER;
355*9739f5f9SChristian Marangi 	}
356*9739f5f9SChristian Marangi 
357*9739f5f9SChristian Marangi 	sa_record->sa_spi = 0x0;
358*9739f5f9SChristian Marangi 	sa_record->sa_seqmum_mask[0] = 0xFFFFFFFF;
359*9739f5f9SChristian Marangi 	sa_record->sa_seqmum_mask[1] = 0x0;
360*9739f5f9SChristian Marangi }
361*9739f5f9SChristian Marangi 
362*9739f5f9SChristian Marangi /*
363*9739f5f9SChristian Marangi  * Poor mans Scatter/gather function:
364*9739f5f9SChristian Marangi  * Create a Descriptor for every segment to avoid copying buffers.
365*9739f5f9SChristian Marangi  * For performance better to wait for hardware to perform multiple DMA
366*9739f5f9SChristian Marangi  */
367*9739f5f9SChristian Marangi static int eip93_scatter_combine(struct eip93_device *eip93,
368*9739f5f9SChristian Marangi 				 struct eip93_cipher_reqctx *rctx,
369*9739f5f9SChristian Marangi 				 u32 datalen, u32 split, int offsetin)
370*9739f5f9SChristian Marangi {
371*9739f5f9SChristian Marangi 	struct eip93_descriptor *cdesc = rctx->cdesc;
372*9739f5f9SChristian Marangi 	struct scatterlist *sgsrc = rctx->sg_src;
373*9739f5f9SChristian Marangi 	struct scatterlist *sgdst = rctx->sg_dst;
374*9739f5f9SChristian Marangi 	unsigned int remainin = sg_dma_len(sgsrc);
375*9739f5f9SChristian Marangi 	unsigned int remainout = sg_dma_len(sgdst);
376*9739f5f9SChristian Marangi 	dma_addr_t saddr = sg_dma_address(sgsrc);
377*9739f5f9SChristian Marangi 	dma_addr_t daddr = sg_dma_address(sgdst);
378*9739f5f9SChristian Marangi 	dma_addr_t state_addr;
379*9739f5f9SChristian Marangi 	u32 src_addr, dst_addr, len, n;
380*9739f5f9SChristian Marangi 	bool nextin = false;
381*9739f5f9SChristian Marangi 	bool nextout = false;
382*9739f5f9SChristian Marangi 	int offsetout = 0;
383*9739f5f9SChristian Marangi 	int err;
384*9739f5f9SChristian Marangi 
385*9739f5f9SChristian Marangi 	if (IS_ECB(rctx->flags))
386*9739f5f9SChristian Marangi 		rctx->sa_state_base = 0;
387*9739f5f9SChristian Marangi 
388*9739f5f9SChristian Marangi 	if (split < datalen) {
389*9739f5f9SChristian Marangi 		state_addr = rctx->sa_state_ctr_base;
390*9739f5f9SChristian Marangi 		n = split;
391*9739f5f9SChristian Marangi 	} else {
392*9739f5f9SChristian Marangi 		state_addr = rctx->sa_state_base;
393*9739f5f9SChristian Marangi 		n = datalen;
394*9739f5f9SChristian Marangi 	}
395*9739f5f9SChristian Marangi 
396*9739f5f9SChristian Marangi 	do {
397*9739f5f9SChristian Marangi 		if (nextin) {
398*9739f5f9SChristian Marangi 			sgsrc = sg_next(sgsrc);
399*9739f5f9SChristian Marangi 			remainin = sg_dma_len(sgsrc);
400*9739f5f9SChristian Marangi 			if (remainin == 0)
401*9739f5f9SChristian Marangi 				continue;
402*9739f5f9SChristian Marangi 
403*9739f5f9SChristian Marangi 			saddr = sg_dma_address(sgsrc);
404*9739f5f9SChristian Marangi 			offsetin = 0;
405*9739f5f9SChristian Marangi 			nextin = false;
406*9739f5f9SChristian Marangi 		}
407*9739f5f9SChristian Marangi 
408*9739f5f9SChristian Marangi 		if (nextout) {
409*9739f5f9SChristian Marangi 			sgdst = sg_next(sgdst);
410*9739f5f9SChristian Marangi 			remainout = sg_dma_len(sgdst);
411*9739f5f9SChristian Marangi 			if (remainout == 0)
412*9739f5f9SChristian Marangi 				continue;
413*9739f5f9SChristian Marangi 
414*9739f5f9SChristian Marangi 			daddr = sg_dma_address(sgdst);
415*9739f5f9SChristian Marangi 			offsetout = 0;
416*9739f5f9SChristian Marangi 			nextout = false;
417*9739f5f9SChristian Marangi 		}
418*9739f5f9SChristian Marangi 		src_addr = saddr + offsetin;
419*9739f5f9SChristian Marangi 		dst_addr = daddr + offsetout;
420*9739f5f9SChristian Marangi 
421*9739f5f9SChristian Marangi 		if (remainin == remainout) {
422*9739f5f9SChristian Marangi 			len = remainin;
423*9739f5f9SChristian Marangi 			if (len > n) {
424*9739f5f9SChristian Marangi 				len = n;
425*9739f5f9SChristian Marangi 				remainin -= n;
426*9739f5f9SChristian Marangi 				remainout -= n;
427*9739f5f9SChristian Marangi 				offsetin += n;
428*9739f5f9SChristian Marangi 				offsetout += n;
429*9739f5f9SChristian Marangi 			} else {
430*9739f5f9SChristian Marangi 				nextin = true;
431*9739f5f9SChristian Marangi 				nextout = true;
432*9739f5f9SChristian Marangi 			}
433*9739f5f9SChristian Marangi 		} else if (remainin < remainout) {
434*9739f5f9SChristian Marangi 			len = remainin;
435*9739f5f9SChristian Marangi 			if (len > n) {
436*9739f5f9SChristian Marangi 				len = n;
437*9739f5f9SChristian Marangi 				remainin -= n;
438*9739f5f9SChristian Marangi 				remainout -= n;
439*9739f5f9SChristian Marangi 				offsetin += n;
440*9739f5f9SChristian Marangi 				offsetout += n;
441*9739f5f9SChristian Marangi 			} else {
442*9739f5f9SChristian Marangi 				offsetout += len;
443*9739f5f9SChristian Marangi 				remainout -= len;
444*9739f5f9SChristian Marangi 				nextin = true;
445*9739f5f9SChristian Marangi 			}
446*9739f5f9SChristian Marangi 		} else {
447*9739f5f9SChristian Marangi 			len = remainout;
448*9739f5f9SChristian Marangi 			if (len > n) {
449*9739f5f9SChristian Marangi 				len = n;
450*9739f5f9SChristian Marangi 				remainin -= n;
451*9739f5f9SChristian Marangi 				remainout -= n;
452*9739f5f9SChristian Marangi 				offsetin += n;
453*9739f5f9SChristian Marangi 				offsetout += n;
454*9739f5f9SChristian Marangi 			} else {
455*9739f5f9SChristian Marangi 				offsetin += len;
456*9739f5f9SChristian Marangi 				remainin -= len;
457*9739f5f9SChristian Marangi 				nextout = true;
458*9739f5f9SChristian Marangi 			}
459*9739f5f9SChristian Marangi 		}
460*9739f5f9SChristian Marangi 		n -= len;
461*9739f5f9SChristian Marangi 
462*9739f5f9SChristian Marangi 		cdesc->src_addr = src_addr;
463*9739f5f9SChristian Marangi 		cdesc->dst_addr = dst_addr;
464*9739f5f9SChristian Marangi 		cdesc->state_addr = state_addr;
465*9739f5f9SChristian Marangi 		cdesc->pe_length_word = FIELD_PREP(EIP93_PE_LENGTH_HOST_PE_READY,
466*9739f5f9SChristian Marangi 						   EIP93_PE_LENGTH_HOST_READY);
467*9739f5f9SChristian Marangi 		cdesc->pe_length_word |= FIELD_PREP(EIP93_PE_LENGTH_LENGTH, len);
468*9739f5f9SChristian Marangi 
469*9739f5f9SChristian Marangi 		if (n == 0) {
470*9739f5f9SChristian Marangi 			n = datalen - split;
471*9739f5f9SChristian Marangi 			split = datalen;
472*9739f5f9SChristian Marangi 			state_addr = rctx->sa_state_base;
473*9739f5f9SChristian Marangi 		}
474*9739f5f9SChristian Marangi 
475*9739f5f9SChristian Marangi 		if (n == 0)
476*9739f5f9SChristian Marangi 			cdesc->user_id |= FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS,
477*9739f5f9SChristian Marangi 						     EIP93_DESC_LAST);
478*9739f5f9SChristian Marangi 
479*9739f5f9SChristian Marangi 		/*
480*9739f5f9SChristian Marangi 		 * Loop - Delay - No need to rollback
481*9739f5f9SChristian Marangi 		 * Maybe refine by slowing down at EIP93_RING_BUSY
482*9739f5f9SChristian Marangi 		 */
483*9739f5f9SChristian Marangi again:
484*9739f5f9SChristian Marangi 		scoped_guard(spinlock_irqsave, &eip93->ring->write_lock)
485*9739f5f9SChristian Marangi 			err = eip93_put_descriptor(eip93, cdesc);
486*9739f5f9SChristian Marangi 		if (err) {
487*9739f5f9SChristian Marangi 			usleep_range(EIP93_RING_BUSY_DELAY,
488*9739f5f9SChristian Marangi 				     EIP93_RING_BUSY_DELAY * 2);
489*9739f5f9SChristian Marangi 			goto again;
490*9739f5f9SChristian Marangi 		}
491*9739f5f9SChristian Marangi 		/* Writing new descriptor count starts DMA action */
492*9739f5f9SChristian Marangi 		writel(1, eip93->base + EIP93_REG_PE_CD_COUNT);
493*9739f5f9SChristian Marangi 	} while (n);
494*9739f5f9SChristian Marangi 
495*9739f5f9SChristian Marangi 	return -EINPROGRESS;
496*9739f5f9SChristian Marangi }
497*9739f5f9SChristian Marangi 
498*9739f5f9SChristian Marangi int eip93_send_req(struct crypto_async_request *async,
499*9739f5f9SChristian Marangi 		   const u8 *reqiv, struct eip93_cipher_reqctx *rctx)
500*9739f5f9SChristian Marangi {
501*9739f5f9SChristian Marangi 	struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm);
502*9739f5f9SChristian Marangi 	struct eip93_device *eip93 = ctx->eip93;
503*9739f5f9SChristian Marangi 	struct scatterlist *src = rctx->sg_src;
504*9739f5f9SChristian Marangi 	struct scatterlist *dst = rctx->sg_dst;
505*9739f5f9SChristian Marangi 	struct sa_state *sa_state;
506*9739f5f9SChristian Marangi 	struct eip93_descriptor cdesc;
507*9739f5f9SChristian Marangi 	u32 flags = rctx->flags;
508*9739f5f9SChristian Marangi 	int offsetin = 0, err;
509*9739f5f9SChristian Marangi 	u32 datalen = rctx->assoclen + rctx->textsize;
510*9739f5f9SChristian Marangi 	u32 split = datalen;
511*9739f5f9SChristian Marangi 	u32 start, end, ctr, blocks;
512*9739f5f9SChristian Marangi 	u32 iv[AES_BLOCK_SIZE / sizeof(u32)];
513*9739f5f9SChristian Marangi 	int crypto_async_idr;
514*9739f5f9SChristian Marangi 
515*9739f5f9SChristian Marangi 	rctx->sa_state_ctr = NULL;
516*9739f5f9SChristian Marangi 	rctx->sa_state = NULL;
517*9739f5f9SChristian Marangi 
518*9739f5f9SChristian Marangi 	if (IS_ECB(flags))
519*9739f5f9SChristian Marangi 		goto skip_iv;
520*9739f5f9SChristian Marangi 
521*9739f5f9SChristian Marangi 	memcpy(iv, reqiv, rctx->ivsize);
522*9739f5f9SChristian Marangi 
523*9739f5f9SChristian Marangi 	rctx->sa_state = kzalloc(sizeof(*rctx->sa_state), GFP_KERNEL);
524*9739f5f9SChristian Marangi 	if (!rctx->sa_state)
525*9739f5f9SChristian Marangi 		return -ENOMEM;
526*9739f5f9SChristian Marangi 
527*9739f5f9SChristian Marangi 	sa_state = rctx->sa_state;
528*9739f5f9SChristian Marangi 
529*9739f5f9SChristian Marangi 	memcpy(sa_state->state_iv, iv, rctx->ivsize);
530*9739f5f9SChristian Marangi 	if (IS_RFC3686(flags)) {
531*9739f5f9SChristian Marangi 		sa_state->state_iv[0] = ctx->sa_nonce;
532*9739f5f9SChristian Marangi 		sa_state->state_iv[1] = iv[0];
533*9739f5f9SChristian Marangi 		sa_state->state_iv[2] = iv[1];
534*9739f5f9SChristian Marangi 		sa_state->state_iv[3] = (u32 __force)cpu_to_be32(0x1);
535*9739f5f9SChristian Marangi 	} else if (!IS_HMAC(flags) && IS_CTR(flags)) {
536*9739f5f9SChristian Marangi 		/* Compute data length. */
537*9739f5f9SChristian Marangi 		blocks = DIV_ROUND_UP(rctx->textsize, AES_BLOCK_SIZE);
538*9739f5f9SChristian Marangi 		ctr = be32_to_cpu((__be32 __force)iv[3]);
539*9739f5f9SChristian Marangi 		/* Check 32bit counter overflow. */
540*9739f5f9SChristian Marangi 		start = ctr;
541*9739f5f9SChristian Marangi 		end = start + blocks - 1;
542*9739f5f9SChristian Marangi 		if (end < start) {
543*9739f5f9SChristian Marangi 			split = AES_BLOCK_SIZE * -start;
544*9739f5f9SChristian Marangi 			/*
545*9739f5f9SChristian Marangi 			 * Increment the counter manually to cope with
546*9739f5f9SChristian Marangi 			 * the hardware counter overflow.
547*9739f5f9SChristian Marangi 			 */
548*9739f5f9SChristian Marangi 			iv[3] = 0xffffffff;
549*9739f5f9SChristian Marangi 			crypto_inc((u8 *)iv, AES_BLOCK_SIZE);
550*9739f5f9SChristian Marangi 
551*9739f5f9SChristian Marangi 			rctx->sa_state_ctr = kzalloc(sizeof(*rctx->sa_state_ctr),
552*9739f5f9SChristian Marangi 						     GFP_KERNEL);
553*9739f5f9SChristian Marangi 			if (!rctx->sa_state_ctr) {
554*9739f5f9SChristian Marangi 				err = -ENOMEM;
555*9739f5f9SChristian Marangi 				goto free_sa_state;
556*9739f5f9SChristian Marangi 			}
557*9739f5f9SChristian Marangi 
558*9739f5f9SChristian Marangi 			memcpy(rctx->sa_state_ctr->state_iv, reqiv, rctx->ivsize);
559*9739f5f9SChristian Marangi 			memcpy(sa_state->state_iv, iv, rctx->ivsize);
560*9739f5f9SChristian Marangi 
561*9739f5f9SChristian Marangi 			rctx->sa_state_ctr_base = dma_map_single(eip93->dev, rctx->sa_state_ctr,
562*9739f5f9SChristian Marangi 								 sizeof(*rctx->sa_state_ctr),
563*9739f5f9SChristian Marangi 								 DMA_TO_DEVICE);
564*9739f5f9SChristian Marangi 			err = dma_mapping_error(eip93->dev, rctx->sa_state_ctr_base);
565*9739f5f9SChristian Marangi 			if (err)
566*9739f5f9SChristian Marangi 				goto free_sa_state_ctr;
567*9739f5f9SChristian Marangi 		}
568*9739f5f9SChristian Marangi 	}
569*9739f5f9SChristian Marangi 
570*9739f5f9SChristian Marangi 	rctx->sa_state_base = dma_map_single(eip93->dev, rctx->sa_state,
571*9739f5f9SChristian Marangi 					     sizeof(*rctx->sa_state), DMA_TO_DEVICE);
572*9739f5f9SChristian Marangi 	err = dma_mapping_error(eip93->dev, rctx->sa_state_base);
573*9739f5f9SChristian Marangi 	if (err)
574*9739f5f9SChristian Marangi 		goto free_sa_state_ctr_dma;
575*9739f5f9SChristian Marangi 
576*9739f5f9SChristian Marangi skip_iv:
577*9739f5f9SChristian Marangi 
578*9739f5f9SChristian Marangi 	cdesc.pe_ctrl_stat_word = FIELD_PREP(EIP93_PE_CTRL_PE_READY_DES_TRING_OWN,
579*9739f5f9SChristian Marangi 					     EIP93_PE_CTRL_HOST_READY);
580*9739f5f9SChristian Marangi 	cdesc.sa_addr = rctx->sa_record_base;
581*9739f5f9SChristian Marangi 	cdesc.arc4_addr = 0;
582*9739f5f9SChristian Marangi 
583*9739f5f9SChristian Marangi 	scoped_guard(spinlock_bh, &eip93->ring->idr_lock)
584*9739f5f9SChristian Marangi 		crypto_async_idr = idr_alloc(&eip93->ring->crypto_async_idr, async, 0,
585*9739f5f9SChristian Marangi 					     EIP93_RING_NUM - 1, GFP_ATOMIC);
586*9739f5f9SChristian Marangi 
587*9739f5f9SChristian Marangi 	cdesc.user_id = FIELD_PREP(EIP93_PE_USER_ID_CRYPTO_IDR, (u16)crypto_async_idr) |
588*9739f5f9SChristian Marangi 			FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, rctx->desc_flags);
589*9739f5f9SChristian Marangi 
590*9739f5f9SChristian Marangi 	rctx->cdesc = &cdesc;
591*9739f5f9SChristian Marangi 
592*9739f5f9SChristian Marangi 	/* map DMA_BIDIRECTIONAL to invalidate cache on destination
593*9739f5f9SChristian Marangi 	 * implies __dma_cache_wback_inv
594*9739f5f9SChristian Marangi 	 */
595*9739f5f9SChristian Marangi 	if (!dma_map_sg(eip93->dev, dst, rctx->dst_nents, DMA_BIDIRECTIONAL)) {
596*9739f5f9SChristian Marangi 		err = -ENOMEM;
597*9739f5f9SChristian Marangi 		goto free_sa_state_ctr_dma;
598*9739f5f9SChristian Marangi 	}
599*9739f5f9SChristian Marangi 
600*9739f5f9SChristian Marangi 	if (src != dst &&
601*9739f5f9SChristian Marangi 	    !dma_map_sg(eip93->dev, src, rctx->src_nents, DMA_TO_DEVICE)) {
602*9739f5f9SChristian Marangi 		err = -ENOMEM;
603*9739f5f9SChristian Marangi 		goto free_sg_dma;
604*9739f5f9SChristian Marangi 	}
605*9739f5f9SChristian Marangi 
606*9739f5f9SChristian Marangi 	return eip93_scatter_combine(eip93, rctx, datalen, split, offsetin);
607*9739f5f9SChristian Marangi 
608*9739f5f9SChristian Marangi free_sg_dma:
609*9739f5f9SChristian Marangi 	dma_unmap_sg(eip93->dev, dst, rctx->dst_nents, DMA_BIDIRECTIONAL);
610*9739f5f9SChristian Marangi free_sa_state_ctr_dma:
611*9739f5f9SChristian Marangi 	if (rctx->sa_state_ctr)
612*9739f5f9SChristian Marangi 		dma_unmap_single(eip93->dev, rctx->sa_state_ctr_base,
613*9739f5f9SChristian Marangi 				 sizeof(*rctx->sa_state_ctr),
614*9739f5f9SChristian Marangi 				 DMA_TO_DEVICE);
615*9739f5f9SChristian Marangi free_sa_state_ctr:
616*9739f5f9SChristian Marangi 	kfree(rctx->sa_state_ctr);
617*9739f5f9SChristian Marangi 	if (rctx->sa_state)
618*9739f5f9SChristian Marangi 		dma_unmap_single(eip93->dev, rctx->sa_state_base,
619*9739f5f9SChristian Marangi 				 sizeof(*rctx->sa_state),
620*9739f5f9SChristian Marangi 				 DMA_TO_DEVICE);
621*9739f5f9SChristian Marangi free_sa_state:
622*9739f5f9SChristian Marangi 	kfree(rctx->sa_state);
623*9739f5f9SChristian Marangi 
624*9739f5f9SChristian Marangi 	return err;
625*9739f5f9SChristian Marangi }
626*9739f5f9SChristian Marangi 
627*9739f5f9SChristian Marangi void eip93_unmap_dma(struct eip93_device *eip93, struct eip93_cipher_reqctx *rctx,
628*9739f5f9SChristian Marangi 		     struct scatterlist *reqsrc, struct scatterlist *reqdst)
629*9739f5f9SChristian Marangi {
630*9739f5f9SChristian Marangi 	u32 len = rctx->assoclen + rctx->textsize;
631*9739f5f9SChristian Marangi 	u32 authsize = rctx->authsize;
632*9739f5f9SChristian Marangi 	u32 flags = rctx->flags;
633*9739f5f9SChristian Marangi 	u32 *otag;
634*9739f5f9SChristian Marangi 	int i;
635*9739f5f9SChristian Marangi 
636*9739f5f9SChristian Marangi 	if (rctx->sg_src == rctx->sg_dst) {
637*9739f5f9SChristian Marangi 		dma_unmap_sg(eip93->dev, rctx->sg_dst, rctx->dst_nents,
638*9739f5f9SChristian Marangi 			     DMA_BIDIRECTIONAL);
639*9739f5f9SChristian Marangi 		goto process_tag;
640*9739f5f9SChristian Marangi 	}
641*9739f5f9SChristian Marangi 
642*9739f5f9SChristian Marangi 	dma_unmap_sg(eip93->dev, rctx->sg_src, rctx->src_nents,
643*9739f5f9SChristian Marangi 		     DMA_TO_DEVICE);
644*9739f5f9SChristian Marangi 
645*9739f5f9SChristian Marangi 	if (rctx->sg_src != reqsrc)
646*9739f5f9SChristian Marangi 		eip93_free_sg_copy(len +  rctx->authsize, &rctx->sg_src);
647*9739f5f9SChristian Marangi 
648*9739f5f9SChristian Marangi 	dma_unmap_sg(eip93->dev, rctx->sg_dst, rctx->dst_nents,
649*9739f5f9SChristian Marangi 		     DMA_BIDIRECTIONAL);
650*9739f5f9SChristian Marangi 
651*9739f5f9SChristian Marangi 	/* SHA tags need conversion from net-to-host */
652*9739f5f9SChristian Marangi process_tag:
653*9739f5f9SChristian Marangi 	if (IS_DECRYPT(flags))
654*9739f5f9SChristian Marangi 		authsize = 0;
655*9739f5f9SChristian Marangi 
656*9739f5f9SChristian Marangi 	if (authsize) {
657*9739f5f9SChristian Marangi 		if (!IS_HASH_MD5(flags)) {
658*9739f5f9SChristian Marangi 			otag = sg_virt(rctx->sg_dst) + len;
659*9739f5f9SChristian Marangi 			for (i = 0; i < (authsize / 4); i++)
660*9739f5f9SChristian Marangi 				otag[i] = be32_to_cpu((__be32 __force)otag[i]);
661*9739f5f9SChristian Marangi 		}
662*9739f5f9SChristian Marangi 	}
663*9739f5f9SChristian Marangi 
664*9739f5f9SChristian Marangi 	if (rctx->sg_dst != reqdst) {
665*9739f5f9SChristian Marangi 		sg_copy_from_buffer(reqdst, sg_nents(reqdst),
666*9739f5f9SChristian Marangi 				    sg_virt(rctx->sg_dst), len + authsize);
667*9739f5f9SChristian Marangi 		eip93_free_sg_copy(len + rctx->authsize, &rctx->sg_dst);
668*9739f5f9SChristian Marangi 	}
669*9739f5f9SChristian Marangi }
670*9739f5f9SChristian Marangi 
671*9739f5f9SChristian Marangi void eip93_handle_result(struct eip93_device *eip93, struct eip93_cipher_reqctx *rctx,
672*9739f5f9SChristian Marangi 			 u8 *reqiv)
673*9739f5f9SChristian Marangi {
674*9739f5f9SChristian Marangi 	if (rctx->sa_state_ctr)
675*9739f5f9SChristian Marangi 		dma_unmap_single(eip93->dev, rctx->sa_state_ctr_base,
676*9739f5f9SChristian Marangi 				 sizeof(*rctx->sa_state_ctr),
677*9739f5f9SChristian Marangi 				 DMA_FROM_DEVICE);
678*9739f5f9SChristian Marangi 
679*9739f5f9SChristian Marangi 	if (rctx->sa_state)
680*9739f5f9SChristian Marangi 		dma_unmap_single(eip93->dev, rctx->sa_state_base,
681*9739f5f9SChristian Marangi 				 sizeof(*rctx->sa_state),
682*9739f5f9SChristian Marangi 				 DMA_FROM_DEVICE);
683*9739f5f9SChristian Marangi 
684*9739f5f9SChristian Marangi 	if (!IS_ECB(rctx->flags))
685*9739f5f9SChristian Marangi 		memcpy(reqiv, rctx->sa_state->state_iv, rctx->ivsize);
686*9739f5f9SChristian Marangi 
687*9739f5f9SChristian Marangi 	kfree(rctx->sa_state_ctr);
688*9739f5f9SChristian Marangi 	kfree(rctx->sa_state);
689*9739f5f9SChristian Marangi }
690*9739f5f9SChristian Marangi 
691*9739f5f9SChristian Marangi int eip93_hmac_setkey(u32 ctx_flags, const u8 *key, unsigned int keylen,
692*9739f5f9SChristian Marangi 		      unsigned int hashlen, u8 *dest_ipad, u8 *dest_opad,
693*9739f5f9SChristian Marangi 		      bool skip_ipad)
694*9739f5f9SChristian Marangi {
695*9739f5f9SChristian Marangi 	u8 ipad[SHA256_BLOCK_SIZE], opad[SHA256_BLOCK_SIZE];
696*9739f5f9SChristian Marangi 	struct crypto_ahash *ahash_tfm;
697*9739f5f9SChristian Marangi 	struct eip93_hash_reqctx *rctx;
698*9739f5f9SChristian Marangi 	struct ahash_request *req;
699*9739f5f9SChristian Marangi 	DECLARE_CRYPTO_WAIT(wait);
700*9739f5f9SChristian Marangi 	struct scatterlist sg[1];
701*9739f5f9SChristian Marangi 	const char *alg_name;
702*9739f5f9SChristian Marangi 	int i, ret;
703*9739f5f9SChristian Marangi 
704*9739f5f9SChristian Marangi 	switch (ctx_flags & EIP93_HASH_MASK) {
705*9739f5f9SChristian Marangi 	case EIP93_HASH_SHA256:
706*9739f5f9SChristian Marangi 		alg_name = "sha256-eip93";
707*9739f5f9SChristian Marangi 		break;
708*9739f5f9SChristian Marangi 	case EIP93_HASH_SHA224:
709*9739f5f9SChristian Marangi 		alg_name = "sha224-eip93";
710*9739f5f9SChristian Marangi 		break;
711*9739f5f9SChristian Marangi 	case EIP93_HASH_SHA1:
712*9739f5f9SChristian Marangi 		alg_name = "sha1-eip93";
713*9739f5f9SChristian Marangi 		break;
714*9739f5f9SChristian Marangi 	case EIP93_HASH_MD5:
715*9739f5f9SChristian Marangi 		alg_name = "md5-eip93";
716*9739f5f9SChristian Marangi 		break;
717*9739f5f9SChristian Marangi 	default: /* Impossible */
718*9739f5f9SChristian Marangi 		return -EINVAL;
719*9739f5f9SChristian Marangi 	}
720*9739f5f9SChristian Marangi 
721*9739f5f9SChristian Marangi 	ahash_tfm = crypto_alloc_ahash(alg_name, 0, CRYPTO_ALG_ASYNC);
722*9739f5f9SChristian Marangi 	if (IS_ERR(ahash_tfm))
723*9739f5f9SChristian Marangi 		return PTR_ERR(ahash_tfm);
724*9739f5f9SChristian Marangi 
725*9739f5f9SChristian Marangi 	req = ahash_request_alloc(ahash_tfm, GFP_ATOMIC);
726*9739f5f9SChristian Marangi 	if (!req) {
727*9739f5f9SChristian Marangi 		ret = -ENOMEM;
728*9739f5f9SChristian Marangi 		goto err_ahash;
729*9739f5f9SChristian Marangi 	}
730*9739f5f9SChristian Marangi 
731*9739f5f9SChristian Marangi 	rctx = ahash_request_ctx_dma(req);
732*9739f5f9SChristian Marangi 	crypto_init_wait(&wait);
733*9739f5f9SChristian Marangi 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
734*9739f5f9SChristian Marangi 				   crypto_req_done, &wait);
735*9739f5f9SChristian Marangi 
736*9739f5f9SChristian Marangi 	/* Hash the key if > SHA256_BLOCK_SIZE */
737*9739f5f9SChristian Marangi 	if (keylen > SHA256_BLOCK_SIZE) {
738*9739f5f9SChristian Marangi 		sg_init_one(&sg[0], key, keylen);
739*9739f5f9SChristian Marangi 
740*9739f5f9SChristian Marangi 		ahash_request_set_crypt(req, sg, ipad, keylen);
741*9739f5f9SChristian Marangi 		ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
742*9739f5f9SChristian Marangi 		if (ret)
743*9739f5f9SChristian Marangi 			goto err_req;
744*9739f5f9SChristian Marangi 
745*9739f5f9SChristian Marangi 		keylen = hashlen;
746*9739f5f9SChristian Marangi 	} else {
747*9739f5f9SChristian Marangi 		memcpy(ipad, key, keylen);
748*9739f5f9SChristian Marangi 	}
749*9739f5f9SChristian Marangi 
750*9739f5f9SChristian Marangi 	/* Copy to opad */
751*9739f5f9SChristian Marangi 	memset(ipad + keylen, 0, SHA256_BLOCK_SIZE - keylen);
752*9739f5f9SChristian Marangi 	memcpy(opad, ipad, SHA256_BLOCK_SIZE);
753*9739f5f9SChristian Marangi 
754*9739f5f9SChristian Marangi 	/* Pad with HMAC constants */
755*9739f5f9SChristian Marangi 	for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
756*9739f5f9SChristian Marangi 		ipad[i] ^= HMAC_IPAD_VALUE;
757*9739f5f9SChristian Marangi 		opad[i] ^= HMAC_OPAD_VALUE;
758*9739f5f9SChristian Marangi 	}
759*9739f5f9SChristian Marangi 
760*9739f5f9SChristian Marangi 	if (skip_ipad) {
761*9739f5f9SChristian Marangi 		memcpy(dest_ipad, ipad, SHA256_BLOCK_SIZE);
762*9739f5f9SChristian Marangi 	} else {
763*9739f5f9SChristian Marangi 		/* Hash ipad */
764*9739f5f9SChristian Marangi 		sg_init_one(&sg[0], ipad, SHA256_BLOCK_SIZE);
765*9739f5f9SChristian Marangi 		ahash_request_set_crypt(req, sg, dest_ipad, SHA256_BLOCK_SIZE);
766*9739f5f9SChristian Marangi 		ret = crypto_ahash_init(req);
767*9739f5f9SChristian Marangi 		if (ret)
768*9739f5f9SChristian Marangi 			goto err_req;
769*9739f5f9SChristian Marangi 
770*9739f5f9SChristian Marangi 		/* Disable HASH_FINALIZE for ipad hash */
771*9739f5f9SChristian Marangi 		rctx->partial_hash = true;
772*9739f5f9SChristian Marangi 
773*9739f5f9SChristian Marangi 		ret = crypto_wait_req(crypto_ahash_finup(req), &wait);
774*9739f5f9SChristian Marangi 		if (ret)
775*9739f5f9SChristian Marangi 			goto err_req;
776*9739f5f9SChristian Marangi 	}
777*9739f5f9SChristian Marangi 
778*9739f5f9SChristian Marangi 	/* Hash opad */
779*9739f5f9SChristian Marangi 	sg_init_one(&sg[0], opad, SHA256_BLOCK_SIZE);
780*9739f5f9SChristian Marangi 	ahash_request_set_crypt(req, sg, dest_opad, SHA256_BLOCK_SIZE);
781*9739f5f9SChristian Marangi 	ret = crypto_ahash_init(req);
782*9739f5f9SChristian Marangi 	if (ret)
783*9739f5f9SChristian Marangi 		goto err_req;
784*9739f5f9SChristian Marangi 
785*9739f5f9SChristian Marangi 	/* Disable HASH_FINALIZE for opad hash */
786*9739f5f9SChristian Marangi 	rctx->partial_hash = true;
787*9739f5f9SChristian Marangi 
788*9739f5f9SChristian Marangi 	ret = crypto_wait_req(crypto_ahash_finup(req), &wait);
789*9739f5f9SChristian Marangi 	if (ret)
790*9739f5f9SChristian Marangi 		goto err_req;
791*9739f5f9SChristian Marangi 
792*9739f5f9SChristian Marangi 	if (!IS_HASH_MD5(ctx_flags)) {
793*9739f5f9SChristian Marangi 		for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++) {
794*9739f5f9SChristian Marangi 			u32 *ipad_hash = (u32 *)dest_ipad;
795*9739f5f9SChristian Marangi 			u32 *opad_hash = (u32 *)dest_opad;
796*9739f5f9SChristian Marangi 
797*9739f5f9SChristian Marangi 			if (!skip_ipad)
798*9739f5f9SChristian Marangi 				ipad_hash[i] = (u32 __force)cpu_to_be32(ipad_hash[i]);
799*9739f5f9SChristian Marangi 			opad_hash[i] = (u32 __force)cpu_to_be32(opad_hash[i]);
800*9739f5f9SChristian Marangi 		}
801*9739f5f9SChristian Marangi 	}
802*9739f5f9SChristian Marangi 
803*9739f5f9SChristian Marangi err_req:
804*9739f5f9SChristian Marangi 	ahash_request_free(req);
805*9739f5f9SChristian Marangi err_ahash:
806*9739f5f9SChristian Marangi 	crypto_free_ahash(ahash_tfm);
807*9739f5f9SChristian Marangi 
808*9739f5f9SChristian Marangi 	return ret;
809*9739f5f9SChristian Marangi }
810