1915e4e84SJonathan Cameron // SPDX-License-Identifier: GPL-2.0
25377265fSHao Fang /* Copyright (c) 2016-2017 HiSilicon Limited. */
3915e4e84SJonathan Cameron #include <linux/crypto.h>
4915e4e84SJonathan Cameron #include <linux/dma-mapping.h>
5915e4e84SJonathan Cameron #include <linux/dmapool.h>
6915e4e84SJonathan Cameron #include <linux/module.h>
7915e4e84SJonathan Cameron #include <linux/mutex.h>
8915e4e84SJonathan Cameron #include <linux/slab.h>
9915e4e84SJonathan Cameron 
10915e4e84SJonathan Cameron #include <crypto/aes.h>
11915e4e84SJonathan Cameron #include <crypto/algapi.h>
12894b68d8SArd Biesheuvel #include <crypto/internal/des.h>
13915e4e84SJonathan Cameron #include <crypto/skcipher.h>
14915e4e84SJonathan Cameron #include <crypto/xts.h>
15915e4e84SJonathan Cameron #include <crypto/internal/skcipher.h>
16915e4e84SJonathan Cameron 
17915e4e84SJonathan Cameron #include "sec_drv.h"
18915e4e84SJonathan Cameron 
19915e4e84SJonathan Cameron #define SEC_MAX_CIPHER_KEY		64
20915e4e84SJonathan Cameron #define SEC_REQ_LIMIT SZ_32M
21915e4e84SJonathan Cameron 
22915e4e84SJonathan Cameron struct sec_c_alg_cfg {
23915e4e84SJonathan Cameron 	unsigned c_alg		: 3;
24915e4e84SJonathan Cameron 	unsigned c_mode		: 3;
25915e4e84SJonathan Cameron 	unsigned key_len	: 2;
26915e4e84SJonathan Cameron 	unsigned c_width	: 2;
27915e4e84SJonathan Cameron };
28915e4e84SJonathan Cameron 
29915e4e84SJonathan Cameron static const struct sec_c_alg_cfg sec_c_alg_cfgs[] =  {
30915e4e84SJonathan Cameron 	[SEC_C_DES_ECB_64] = {
31915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_DES,
32915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_ECB,
33915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_DES,
34915e4e84SJonathan Cameron 	},
35915e4e84SJonathan Cameron 	[SEC_C_DES_CBC_64] = {
36915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_DES,
37915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_CBC,
38915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_DES,
39915e4e84SJonathan Cameron 	},
40915e4e84SJonathan Cameron 	[SEC_C_3DES_ECB_192_3KEY] = {
41915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_3DES,
42915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_ECB,
43915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_3DES_3_KEY,
44915e4e84SJonathan Cameron 	},
45915e4e84SJonathan Cameron 	[SEC_C_3DES_ECB_192_2KEY] = {
46915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_3DES,
47915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_ECB,
48915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_3DES_2_KEY,
49915e4e84SJonathan Cameron 	},
50915e4e84SJonathan Cameron 	[SEC_C_3DES_CBC_192_3KEY] = {
51915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_3DES,
52915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_CBC,
53915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_3DES_3_KEY,
54915e4e84SJonathan Cameron 	},
55915e4e84SJonathan Cameron 	[SEC_C_3DES_CBC_192_2KEY] = {
56915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_3DES,
57915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_CBC,
58915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_3DES_2_KEY,
59915e4e84SJonathan Cameron 	},
60915e4e84SJonathan Cameron 	[SEC_C_AES_ECB_128] = {
61915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
62915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_ECB,
63915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_128,
64915e4e84SJonathan Cameron 	},
65915e4e84SJonathan Cameron 	[SEC_C_AES_ECB_192] = {
66915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
67915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_ECB,
68915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_192,
69915e4e84SJonathan Cameron 	},
70915e4e84SJonathan Cameron 	[SEC_C_AES_ECB_256] = {
71915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
72915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_ECB,
73915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_256,
74915e4e84SJonathan Cameron 	},
75915e4e84SJonathan Cameron 	[SEC_C_AES_CBC_128] = {
76915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
77915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_CBC,
78915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_128,
79915e4e84SJonathan Cameron 	},
80915e4e84SJonathan Cameron 	[SEC_C_AES_CBC_192] = {
81915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
82915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_CBC,
83915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_192,
84915e4e84SJonathan Cameron 	},
85915e4e84SJonathan Cameron 	[SEC_C_AES_CBC_256] = {
86915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
87915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_CBC,
88915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_256,
89915e4e84SJonathan Cameron 	},
90915e4e84SJonathan Cameron 	[SEC_C_AES_CTR_128] = {
91915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
92915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_CTR,
93915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_128,
94915e4e84SJonathan Cameron 	},
95915e4e84SJonathan Cameron 	[SEC_C_AES_CTR_192] = {
96915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
97915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_CTR,
98915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_192,
99915e4e84SJonathan Cameron 	},
100915e4e84SJonathan Cameron 	[SEC_C_AES_CTR_256] = {
101915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
102915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_CTR,
103915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_256,
104915e4e84SJonathan Cameron 	},
105915e4e84SJonathan Cameron 	[SEC_C_AES_XTS_128] = {
106915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
107915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_XTS,
108915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_128,
109915e4e84SJonathan Cameron 	},
110915e4e84SJonathan Cameron 	[SEC_C_AES_XTS_256] = {
111915e4e84SJonathan Cameron 		.c_alg = SEC_C_ALG_AES,
112915e4e84SJonathan Cameron 		.c_mode = SEC_C_MODE_XTS,
113915e4e84SJonathan Cameron 		.key_len = SEC_KEY_LEN_AES_256,
114915e4e84SJonathan Cameron 	},
115915e4e84SJonathan Cameron 	[SEC_C_NULL] = {
116915e4e84SJonathan Cameron 	},
117915e4e84SJonathan Cameron };
118915e4e84SJonathan Cameron 
119915e4e84SJonathan Cameron /*
120915e4e84SJonathan Cameron  * Mutex used to ensure safe operation of reference count of
121915e4e84SJonathan Cameron  * alg providers
122915e4e84SJonathan Cameron  */
123915e4e84SJonathan Cameron static DEFINE_MUTEX(algs_lock);
124915e4e84SJonathan Cameron static unsigned int active_devs;
125915e4e84SJonathan Cameron 
sec_alg_skcipher_init_template(struct sec_alg_tfm_ctx * ctx,struct sec_bd_info * req,enum sec_cipher_alg alg)126915e4e84SJonathan Cameron static void sec_alg_skcipher_init_template(struct sec_alg_tfm_ctx *ctx,
127915e4e84SJonathan Cameron 					   struct sec_bd_info *req,
128915e4e84SJonathan Cameron 					   enum sec_cipher_alg alg)
129915e4e84SJonathan Cameron {
130915e4e84SJonathan Cameron 	const struct sec_c_alg_cfg *cfg = &sec_c_alg_cfgs[alg];
131915e4e84SJonathan Cameron 
132915e4e84SJonathan Cameron 	memset(req, 0, sizeof(*req));
133915e4e84SJonathan Cameron 	req->w0 |= cfg->c_mode << SEC_BD_W0_C_MODE_S;
134915e4e84SJonathan Cameron 	req->w1 |= cfg->c_alg << SEC_BD_W1_C_ALG_S;
135915e4e84SJonathan Cameron 	req->w3 |= cfg->key_len << SEC_BD_W3_C_KEY_LEN_S;
136915e4e84SJonathan Cameron 	req->w0 |= cfg->c_width << SEC_BD_W0_C_WIDTH_S;
137915e4e84SJonathan Cameron 
138915e4e84SJonathan Cameron 	req->cipher_key_addr_lo = lower_32_bits(ctx->pkey);
139915e4e84SJonathan Cameron 	req->cipher_key_addr_hi = upper_32_bits(ctx->pkey);
140915e4e84SJonathan Cameron }
141915e4e84SJonathan Cameron 
sec_alg_skcipher_init_context(struct crypto_skcipher * atfm,const u8 * key,unsigned int keylen,enum sec_cipher_alg alg)142915e4e84SJonathan Cameron static void sec_alg_skcipher_init_context(struct crypto_skcipher *atfm,
143915e4e84SJonathan Cameron 					  const u8 *key,
144915e4e84SJonathan Cameron 					  unsigned int keylen,
145915e4e84SJonathan Cameron 					  enum sec_cipher_alg alg)
146915e4e84SJonathan Cameron {
147915e4e84SJonathan Cameron 	struct crypto_tfm *tfm = crypto_skcipher_tfm(atfm);
148915e4e84SJonathan Cameron 	struct sec_alg_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
149915e4e84SJonathan Cameron 
150915e4e84SJonathan Cameron 	ctx->cipher_alg = alg;
151915e4e84SJonathan Cameron 	memcpy(ctx->key, key, keylen);
152915e4e84SJonathan Cameron 	sec_alg_skcipher_init_template(ctx, &ctx->req_template,
153915e4e84SJonathan Cameron 				       ctx->cipher_alg);
154915e4e84SJonathan Cameron }
155915e4e84SJonathan Cameron 
sec_free_hw_sgl(struct sec_hw_sgl * hw_sgl,dma_addr_t psec_sgl,struct sec_dev_info * info)156e00371afSYunfeng Ye static void sec_free_hw_sgl(struct sec_hw_sgl *hw_sgl,
157e00371afSYunfeng Ye 			    dma_addr_t psec_sgl, struct sec_dev_info *info)
158e00371afSYunfeng Ye {
159e00371afSYunfeng Ye 	struct sec_hw_sgl *sgl_current, *sgl_next;
160e00371afSYunfeng Ye 	dma_addr_t sgl_next_dma;
161e00371afSYunfeng Ye 
162e00371afSYunfeng Ye 	sgl_current = hw_sgl;
163e00371afSYunfeng Ye 	while (sgl_current) {
164e00371afSYunfeng Ye 		sgl_next = sgl_current->next;
165e00371afSYunfeng Ye 		sgl_next_dma = sgl_current->next_sgl;
166e00371afSYunfeng Ye 
167e00371afSYunfeng Ye 		dma_pool_free(info->hw_sgl_pool, sgl_current, psec_sgl);
168e00371afSYunfeng Ye 
169e00371afSYunfeng Ye 		sgl_current = sgl_next;
170e00371afSYunfeng Ye 		psec_sgl = sgl_next_dma;
171e00371afSYunfeng Ye 	}
172e00371afSYunfeng Ye }
173e00371afSYunfeng Ye 
sec_alloc_and_fill_hw_sgl(struct sec_hw_sgl ** sec_sgl,dma_addr_t * psec_sgl,struct scatterlist * sgl,int count,struct sec_dev_info * info,gfp_t gfp)174915e4e84SJonathan Cameron static int sec_alloc_and_fill_hw_sgl(struct sec_hw_sgl **sec_sgl,
175915e4e84SJonathan Cameron 				     dma_addr_t *psec_sgl,
176915e4e84SJonathan Cameron 				     struct scatterlist *sgl,
177915e4e84SJonathan Cameron 				     int count,
1785ead0517SMikulas Patocka 				     struct sec_dev_info *info,
1795ead0517SMikulas Patocka 				     gfp_t gfp)
180915e4e84SJonathan Cameron {
181915e4e84SJonathan Cameron 	struct sec_hw_sgl *sgl_current = NULL;
182915e4e84SJonathan Cameron 	struct sec_hw_sgl *sgl_next;
183915e4e84SJonathan Cameron 	dma_addr_t sgl_next_dma;
184915e4e84SJonathan Cameron 	struct scatterlist *sg;
185915e4e84SJonathan Cameron 	int ret, sge_index, i;
186915e4e84SJonathan Cameron 
187915e4e84SJonathan Cameron 	if (!count)
188915e4e84SJonathan Cameron 		return -EINVAL;
189915e4e84SJonathan Cameron 
190915e4e84SJonathan Cameron 	for_each_sg(sgl, sg, count, i) {
191915e4e84SJonathan Cameron 		sge_index = i % SEC_MAX_SGE_NUM;
192915e4e84SJonathan Cameron 		if (sge_index == 0) {
193915e4e84SJonathan Cameron 			sgl_next = dma_pool_zalloc(info->hw_sgl_pool,
1945ead0517SMikulas Patocka 						   gfp, &sgl_next_dma);
195915e4e84SJonathan Cameron 			if (!sgl_next) {
196915e4e84SJonathan Cameron 				ret = -ENOMEM;
197915e4e84SJonathan Cameron 				goto err_free_hw_sgls;
198915e4e84SJonathan Cameron 			}
199915e4e84SJonathan Cameron 
200915e4e84SJonathan Cameron 			if (!sgl_current) { /* First one */
201915e4e84SJonathan Cameron 				*psec_sgl = sgl_next_dma;
202915e4e84SJonathan Cameron 				*sec_sgl = sgl_next;
203915e4e84SJonathan Cameron 			} else { /* Chained */
204915e4e84SJonathan Cameron 				sgl_current->entry_sum_in_sgl = SEC_MAX_SGE_NUM;
205915e4e84SJonathan Cameron 				sgl_current->next_sgl = sgl_next_dma;
206915e4e84SJonathan Cameron 				sgl_current->next = sgl_next;
207915e4e84SJonathan Cameron 			}
208915e4e84SJonathan Cameron 			sgl_current = sgl_next;
209915e4e84SJonathan Cameron 		}
210915e4e84SJonathan Cameron 		sgl_current->sge_entries[sge_index].buf = sg_dma_address(sg);
211915e4e84SJonathan Cameron 		sgl_current->sge_entries[sge_index].len = sg_dma_len(sg);
212915e4e84SJonathan Cameron 		sgl_current->data_bytes_in_sgl += sg_dma_len(sg);
213915e4e84SJonathan Cameron 	}
214915e4e84SJonathan Cameron 	sgl_current->entry_sum_in_sgl = count % SEC_MAX_SGE_NUM;
215915e4e84SJonathan Cameron 	sgl_current->next_sgl = 0;
216915e4e84SJonathan Cameron 	(*sec_sgl)->entry_sum_in_chain = count;
217915e4e84SJonathan Cameron 
218915e4e84SJonathan Cameron 	return 0;
219915e4e84SJonathan Cameron 
220915e4e84SJonathan Cameron err_free_hw_sgls:
221e00371afSYunfeng Ye 	sec_free_hw_sgl(*sec_sgl, *psec_sgl, info);
222915e4e84SJonathan Cameron 	*psec_sgl = 0;
223915e4e84SJonathan Cameron 
224915e4e84SJonathan Cameron 	return ret;
225915e4e84SJonathan Cameron }
226915e4e84SJonathan Cameron 
sec_alg_skcipher_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen,enum sec_cipher_alg alg)227915e4e84SJonathan Cameron static int sec_alg_skcipher_setkey(struct crypto_skcipher *tfm,
228915e4e84SJonathan Cameron 				   const u8 *key, unsigned int keylen,
229915e4e84SJonathan Cameron 				   enum sec_cipher_alg alg)
230915e4e84SJonathan Cameron {
231915e4e84SJonathan Cameron 	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
232915e4e84SJonathan Cameron 	struct device *dev = ctx->queue->dev_info->dev;
233915e4e84SJonathan Cameron 
234915e4e84SJonathan Cameron 	mutex_lock(&ctx->lock);
235915e4e84SJonathan Cameron 	if (ctx->key) {
236915e4e84SJonathan Cameron 		/* rekeying */
237915e4e84SJonathan Cameron 		memset(ctx->key, 0, SEC_MAX_CIPHER_KEY);
238915e4e84SJonathan Cameron 	} else {
239915e4e84SJonathan Cameron 		/* new key */
240750afb08SLuis Chamberlain 		ctx->key = dma_alloc_coherent(dev, SEC_MAX_CIPHER_KEY,
241915e4e84SJonathan Cameron 					      &ctx->pkey, GFP_KERNEL);
242915e4e84SJonathan Cameron 		if (!ctx->key) {
243915e4e84SJonathan Cameron 			mutex_unlock(&ctx->lock);
244915e4e84SJonathan Cameron 			return -ENOMEM;
245915e4e84SJonathan Cameron 		}
246915e4e84SJonathan Cameron 	}
247915e4e84SJonathan Cameron 	mutex_unlock(&ctx->lock);
248915e4e84SJonathan Cameron 	sec_alg_skcipher_init_context(tfm, key, keylen, alg);
249915e4e84SJonathan Cameron 
250915e4e84SJonathan Cameron 	return 0;
251915e4e84SJonathan Cameron }
252915e4e84SJonathan Cameron 
sec_alg_skcipher_setkey_aes_ecb(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)253915e4e84SJonathan Cameron static int sec_alg_skcipher_setkey_aes_ecb(struct crypto_skcipher *tfm,
254915e4e84SJonathan Cameron 					   const u8 *key, unsigned int keylen)
255915e4e84SJonathan Cameron {
256915e4e84SJonathan Cameron 	enum sec_cipher_alg alg;
257915e4e84SJonathan Cameron 
258915e4e84SJonathan Cameron 	switch (keylen) {
259915e4e84SJonathan Cameron 	case AES_KEYSIZE_128:
260915e4e84SJonathan Cameron 		alg = SEC_C_AES_ECB_128;
261915e4e84SJonathan Cameron 		break;
262915e4e84SJonathan Cameron 	case AES_KEYSIZE_192:
263915e4e84SJonathan Cameron 		alg = SEC_C_AES_ECB_192;
264915e4e84SJonathan Cameron 		break;
265915e4e84SJonathan Cameron 	case AES_KEYSIZE_256:
266915e4e84SJonathan Cameron 		alg = SEC_C_AES_ECB_256;
267915e4e84SJonathan Cameron 		break;
268915e4e84SJonathan Cameron 	default:
269915e4e84SJonathan Cameron 		return -EINVAL;
270915e4e84SJonathan Cameron 	}
271915e4e84SJonathan Cameron 
272915e4e84SJonathan Cameron 	return sec_alg_skcipher_setkey(tfm, key, keylen, alg);
273915e4e84SJonathan Cameron }
274915e4e84SJonathan Cameron 
sec_alg_skcipher_setkey_aes_cbc(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)275915e4e84SJonathan Cameron static int sec_alg_skcipher_setkey_aes_cbc(struct crypto_skcipher *tfm,
276915e4e84SJonathan Cameron 					   const u8 *key, unsigned int keylen)
277915e4e84SJonathan Cameron {
278915e4e84SJonathan Cameron 	enum sec_cipher_alg alg;
279915e4e84SJonathan Cameron 
280915e4e84SJonathan Cameron 	switch (keylen) {
281915e4e84SJonathan Cameron 	case AES_KEYSIZE_128:
282915e4e84SJonathan Cameron 		alg = SEC_C_AES_CBC_128;
283915e4e84SJonathan Cameron 		break;
284915e4e84SJonathan Cameron 	case AES_KEYSIZE_192:
285915e4e84SJonathan Cameron 		alg = SEC_C_AES_CBC_192;
286915e4e84SJonathan Cameron 		break;
287915e4e84SJonathan Cameron 	case AES_KEYSIZE_256:
288915e4e84SJonathan Cameron 		alg = SEC_C_AES_CBC_256;
289915e4e84SJonathan Cameron 		break;
290915e4e84SJonathan Cameron 	default:
291915e4e84SJonathan Cameron 		return -EINVAL;
292915e4e84SJonathan Cameron 	}
293915e4e84SJonathan Cameron 
294915e4e84SJonathan Cameron 	return sec_alg_skcipher_setkey(tfm, key, keylen, alg);
295915e4e84SJonathan Cameron }
296915e4e84SJonathan Cameron 
sec_alg_skcipher_setkey_aes_ctr(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)297915e4e84SJonathan Cameron static int sec_alg_skcipher_setkey_aes_ctr(struct crypto_skcipher *tfm,
298915e4e84SJonathan Cameron 					   const u8 *key, unsigned int keylen)
299915e4e84SJonathan Cameron {
300915e4e84SJonathan Cameron 	enum sec_cipher_alg alg;
301915e4e84SJonathan Cameron 
302915e4e84SJonathan Cameron 	switch (keylen) {
303915e4e84SJonathan Cameron 	case AES_KEYSIZE_128:
304915e4e84SJonathan Cameron 		alg = SEC_C_AES_CTR_128;
305915e4e84SJonathan Cameron 		break;
306915e4e84SJonathan Cameron 	case AES_KEYSIZE_192:
307915e4e84SJonathan Cameron 		alg = SEC_C_AES_CTR_192;
308915e4e84SJonathan Cameron 		break;
309915e4e84SJonathan Cameron 	case AES_KEYSIZE_256:
310915e4e84SJonathan Cameron 		alg = SEC_C_AES_CTR_256;
311915e4e84SJonathan Cameron 		break;
312915e4e84SJonathan Cameron 	default:
313915e4e84SJonathan Cameron 		return -EINVAL;
314915e4e84SJonathan Cameron 	}
315915e4e84SJonathan Cameron 
316915e4e84SJonathan Cameron 	return sec_alg_skcipher_setkey(tfm, key, keylen, alg);
317915e4e84SJonathan Cameron }
318915e4e84SJonathan Cameron 
sec_alg_skcipher_setkey_aes_xts(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)319915e4e84SJonathan Cameron static int sec_alg_skcipher_setkey_aes_xts(struct crypto_skcipher *tfm,
320915e4e84SJonathan Cameron 					   const u8 *key, unsigned int keylen)
321915e4e84SJonathan Cameron {
322915e4e84SJonathan Cameron 	enum sec_cipher_alg alg;
323915e4e84SJonathan Cameron 	int ret;
324915e4e84SJonathan Cameron 
325915e4e84SJonathan Cameron 	ret = xts_verify_key(tfm, key, keylen);
326915e4e84SJonathan Cameron 	if (ret)
327915e4e84SJonathan Cameron 		return ret;
328915e4e84SJonathan Cameron 
329915e4e84SJonathan Cameron 	switch (keylen) {
330915e4e84SJonathan Cameron 	case AES_KEYSIZE_128 * 2:
331915e4e84SJonathan Cameron 		alg = SEC_C_AES_XTS_128;
332915e4e84SJonathan Cameron 		break;
333915e4e84SJonathan Cameron 	case AES_KEYSIZE_256 * 2:
334915e4e84SJonathan Cameron 		alg = SEC_C_AES_XTS_256;
335915e4e84SJonathan Cameron 		break;
336915e4e84SJonathan Cameron 	default:
337915e4e84SJonathan Cameron 		return -EINVAL;
338915e4e84SJonathan Cameron 	}
339915e4e84SJonathan Cameron 
340915e4e84SJonathan Cameron 	return sec_alg_skcipher_setkey(tfm, key, keylen, alg);
341915e4e84SJonathan Cameron }
342915e4e84SJonathan Cameron 
sec_alg_skcipher_setkey_des_ecb(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)343915e4e84SJonathan Cameron static int sec_alg_skcipher_setkey_des_ecb(struct crypto_skcipher *tfm,
344915e4e84SJonathan Cameron 					   const u8 *key, unsigned int keylen)
345915e4e84SJonathan Cameron {
346894b68d8SArd Biesheuvel 	return verify_skcipher_des_key(tfm, key) ?:
347894b68d8SArd Biesheuvel 	       sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_ECB_64);
348915e4e84SJonathan Cameron }
349915e4e84SJonathan Cameron 
sec_alg_skcipher_setkey_des_cbc(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)350915e4e84SJonathan Cameron static int sec_alg_skcipher_setkey_des_cbc(struct crypto_skcipher *tfm,
351915e4e84SJonathan Cameron 					   const u8 *key, unsigned int keylen)
352915e4e84SJonathan Cameron {
353894b68d8SArd Biesheuvel 	return verify_skcipher_des_key(tfm, key) ?:
354894b68d8SArd Biesheuvel 	       sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_CBC_64);
355915e4e84SJonathan Cameron }
356915e4e84SJonathan Cameron 
sec_alg_skcipher_setkey_3des_ecb(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)357915e4e84SJonathan Cameron static int sec_alg_skcipher_setkey_3des_ecb(struct crypto_skcipher *tfm,
358915e4e84SJonathan Cameron 					    const u8 *key, unsigned int keylen)
359915e4e84SJonathan Cameron {
360894b68d8SArd Biesheuvel 	return verify_skcipher_des3_key(tfm, key) ?:
36194fc2e0bSHerbert Xu 	       sec_alg_skcipher_setkey(tfm, key, keylen,
362915e4e84SJonathan Cameron 				       SEC_C_3DES_ECB_192_3KEY);
363915e4e84SJonathan Cameron }
364915e4e84SJonathan Cameron 
sec_alg_skcipher_setkey_3des_cbc(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)365915e4e84SJonathan Cameron static int sec_alg_skcipher_setkey_3des_cbc(struct crypto_skcipher *tfm,
366915e4e84SJonathan Cameron 					    const u8 *key, unsigned int keylen)
367915e4e84SJonathan Cameron {
368894b68d8SArd Biesheuvel 	return verify_skcipher_des3_key(tfm, key) ?:
36994fc2e0bSHerbert Xu 	       sec_alg_skcipher_setkey(tfm, key, keylen,
370915e4e84SJonathan Cameron 				       SEC_C_3DES_CBC_192_3KEY);
371915e4e84SJonathan Cameron }
372915e4e84SJonathan Cameron 
sec_alg_free_el(struct sec_request_el * el,struct sec_dev_info * info)373915e4e84SJonathan Cameron static void sec_alg_free_el(struct sec_request_el *el,
374915e4e84SJonathan Cameron 			    struct sec_dev_info *info)
375915e4e84SJonathan Cameron {
376915e4e84SJonathan Cameron 	sec_free_hw_sgl(el->out, el->dma_out, info);
377915e4e84SJonathan Cameron 	sec_free_hw_sgl(el->in, el->dma_in, info);
378915e4e84SJonathan Cameron 	kfree(el->sgl_in);
379915e4e84SJonathan Cameron 	kfree(el->sgl_out);
380915e4e84SJonathan Cameron 	kfree(el);
381915e4e84SJonathan Cameron }
382915e4e84SJonathan Cameron 
383915e4e84SJonathan Cameron /* queuelock must be held */
sec_send_request(struct sec_request * sec_req,struct sec_queue * queue)3848418cf54Skbuild test robot static int sec_send_request(struct sec_request *sec_req, struct sec_queue *queue)
385915e4e84SJonathan Cameron {
386915e4e84SJonathan Cameron 	struct sec_request_el *el, *temp;
387915e4e84SJonathan Cameron 	int ret = 0;
388915e4e84SJonathan Cameron 
389915e4e84SJonathan Cameron 	mutex_lock(&sec_req->lock);
390915e4e84SJonathan Cameron 	list_for_each_entry_safe(el, temp, &sec_req->elements, head) {
391915e4e84SJonathan Cameron 		/*
392915e4e84SJonathan Cameron 		 * Add to hardware queue only under following circumstances
393915e4e84SJonathan Cameron 		 * 1) Software and hardware queue empty so no chain dependencies
394915e4e84SJonathan Cameron 		 * 2) No dependencies as new IV - (check software queue empty
395915e4e84SJonathan Cameron 		 *    to maintain order)
396915e4e84SJonathan Cameron 		 * 3) No dependencies because the mode does no chaining.
397915e4e84SJonathan Cameron 		 *
398915e4e84SJonathan Cameron 		 * In other cases first insert onto the software queue which
399915e4e84SJonathan Cameron 		 * is then emptied as requests complete
400915e4e84SJonathan Cameron 		 */
401915e4e84SJonathan Cameron 		if (!queue->havesoftqueue ||
402915e4e84SJonathan Cameron 		    (kfifo_is_empty(&queue->softqueue) &&
403915e4e84SJonathan Cameron 		     sec_queue_empty(queue))) {
404915e4e84SJonathan Cameron 			ret = sec_queue_send(queue, &el->req, sec_req);
405915e4e84SJonathan Cameron 			if (ret == -EAGAIN) {
406915e4e84SJonathan Cameron 				/* Wait unti we can send then try again */
407915e4e84SJonathan Cameron 				/* DEAD if here - should not happen */
408915e4e84SJonathan Cameron 				ret = -EBUSY;
409915e4e84SJonathan Cameron 				goto err_unlock;
410915e4e84SJonathan Cameron 			}
411915e4e84SJonathan Cameron 		} else {
412915e4e84SJonathan Cameron 			kfifo_put(&queue->softqueue, el);
413915e4e84SJonathan Cameron 		}
414915e4e84SJonathan Cameron 	}
415915e4e84SJonathan Cameron err_unlock:
416915e4e84SJonathan Cameron 	mutex_unlock(&sec_req->lock);
417915e4e84SJonathan Cameron 
418915e4e84SJonathan Cameron 	return ret;
419915e4e84SJonathan Cameron }
420915e4e84SJonathan Cameron 
sec_skcipher_alg_callback(struct sec_bd_info * sec_resp,struct crypto_async_request * req_base)421915e4e84SJonathan Cameron static void sec_skcipher_alg_callback(struct sec_bd_info *sec_resp,
422915e4e84SJonathan Cameron 				      struct crypto_async_request *req_base)
423915e4e84SJonathan Cameron {
424915e4e84SJonathan Cameron 	struct skcipher_request *skreq = container_of(req_base,
425915e4e84SJonathan Cameron 						      struct skcipher_request,
426915e4e84SJonathan Cameron 						      base);
427915e4e84SJonathan Cameron 	struct sec_request *sec_req = skcipher_request_ctx(skreq);
428915e4e84SJonathan Cameron 	struct sec_request *backlog_req;
429915e4e84SJonathan Cameron 	struct sec_request_el *sec_req_el, *nextrequest;
430915e4e84SJonathan Cameron 	struct sec_alg_tfm_ctx *ctx = sec_req->tfm_ctx;
431915e4e84SJonathan Cameron 	struct crypto_skcipher *atfm = crypto_skcipher_reqtfm(skreq);
432915e4e84SJonathan Cameron 	struct device *dev = ctx->queue->dev_info->dev;
433915e4e84SJonathan Cameron 	int icv_or_skey_en, ret;
434915e4e84SJonathan Cameron 	bool done;
435915e4e84SJonathan Cameron 
436915e4e84SJonathan Cameron 	sec_req_el = list_first_entry(&sec_req->elements, struct sec_request_el,
437915e4e84SJonathan Cameron 				      head);
438915e4e84SJonathan Cameron 	icv_or_skey_en = (sec_resp->w0 & SEC_BD_W0_ICV_OR_SKEY_EN_M) >>
439915e4e84SJonathan Cameron 		SEC_BD_W0_ICV_OR_SKEY_EN_S;
440915e4e84SJonathan Cameron 	if (sec_resp->w1 & SEC_BD_W1_BD_INVALID || icv_or_skey_en == 3) {
441915e4e84SJonathan Cameron 		dev_err(dev, "Got an invalid answer %lu %d\n",
442915e4e84SJonathan Cameron 			sec_resp->w1 & SEC_BD_W1_BD_INVALID,
443915e4e84SJonathan Cameron 			icv_or_skey_en);
444915e4e84SJonathan Cameron 		sec_req->err = -EINVAL;
445915e4e84SJonathan Cameron 		/*
446915e4e84SJonathan Cameron 		 * We need to muddle on to avoid getting stuck with elements
447915e4e84SJonathan Cameron 		 * on the queue. Error will be reported so requester so
448915e4e84SJonathan Cameron 		 * it should be able to handle appropriately.
449915e4e84SJonathan Cameron 		 */
450915e4e84SJonathan Cameron 	}
451915e4e84SJonathan Cameron 
45268740ab5SZhengchao Shao 	spin_lock_bh(&ctx->queue->queuelock);
453915e4e84SJonathan Cameron 	/* Put the IV in place for chained cases */
454915e4e84SJonathan Cameron 	switch (ctx->cipher_alg) {
455915e4e84SJonathan Cameron 	case SEC_C_AES_CBC_128:
456915e4e84SJonathan Cameron 	case SEC_C_AES_CBC_192:
457915e4e84SJonathan Cameron 	case SEC_C_AES_CBC_256:
458915e4e84SJonathan Cameron 		if (sec_req_el->req.w0 & SEC_BD_W0_DE)
459915e4e84SJonathan Cameron 			sg_pcopy_to_buffer(sec_req_el->sgl_out,
460915e4e84SJonathan Cameron 					   sg_nents(sec_req_el->sgl_out),
461915e4e84SJonathan Cameron 					   skreq->iv,
462915e4e84SJonathan Cameron 					   crypto_skcipher_ivsize(atfm),
463915e4e84SJonathan Cameron 					   sec_req_el->el_length -
464915e4e84SJonathan Cameron 					   crypto_skcipher_ivsize(atfm));
465915e4e84SJonathan Cameron 		else
466915e4e84SJonathan Cameron 			sg_pcopy_to_buffer(sec_req_el->sgl_in,
467915e4e84SJonathan Cameron 					   sg_nents(sec_req_el->sgl_in),
468915e4e84SJonathan Cameron 					   skreq->iv,
469915e4e84SJonathan Cameron 					   crypto_skcipher_ivsize(atfm),
470915e4e84SJonathan Cameron 					   sec_req_el->el_length -
471915e4e84SJonathan Cameron 					   crypto_skcipher_ivsize(atfm));
472915e4e84SJonathan Cameron 		/* No need to sync to the device as coherent DMA */
473915e4e84SJonathan Cameron 		break;
474915e4e84SJonathan Cameron 	case SEC_C_AES_CTR_128:
475915e4e84SJonathan Cameron 	case SEC_C_AES_CTR_192:
476915e4e84SJonathan Cameron 	case SEC_C_AES_CTR_256:
477915e4e84SJonathan Cameron 		crypto_inc(skreq->iv, 16);
478915e4e84SJonathan Cameron 		break;
479915e4e84SJonathan Cameron 	default:
480915e4e84SJonathan Cameron 		/* Do not update */
481915e4e84SJonathan Cameron 		break;
482915e4e84SJonathan Cameron 	}
483915e4e84SJonathan Cameron 
484915e4e84SJonathan Cameron 	if (ctx->queue->havesoftqueue &&
485915e4e84SJonathan Cameron 	    !kfifo_is_empty(&ctx->queue->softqueue) &&
486915e4e84SJonathan Cameron 	    sec_queue_empty(ctx->queue)) {
487915e4e84SJonathan Cameron 		ret = kfifo_get(&ctx->queue->softqueue, &nextrequest);
488915e4e84SJonathan Cameron 		if (ret <= 0)
489915e4e84SJonathan Cameron 			dev_err(dev,
490915e4e84SJonathan Cameron 				"Error getting next element from kfifo %d\n",
491915e4e84SJonathan Cameron 				ret);
492915e4e84SJonathan Cameron 		else
493915e4e84SJonathan Cameron 			/* We know there is space so this cannot fail */
494915e4e84SJonathan Cameron 			sec_queue_send(ctx->queue, &nextrequest->req,
495915e4e84SJonathan Cameron 				       nextrequest->sec_req);
496915e4e84SJonathan Cameron 	} else if (!list_empty(&ctx->backlog)) {
497915e4e84SJonathan Cameron 		/* Need to verify there is room first */
498915e4e84SJonathan Cameron 		backlog_req = list_first_entry(&ctx->backlog,
499915e4e84SJonathan Cameron 					       typeof(*backlog_req),
500915e4e84SJonathan Cameron 					       backlog_head);
501915e4e84SJonathan Cameron 		if (sec_queue_can_enqueue(ctx->queue,
502915e4e84SJonathan Cameron 		    backlog_req->num_elements) ||
503915e4e84SJonathan Cameron 		    (ctx->queue->havesoftqueue &&
504915e4e84SJonathan Cameron 		     kfifo_avail(&ctx->queue->softqueue) >
505915e4e84SJonathan Cameron 		     backlog_req->num_elements)) {
506915e4e84SJonathan Cameron 			sec_send_request(backlog_req, ctx->queue);
507*e2b537b7SHerbert Xu 			crypto_request_complete(backlog_req->req_base,
508915e4e84SJonathan Cameron 						-EINPROGRESS);
509915e4e84SJonathan Cameron 			list_del(&backlog_req->backlog_head);
510915e4e84SJonathan Cameron 		}
511915e4e84SJonathan Cameron 	}
51268740ab5SZhengchao Shao 	spin_unlock_bh(&ctx->queue->queuelock);
513915e4e84SJonathan Cameron 
514915e4e84SJonathan Cameron 	mutex_lock(&sec_req->lock);
515915e4e84SJonathan Cameron 	list_del(&sec_req_el->head);
516915e4e84SJonathan Cameron 	mutex_unlock(&sec_req->lock);
517915e4e84SJonathan Cameron 	sec_alg_free_el(sec_req_el, ctx->queue->dev_info);
518915e4e84SJonathan Cameron 
519915e4e84SJonathan Cameron 	/*
520915e4e84SJonathan Cameron 	 * Request is done.
521915e4e84SJonathan Cameron 	 * The dance is needed as the lock is freed in the completion
522915e4e84SJonathan Cameron 	 */
523915e4e84SJonathan Cameron 	mutex_lock(&sec_req->lock);
524915e4e84SJonathan Cameron 	done = list_empty(&sec_req->elements);
525915e4e84SJonathan Cameron 	mutex_unlock(&sec_req->lock);
526915e4e84SJonathan Cameron 	if (done) {
527915e4e84SJonathan Cameron 		if (crypto_skcipher_ivsize(atfm)) {
528915e4e84SJonathan Cameron 			dma_unmap_single(dev, sec_req->dma_iv,
529915e4e84SJonathan Cameron 					 crypto_skcipher_ivsize(atfm),
530915e4e84SJonathan Cameron 					 DMA_TO_DEVICE);
531915e4e84SJonathan Cameron 		}
532915e4e84SJonathan Cameron 		dma_unmap_sg(dev, skreq->src, sec_req->len_in,
533915e4e84SJonathan Cameron 			     DMA_BIDIRECTIONAL);
534915e4e84SJonathan Cameron 		if (skreq->src != skreq->dst)
535915e4e84SJonathan Cameron 			dma_unmap_sg(dev, skreq->dst, sec_req->len_out,
536915e4e84SJonathan Cameron 				     DMA_BIDIRECTIONAL);
537*e2b537b7SHerbert Xu 		skcipher_request_complete(skreq, sec_req->err);
538915e4e84SJonathan Cameron 	}
539915e4e84SJonathan Cameron }
540915e4e84SJonathan Cameron 
sec_alg_callback(struct sec_bd_info * resp,void * shadow)541915e4e84SJonathan Cameron void sec_alg_callback(struct sec_bd_info *resp, void *shadow)
542915e4e84SJonathan Cameron {
543915e4e84SJonathan Cameron 	struct sec_request *sec_req = shadow;
544915e4e84SJonathan Cameron 
545915e4e84SJonathan Cameron 	sec_req->cb(resp, sec_req->req_base);
546915e4e84SJonathan Cameron }
547915e4e84SJonathan Cameron 
sec_alg_alloc_and_calc_split_sizes(int length,size_t ** split_sizes,int * steps,gfp_t gfp)548915e4e84SJonathan Cameron static int sec_alg_alloc_and_calc_split_sizes(int length, size_t **split_sizes,
5495ead0517SMikulas Patocka 					      int *steps, gfp_t gfp)
550915e4e84SJonathan Cameron {
551915e4e84SJonathan Cameron 	size_t *sizes;
552915e4e84SJonathan Cameron 	int i;
553915e4e84SJonathan Cameron 
554915e4e84SJonathan Cameron 	/* Split into suitable sized blocks */
555915e4e84SJonathan Cameron 	*steps = roundup(length, SEC_REQ_LIMIT) / SEC_REQ_LIMIT;
5565ead0517SMikulas Patocka 	sizes = kcalloc(*steps, sizeof(*sizes), gfp);
557915e4e84SJonathan Cameron 	if (!sizes)
558915e4e84SJonathan Cameron 		return -ENOMEM;
559915e4e84SJonathan Cameron 
560915e4e84SJonathan Cameron 	for (i = 0; i < *steps - 1; i++)
561915e4e84SJonathan Cameron 		sizes[i] = SEC_REQ_LIMIT;
562915e4e84SJonathan Cameron 	sizes[*steps - 1] = length - SEC_REQ_LIMIT * (*steps - 1);
563915e4e84SJonathan Cameron 	*split_sizes = sizes;
564915e4e84SJonathan Cameron 
565915e4e84SJonathan Cameron 	return 0;
566915e4e84SJonathan Cameron }
567915e4e84SJonathan Cameron 
sec_map_and_split_sg(struct scatterlist * sgl,size_t * split_sizes,int steps,struct scatterlist *** splits,int ** splits_nents,int sgl_len_in,struct device * dev,gfp_t gfp)568915e4e84SJonathan Cameron static int sec_map_and_split_sg(struct scatterlist *sgl, size_t *split_sizes,
569915e4e84SJonathan Cameron 				int steps, struct scatterlist ***splits,
570915e4e84SJonathan Cameron 				int **splits_nents,
571915e4e84SJonathan Cameron 				int sgl_len_in,
5725ead0517SMikulas Patocka 				struct device *dev, gfp_t gfp)
573915e4e84SJonathan Cameron {
574915e4e84SJonathan Cameron 	int ret, count;
575915e4e84SJonathan Cameron 
576915e4e84SJonathan Cameron 	count = dma_map_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL);
577915e4e84SJonathan Cameron 	if (!count)
578915e4e84SJonathan Cameron 		return -EINVAL;
579915e4e84SJonathan Cameron 
5805ead0517SMikulas Patocka 	*splits = kcalloc(steps, sizeof(struct scatterlist *), gfp);
581915e4e84SJonathan Cameron 	if (!*splits) {
582915e4e84SJonathan Cameron 		ret = -ENOMEM;
583915e4e84SJonathan Cameron 		goto err_unmap_sg;
584915e4e84SJonathan Cameron 	}
5855ead0517SMikulas Patocka 	*splits_nents = kcalloc(steps, sizeof(int), gfp);
586915e4e84SJonathan Cameron 	if (!*splits_nents) {
587915e4e84SJonathan Cameron 		ret = -ENOMEM;
588915e4e84SJonathan Cameron 		goto err_free_splits;
589915e4e84SJonathan Cameron 	}
590915e4e84SJonathan Cameron 
591915e4e84SJonathan Cameron 	/* output the scatter list before and after this */
592915e4e84SJonathan Cameron 	ret = sg_split(sgl, count, 0, steps, split_sizes,
5935ead0517SMikulas Patocka 		       *splits, *splits_nents, gfp);
594915e4e84SJonathan Cameron 	if (ret) {
595915e4e84SJonathan Cameron 		ret = -ENOMEM;
596915e4e84SJonathan Cameron 		goto err_free_splits_nents;
597915e4e84SJonathan Cameron 	}
598915e4e84SJonathan Cameron 
599915e4e84SJonathan Cameron 	return 0;
600915e4e84SJonathan Cameron 
601915e4e84SJonathan Cameron err_free_splits_nents:
602915e4e84SJonathan Cameron 	kfree(*splits_nents);
603915e4e84SJonathan Cameron err_free_splits:
604915e4e84SJonathan Cameron 	kfree(*splits);
605915e4e84SJonathan Cameron err_unmap_sg:
606915e4e84SJonathan Cameron 	dma_unmap_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL);
607915e4e84SJonathan Cameron 
608915e4e84SJonathan Cameron 	return ret;
609915e4e84SJonathan Cameron }
610915e4e84SJonathan Cameron 
611915e4e84SJonathan Cameron /*
612915e4e84SJonathan Cameron  * Reverses the sec_map_and_split_sg call for messages not yet added to
613915e4e84SJonathan Cameron  * the queues.
614915e4e84SJonathan Cameron  */
sec_unmap_sg_on_err(struct scatterlist * sgl,int steps,struct scatterlist ** splits,int * splits_nents,int sgl_len_in,struct device * dev)615915e4e84SJonathan Cameron static void sec_unmap_sg_on_err(struct scatterlist *sgl, int steps,
616915e4e84SJonathan Cameron 				struct scatterlist **splits, int *splits_nents,
617915e4e84SJonathan Cameron 				int sgl_len_in, struct device *dev)
618915e4e84SJonathan Cameron {
619915e4e84SJonathan Cameron 	int i;
620915e4e84SJonathan Cameron 
621915e4e84SJonathan Cameron 	for (i = 0; i < steps; i++)
622915e4e84SJonathan Cameron 		kfree(splits[i]);
623915e4e84SJonathan Cameron 	kfree(splits_nents);
624915e4e84SJonathan Cameron 	kfree(splits);
625915e4e84SJonathan Cameron 
626915e4e84SJonathan Cameron 	dma_unmap_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL);
627915e4e84SJonathan Cameron }
628915e4e84SJonathan Cameron 
629915e4e84SJonathan Cameron static struct sec_request_el
sec_alg_alloc_and_fill_el(struct sec_bd_info * template,int encrypt,int el_size,bool different_dest,struct scatterlist * sgl_in,int n_ents_in,struct scatterlist * sgl_out,int n_ents_out,struct sec_dev_info * info,gfp_t gfp)630915e4e84SJonathan Cameron *sec_alg_alloc_and_fill_el(struct sec_bd_info *template, int encrypt,
631915e4e84SJonathan Cameron 			   int el_size, bool different_dest,
632915e4e84SJonathan Cameron 			   struct scatterlist *sgl_in, int n_ents_in,
633915e4e84SJonathan Cameron 			   struct scatterlist *sgl_out, int n_ents_out,
6345ead0517SMikulas Patocka 			   struct sec_dev_info *info, gfp_t gfp)
635915e4e84SJonathan Cameron {
636915e4e84SJonathan Cameron 	struct sec_request_el *el;
637915e4e84SJonathan Cameron 	struct sec_bd_info *req;
638915e4e84SJonathan Cameron 	int ret;
639915e4e84SJonathan Cameron 
6405ead0517SMikulas Patocka 	el = kzalloc(sizeof(*el), gfp);
641915e4e84SJonathan Cameron 	if (!el)
642915e4e84SJonathan Cameron 		return ERR_PTR(-ENOMEM);
643915e4e84SJonathan Cameron 	el->el_length = el_size;
644915e4e84SJonathan Cameron 	req = &el->req;
645915e4e84SJonathan Cameron 	memcpy(req, template, sizeof(*req));
646915e4e84SJonathan Cameron 
647915e4e84SJonathan Cameron 	req->w0 &= ~SEC_BD_W0_CIPHER_M;
648915e4e84SJonathan Cameron 	if (encrypt)
649915e4e84SJonathan Cameron 		req->w0 |= SEC_CIPHER_ENCRYPT << SEC_BD_W0_CIPHER_S;
650915e4e84SJonathan Cameron 	else
651915e4e84SJonathan Cameron 		req->w0 |= SEC_CIPHER_DECRYPT << SEC_BD_W0_CIPHER_S;
652915e4e84SJonathan Cameron 
653915e4e84SJonathan Cameron 	req->w0 &= ~SEC_BD_W0_C_GRAN_SIZE_19_16_M;
654915e4e84SJonathan Cameron 	req->w0 |= ((el_size >> 16) << SEC_BD_W0_C_GRAN_SIZE_19_16_S) &
655915e4e84SJonathan Cameron 		SEC_BD_W0_C_GRAN_SIZE_19_16_M;
656915e4e84SJonathan Cameron 
657915e4e84SJonathan Cameron 	req->w0 &= ~SEC_BD_W0_C_GRAN_SIZE_21_20_M;
658915e4e84SJonathan Cameron 	req->w0 |= ((el_size >> 20) << SEC_BD_W0_C_GRAN_SIZE_21_20_S) &
659915e4e84SJonathan Cameron 		SEC_BD_W0_C_GRAN_SIZE_21_20_M;
660915e4e84SJonathan Cameron 
661915e4e84SJonathan Cameron 	/* Writing whole u32 so no need to take care of masking */
662915e4e84SJonathan Cameron 	req->w2 = ((1 << SEC_BD_W2_GRAN_NUM_S) & SEC_BD_W2_GRAN_NUM_M) |
663915e4e84SJonathan Cameron 		((el_size << SEC_BD_W2_C_GRAN_SIZE_15_0_S) &
664915e4e84SJonathan Cameron 		 SEC_BD_W2_C_GRAN_SIZE_15_0_M);
665915e4e84SJonathan Cameron 
666915e4e84SJonathan Cameron 	req->w3 &= ~SEC_BD_W3_CIPHER_LEN_OFFSET_M;
667915e4e84SJonathan Cameron 	req->w1 |= SEC_BD_W1_ADDR_TYPE;
668915e4e84SJonathan Cameron 
669915e4e84SJonathan Cameron 	el->sgl_in = sgl_in;
670915e4e84SJonathan Cameron 
671915e4e84SJonathan Cameron 	ret = sec_alloc_and_fill_hw_sgl(&el->in, &el->dma_in, el->sgl_in,
6725ead0517SMikulas Patocka 					n_ents_in, info, gfp);
673915e4e84SJonathan Cameron 	if (ret)
674915e4e84SJonathan Cameron 		goto err_free_el;
675915e4e84SJonathan Cameron 
676915e4e84SJonathan Cameron 	req->data_addr_lo = lower_32_bits(el->dma_in);
677915e4e84SJonathan Cameron 	req->data_addr_hi = upper_32_bits(el->dma_in);
678915e4e84SJonathan Cameron 
679915e4e84SJonathan Cameron 	if (different_dest) {
680915e4e84SJonathan Cameron 		el->sgl_out = sgl_out;
681915e4e84SJonathan Cameron 		ret = sec_alloc_and_fill_hw_sgl(&el->out, &el->dma_out,
682915e4e84SJonathan Cameron 						el->sgl_out,
6835ead0517SMikulas Patocka 						n_ents_out, info, gfp);
684915e4e84SJonathan Cameron 		if (ret)
685915e4e84SJonathan Cameron 			goto err_free_hw_sgl_in;
686915e4e84SJonathan Cameron 
687915e4e84SJonathan Cameron 		req->w0 |= SEC_BD_W0_DE;
688915e4e84SJonathan Cameron 		req->cipher_destin_addr_lo = lower_32_bits(el->dma_out);
689915e4e84SJonathan Cameron 		req->cipher_destin_addr_hi = upper_32_bits(el->dma_out);
690915e4e84SJonathan Cameron 
691915e4e84SJonathan Cameron 	} else {
692915e4e84SJonathan Cameron 		req->w0 &= ~SEC_BD_W0_DE;
693915e4e84SJonathan Cameron 		req->cipher_destin_addr_lo = lower_32_bits(el->dma_in);
694915e4e84SJonathan Cameron 		req->cipher_destin_addr_hi = upper_32_bits(el->dma_in);
695915e4e84SJonathan Cameron 	}
696915e4e84SJonathan Cameron 
697915e4e84SJonathan Cameron 	return el;
698915e4e84SJonathan Cameron 
699915e4e84SJonathan Cameron err_free_hw_sgl_in:
700915e4e84SJonathan Cameron 	sec_free_hw_sgl(el->in, el->dma_in, info);
701915e4e84SJonathan Cameron err_free_el:
702915e4e84SJonathan Cameron 	kfree(el);
703915e4e84SJonathan Cameron 
704915e4e84SJonathan Cameron 	return ERR_PTR(ret);
705915e4e84SJonathan Cameron }
706915e4e84SJonathan Cameron 
sec_alg_skcipher_crypto(struct skcipher_request * skreq,bool encrypt)707915e4e84SJonathan Cameron static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
708915e4e84SJonathan Cameron 				   bool encrypt)
709915e4e84SJonathan Cameron {
710915e4e84SJonathan Cameron 	struct crypto_skcipher *atfm = crypto_skcipher_reqtfm(skreq);
711915e4e84SJonathan Cameron 	struct crypto_tfm *tfm = crypto_skcipher_tfm(atfm);
712915e4e84SJonathan Cameron 	struct sec_alg_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
713915e4e84SJonathan Cameron 	struct sec_queue *queue = ctx->queue;
714915e4e84SJonathan Cameron 	struct sec_request *sec_req = skcipher_request_ctx(skreq);
715915e4e84SJonathan Cameron 	struct sec_dev_info *info = queue->dev_info;
716915e4e84SJonathan Cameron 	int i, ret, steps;
717915e4e84SJonathan Cameron 	size_t *split_sizes;
718915e4e84SJonathan Cameron 	struct scatterlist **splits_in;
719915e4e84SJonathan Cameron 	struct scatterlist **splits_out = NULL;
720915e4e84SJonathan Cameron 	int *splits_in_nents;
721915e4e84SJonathan Cameron 	int *splits_out_nents = NULL;
722915e4e84SJonathan Cameron 	struct sec_request_el *el, *temp;
72368a031d2SJohn Garry 	bool split = skreq->src != skreq->dst;
7245ead0517SMikulas Patocka 	gfp_t gfp = skreq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC;
725915e4e84SJonathan Cameron 
726915e4e84SJonathan Cameron 	mutex_init(&sec_req->lock);
727915e4e84SJonathan Cameron 	sec_req->req_base = &skreq->base;
728915e4e84SJonathan Cameron 	sec_req->err = 0;
729915e4e84SJonathan Cameron 	/* SGL mapping out here to allow us to break it up as necessary */
730915e4e84SJonathan Cameron 	sec_req->len_in = sg_nents(skreq->src);
731915e4e84SJonathan Cameron 
732915e4e84SJonathan Cameron 	ret = sec_alg_alloc_and_calc_split_sizes(skreq->cryptlen, &split_sizes,
7335ead0517SMikulas Patocka 						 &steps, gfp);
734915e4e84SJonathan Cameron 	if (ret)
735915e4e84SJonathan Cameron 		return ret;
736915e4e84SJonathan Cameron 	sec_req->num_elements = steps;
737915e4e84SJonathan Cameron 	ret = sec_map_and_split_sg(skreq->src, split_sizes, steps, &splits_in,
738915e4e84SJonathan Cameron 				   &splits_in_nents, sec_req->len_in,
7395ead0517SMikulas Patocka 				   info->dev, gfp);
740915e4e84SJonathan Cameron 	if (ret)
741915e4e84SJonathan Cameron 		goto err_free_split_sizes;
742915e4e84SJonathan Cameron 
74368a031d2SJohn Garry 	if (split) {
744915e4e84SJonathan Cameron 		sec_req->len_out = sg_nents(skreq->dst);
745915e4e84SJonathan Cameron 		ret = sec_map_and_split_sg(skreq->dst, split_sizes, steps,
746915e4e84SJonathan Cameron 					   &splits_out, &splits_out_nents,
7475ead0517SMikulas Patocka 					   sec_req->len_out, info->dev, gfp);
748915e4e84SJonathan Cameron 		if (ret)
749915e4e84SJonathan Cameron 			goto err_unmap_in_sg;
750915e4e84SJonathan Cameron 	}
751915e4e84SJonathan Cameron 	/* Shared info stored in seq_req - applies to all BDs */
752915e4e84SJonathan Cameron 	sec_req->tfm_ctx = ctx;
753915e4e84SJonathan Cameron 	sec_req->cb = sec_skcipher_alg_callback;
754915e4e84SJonathan Cameron 	INIT_LIST_HEAD(&sec_req->elements);
755915e4e84SJonathan Cameron 
756915e4e84SJonathan Cameron 	/*
757915e4e84SJonathan Cameron 	 * Future optimization.
758915e4e84SJonathan Cameron 	 * In the chaining case we can't use a dma pool bounce buffer
759915e4e84SJonathan Cameron 	 * but in the case where we know there is no chaining we can
760915e4e84SJonathan Cameron 	 */
761915e4e84SJonathan Cameron 	if (crypto_skcipher_ivsize(atfm)) {
762915e4e84SJonathan Cameron 		sec_req->dma_iv = dma_map_single(info->dev, skreq->iv,
763915e4e84SJonathan Cameron 						 crypto_skcipher_ivsize(atfm),
764915e4e84SJonathan Cameron 						 DMA_TO_DEVICE);
765915e4e84SJonathan Cameron 		if (dma_mapping_error(info->dev, sec_req->dma_iv)) {
766915e4e84SJonathan Cameron 			ret = -ENOMEM;
767915e4e84SJonathan Cameron 			goto err_unmap_out_sg;
768915e4e84SJonathan Cameron 		}
769915e4e84SJonathan Cameron 	}
770915e4e84SJonathan Cameron 
771915e4e84SJonathan Cameron 	/* Set them all up then queue - cleaner error handling. */
772915e4e84SJonathan Cameron 	for (i = 0; i < steps; i++) {
773915e4e84SJonathan Cameron 		el = sec_alg_alloc_and_fill_el(&ctx->req_template,
774915e4e84SJonathan Cameron 					       encrypt ? 1 : 0,
775915e4e84SJonathan Cameron 					       split_sizes[i],
776915e4e84SJonathan Cameron 					       skreq->src != skreq->dst,
777915e4e84SJonathan Cameron 					       splits_in[i], splits_in_nents[i],
77868a031d2SJohn Garry 					       split ? splits_out[i] : NULL,
77968a031d2SJohn Garry 					       split ? splits_out_nents[i] : 0,
7805ead0517SMikulas Patocka 					       info, gfp);
781915e4e84SJonathan Cameron 		if (IS_ERR(el)) {
782915e4e84SJonathan Cameron 			ret = PTR_ERR(el);
783915e4e84SJonathan Cameron 			goto err_free_elements;
784915e4e84SJonathan Cameron 		}
785915e4e84SJonathan Cameron 		el->req.cipher_iv_addr_lo = lower_32_bits(sec_req->dma_iv);
786915e4e84SJonathan Cameron 		el->req.cipher_iv_addr_hi = upper_32_bits(sec_req->dma_iv);
787915e4e84SJonathan Cameron 		el->sec_req = sec_req;
788915e4e84SJonathan Cameron 		list_add_tail(&el->head, &sec_req->elements);
789915e4e84SJonathan Cameron 	}
790915e4e84SJonathan Cameron 
791915e4e84SJonathan Cameron 	/*
792915e4e84SJonathan Cameron 	 * Only attempt to queue if the whole lot can fit in the queue -
793915e4e84SJonathan Cameron 	 * we can't successfully cleanup after a partial queing so this
794915e4e84SJonathan Cameron 	 * must succeed or fail atomically.
795915e4e84SJonathan Cameron 	 *
796915e4e84SJonathan Cameron 	 * Big hammer test of both software and hardware queues - could be
797915e4e84SJonathan Cameron 	 * more refined but this is unlikely to happen so no need.
798915e4e84SJonathan Cameron 	 */
799915e4e84SJonathan Cameron 
800915e4e84SJonathan Cameron 	/* Grab a big lock for a long time to avoid concurrency issues */
80168740ab5SZhengchao Shao 	spin_lock_bh(&queue->queuelock);
802915e4e84SJonathan Cameron 
803915e4e84SJonathan Cameron 	/*
804915e4e84SJonathan Cameron 	 * Can go on to queue if we have space in either:
805915e4e84SJonathan Cameron 	 * 1) The hardware queue and no software queue
806915e4e84SJonathan Cameron 	 * 2) The software queue
807915e4e84SJonathan Cameron 	 * AND there is nothing in the backlog.  If there is backlog we
808915e4e84SJonathan Cameron 	 * have to only queue to the backlog queue and return busy.
809915e4e84SJonathan Cameron 	 */
810915e4e84SJonathan Cameron 	if ((!sec_queue_can_enqueue(queue, steps) &&
811915e4e84SJonathan Cameron 	     (!queue->havesoftqueue ||
812915e4e84SJonathan Cameron 	      kfifo_avail(&queue->softqueue) > steps)) ||
813915e4e84SJonathan Cameron 	    !list_empty(&ctx->backlog)) {
8140b0cf6afSJohn Garry 		ret = -EBUSY;
815915e4e84SJonathan Cameron 		if ((skreq->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
816915e4e84SJonathan Cameron 			list_add_tail(&sec_req->backlog_head, &ctx->backlog);
81768740ab5SZhengchao Shao 			spin_unlock_bh(&queue->queuelock);
8180b0cf6afSJohn Garry 			goto out;
819915e4e84SJonathan Cameron 		}
820915e4e84SJonathan Cameron 
82168740ab5SZhengchao Shao 		spin_unlock_bh(&queue->queuelock);
822915e4e84SJonathan Cameron 		goto err_free_elements;
823915e4e84SJonathan Cameron 	}
824915e4e84SJonathan Cameron 	ret = sec_send_request(sec_req, queue);
82568740ab5SZhengchao Shao 	spin_unlock_bh(&queue->queuelock);
826915e4e84SJonathan Cameron 	if (ret)
827915e4e84SJonathan Cameron 		goto err_free_elements;
828915e4e84SJonathan Cameron 
8290b0cf6afSJohn Garry 	ret = -EINPROGRESS;
8300b0cf6afSJohn Garry out:
8310b0cf6afSJohn Garry 	/* Cleanup - all elements in pointer arrays have been copied */
8320b0cf6afSJohn Garry 	kfree(splits_in_nents);
8330b0cf6afSJohn Garry 	kfree(splits_in);
8340b0cf6afSJohn Garry 	kfree(splits_out_nents);
8350b0cf6afSJohn Garry 	kfree(splits_out);
8360b0cf6afSJohn Garry 	kfree(split_sizes);
8370b0cf6afSJohn Garry 	return ret;
838915e4e84SJonathan Cameron 
839915e4e84SJonathan Cameron err_free_elements:
840915e4e84SJonathan Cameron 	list_for_each_entry_safe(el, temp, &sec_req->elements, head) {
841915e4e84SJonathan Cameron 		list_del(&el->head);
842915e4e84SJonathan Cameron 		sec_alg_free_el(el, info);
843915e4e84SJonathan Cameron 	}
844915e4e84SJonathan Cameron 	if (crypto_skcipher_ivsize(atfm))
845915e4e84SJonathan Cameron 		dma_unmap_single(info->dev, sec_req->dma_iv,
846915e4e84SJonathan Cameron 				 crypto_skcipher_ivsize(atfm),
847915e4e84SJonathan Cameron 				 DMA_BIDIRECTIONAL);
848915e4e84SJonathan Cameron err_unmap_out_sg:
84968a031d2SJohn Garry 	if (split)
850915e4e84SJonathan Cameron 		sec_unmap_sg_on_err(skreq->dst, steps, splits_out,
851915e4e84SJonathan Cameron 				    splits_out_nents, sec_req->len_out,
852915e4e84SJonathan Cameron 				    info->dev);
853915e4e84SJonathan Cameron err_unmap_in_sg:
854915e4e84SJonathan Cameron 	sec_unmap_sg_on_err(skreq->src, steps, splits_in, splits_in_nents,
855915e4e84SJonathan Cameron 			    sec_req->len_in, info->dev);
856915e4e84SJonathan Cameron err_free_split_sizes:
857915e4e84SJonathan Cameron 	kfree(split_sizes);
858915e4e84SJonathan Cameron 
859915e4e84SJonathan Cameron 	return ret;
860915e4e84SJonathan Cameron }
861915e4e84SJonathan Cameron 
sec_alg_skcipher_encrypt(struct skcipher_request * req)862915e4e84SJonathan Cameron static int sec_alg_skcipher_encrypt(struct skcipher_request *req)
863915e4e84SJonathan Cameron {
864915e4e84SJonathan Cameron 	return sec_alg_skcipher_crypto(req, true);
865915e4e84SJonathan Cameron }
866915e4e84SJonathan Cameron 
sec_alg_skcipher_decrypt(struct skcipher_request * req)867915e4e84SJonathan Cameron static int sec_alg_skcipher_decrypt(struct skcipher_request *req)
868915e4e84SJonathan Cameron {
869915e4e84SJonathan Cameron 	return sec_alg_skcipher_crypto(req, false);
870915e4e84SJonathan Cameron }
871915e4e84SJonathan Cameron 
sec_alg_skcipher_init(struct crypto_skcipher * tfm)872915e4e84SJonathan Cameron static int sec_alg_skcipher_init(struct crypto_skcipher *tfm)
873915e4e84SJonathan Cameron {
874915e4e84SJonathan Cameron 	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
875915e4e84SJonathan Cameron 
876915e4e84SJonathan Cameron 	mutex_init(&ctx->lock);
877915e4e84SJonathan Cameron 	INIT_LIST_HEAD(&ctx->backlog);
878915e4e84SJonathan Cameron 	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_request));
879915e4e84SJonathan Cameron 
880915e4e84SJonathan Cameron 	ctx->queue = sec_queue_alloc_start_safe();
881915e4e84SJonathan Cameron 	if (IS_ERR(ctx->queue))
882915e4e84SJonathan Cameron 		return PTR_ERR(ctx->queue);
883915e4e84SJonathan Cameron 
88468740ab5SZhengchao Shao 	spin_lock_init(&ctx->queue->queuelock);
885915e4e84SJonathan Cameron 	ctx->queue->havesoftqueue = false;
886915e4e84SJonathan Cameron 
887915e4e84SJonathan Cameron 	return 0;
888915e4e84SJonathan Cameron }
889915e4e84SJonathan Cameron 
sec_alg_skcipher_exit(struct crypto_skcipher * tfm)890915e4e84SJonathan Cameron static void sec_alg_skcipher_exit(struct crypto_skcipher *tfm)
891915e4e84SJonathan Cameron {
892915e4e84SJonathan Cameron 	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
893915e4e84SJonathan Cameron 	struct device *dev = ctx->queue->dev_info->dev;
894915e4e84SJonathan Cameron 
895915e4e84SJonathan Cameron 	if (ctx->key) {
896915e4e84SJonathan Cameron 		memzero_explicit(ctx->key, SEC_MAX_CIPHER_KEY);
897915e4e84SJonathan Cameron 		dma_free_coherent(dev, SEC_MAX_CIPHER_KEY, ctx->key,
898915e4e84SJonathan Cameron 				  ctx->pkey);
899915e4e84SJonathan Cameron 	}
900915e4e84SJonathan Cameron 	sec_queue_stop_release(ctx->queue);
901915e4e84SJonathan Cameron }
902915e4e84SJonathan Cameron 
sec_alg_skcipher_init_with_queue(struct crypto_skcipher * tfm)903915e4e84SJonathan Cameron static int sec_alg_skcipher_init_with_queue(struct crypto_skcipher *tfm)
904915e4e84SJonathan Cameron {
905915e4e84SJonathan Cameron 	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
906915e4e84SJonathan Cameron 	int ret;
907915e4e84SJonathan Cameron 
908915e4e84SJonathan Cameron 	ret = sec_alg_skcipher_init(tfm);
909915e4e84SJonathan Cameron 	if (ret)
910915e4e84SJonathan Cameron 		return ret;
911915e4e84SJonathan Cameron 
912915e4e84SJonathan Cameron 	INIT_KFIFO(ctx->queue->softqueue);
913915e4e84SJonathan Cameron 	ret = kfifo_alloc(&ctx->queue->softqueue, 512, GFP_KERNEL);
914915e4e84SJonathan Cameron 	if (ret) {
915915e4e84SJonathan Cameron 		sec_alg_skcipher_exit(tfm);
916915e4e84SJonathan Cameron 		return ret;
917915e4e84SJonathan Cameron 	}
918915e4e84SJonathan Cameron 	ctx->queue->havesoftqueue = true;
919915e4e84SJonathan Cameron 
920915e4e84SJonathan Cameron 	return 0;
921915e4e84SJonathan Cameron }
922915e4e84SJonathan Cameron 
sec_alg_skcipher_exit_with_queue(struct crypto_skcipher * tfm)923915e4e84SJonathan Cameron static void sec_alg_skcipher_exit_with_queue(struct crypto_skcipher *tfm)
924915e4e84SJonathan Cameron {
925915e4e84SJonathan Cameron 	struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
926915e4e84SJonathan Cameron 
927915e4e84SJonathan Cameron 	kfifo_free(&ctx->queue->softqueue);
928915e4e84SJonathan Cameron 	sec_alg_skcipher_exit(tfm);
929915e4e84SJonathan Cameron }
930915e4e84SJonathan Cameron 
931915e4e84SJonathan Cameron static struct skcipher_alg sec_algs[] = {
932915e4e84SJonathan Cameron 	{
933915e4e84SJonathan Cameron 		.base = {
934915e4e84SJonathan Cameron 			.cra_name = "ecb(aes)",
935915e4e84SJonathan Cameron 			.cra_driver_name = "hisi_sec_aes_ecb",
936915e4e84SJonathan Cameron 			.cra_priority = 4001,
937b8aa7dc5SMikulas Patocka 			.cra_flags = CRYPTO_ALG_ASYNC |
938b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY,
939915e4e84SJonathan Cameron 			.cra_blocksize = AES_BLOCK_SIZE,
940915e4e84SJonathan Cameron 			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
941915e4e84SJonathan Cameron 			.cra_alignmask = 0,
942915e4e84SJonathan Cameron 			.cra_module = THIS_MODULE,
943915e4e84SJonathan Cameron 		},
944915e4e84SJonathan Cameron 		.init = sec_alg_skcipher_init,
945915e4e84SJonathan Cameron 		.exit = sec_alg_skcipher_exit,
946915e4e84SJonathan Cameron 		.setkey = sec_alg_skcipher_setkey_aes_ecb,
947915e4e84SJonathan Cameron 		.decrypt = sec_alg_skcipher_decrypt,
948915e4e84SJonathan Cameron 		.encrypt = sec_alg_skcipher_encrypt,
949915e4e84SJonathan Cameron 		.min_keysize = AES_MIN_KEY_SIZE,
950915e4e84SJonathan Cameron 		.max_keysize = AES_MAX_KEY_SIZE,
951915e4e84SJonathan Cameron 		.ivsize = 0,
952915e4e84SJonathan Cameron 	}, {
953915e4e84SJonathan Cameron 		.base = {
954915e4e84SJonathan Cameron 			.cra_name = "cbc(aes)",
955915e4e84SJonathan Cameron 			.cra_driver_name = "hisi_sec_aes_cbc",
956915e4e84SJonathan Cameron 			.cra_priority = 4001,
957b8aa7dc5SMikulas Patocka 			.cra_flags = CRYPTO_ALG_ASYNC |
958b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY,
959915e4e84SJonathan Cameron 			.cra_blocksize = AES_BLOCK_SIZE,
960915e4e84SJonathan Cameron 			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
961915e4e84SJonathan Cameron 			.cra_alignmask = 0,
962915e4e84SJonathan Cameron 			.cra_module = THIS_MODULE,
963915e4e84SJonathan Cameron 		},
964915e4e84SJonathan Cameron 		.init = sec_alg_skcipher_init_with_queue,
965915e4e84SJonathan Cameron 		.exit = sec_alg_skcipher_exit_with_queue,
966915e4e84SJonathan Cameron 		.setkey = sec_alg_skcipher_setkey_aes_cbc,
967915e4e84SJonathan Cameron 		.decrypt = sec_alg_skcipher_decrypt,
968915e4e84SJonathan Cameron 		.encrypt = sec_alg_skcipher_encrypt,
969915e4e84SJonathan Cameron 		.min_keysize = AES_MIN_KEY_SIZE,
970915e4e84SJonathan Cameron 		.max_keysize = AES_MAX_KEY_SIZE,
971915e4e84SJonathan Cameron 		.ivsize = AES_BLOCK_SIZE,
972915e4e84SJonathan Cameron 	}, {
973915e4e84SJonathan Cameron 		.base = {
974915e4e84SJonathan Cameron 			.cra_name = "ctr(aes)",
975915e4e84SJonathan Cameron 			.cra_driver_name = "hisi_sec_aes_ctr",
976915e4e84SJonathan Cameron 			.cra_priority = 4001,
977b8aa7dc5SMikulas Patocka 			.cra_flags = CRYPTO_ALG_ASYNC |
978b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY,
979915e4e84SJonathan Cameron 			.cra_blocksize = AES_BLOCK_SIZE,
980915e4e84SJonathan Cameron 			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
981915e4e84SJonathan Cameron 			.cra_alignmask = 0,
982915e4e84SJonathan Cameron 			.cra_module = THIS_MODULE,
983915e4e84SJonathan Cameron 		},
984915e4e84SJonathan Cameron 		.init = sec_alg_skcipher_init_with_queue,
985915e4e84SJonathan Cameron 		.exit = sec_alg_skcipher_exit_with_queue,
986915e4e84SJonathan Cameron 		.setkey = sec_alg_skcipher_setkey_aes_ctr,
987915e4e84SJonathan Cameron 		.decrypt = sec_alg_skcipher_decrypt,
988915e4e84SJonathan Cameron 		.encrypt = sec_alg_skcipher_encrypt,
989915e4e84SJonathan Cameron 		.min_keysize = AES_MIN_KEY_SIZE,
990915e4e84SJonathan Cameron 		.max_keysize = AES_MAX_KEY_SIZE,
991915e4e84SJonathan Cameron 		.ivsize = AES_BLOCK_SIZE,
992915e4e84SJonathan Cameron 	}, {
993915e4e84SJonathan Cameron 		.base = {
994915e4e84SJonathan Cameron 			.cra_name = "xts(aes)",
995915e4e84SJonathan Cameron 			.cra_driver_name = "hisi_sec_aes_xts",
996915e4e84SJonathan Cameron 			.cra_priority = 4001,
997b8aa7dc5SMikulas Patocka 			.cra_flags = CRYPTO_ALG_ASYNC |
998b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY,
999915e4e84SJonathan Cameron 			.cra_blocksize = AES_BLOCK_SIZE,
1000915e4e84SJonathan Cameron 			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
1001915e4e84SJonathan Cameron 			.cra_alignmask = 0,
1002915e4e84SJonathan Cameron 			.cra_module = THIS_MODULE,
1003915e4e84SJonathan Cameron 		},
1004915e4e84SJonathan Cameron 		.init = sec_alg_skcipher_init,
1005915e4e84SJonathan Cameron 		.exit = sec_alg_skcipher_exit,
1006915e4e84SJonathan Cameron 		.setkey = sec_alg_skcipher_setkey_aes_xts,
1007915e4e84SJonathan Cameron 		.decrypt = sec_alg_skcipher_decrypt,
1008915e4e84SJonathan Cameron 		.encrypt = sec_alg_skcipher_encrypt,
1009915e4e84SJonathan Cameron 		.min_keysize = 2 * AES_MIN_KEY_SIZE,
1010915e4e84SJonathan Cameron 		.max_keysize = 2 * AES_MAX_KEY_SIZE,
1011915e4e84SJonathan Cameron 		.ivsize = AES_BLOCK_SIZE,
1012915e4e84SJonathan Cameron 	}, {
1013915e4e84SJonathan Cameron 	/* Unable to find any test vectors so untested */
1014915e4e84SJonathan Cameron 		.base = {
1015915e4e84SJonathan Cameron 			.cra_name = "ecb(des)",
1016915e4e84SJonathan Cameron 			.cra_driver_name = "hisi_sec_des_ecb",
1017915e4e84SJonathan Cameron 			.cra_priority = 4001,
1018b8aa7dc5SMikulas Patocka 			.cra_flags = CRYPTO_ALG_ASYNC |
1019b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY,
1020915e4e84SJonathan Cameron 			.cra_blocksize = DES_BLOCK_SIZE,
1021915e4e84SJonathan Cameron 			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
1022915e4e84SJonathan Cameron 			.cra_alignmask = 0,
1023915e4e84SJonathan Cameron 			.cra_module = THIS_MODULE,
1024915e4e84SJonathan Cameron 		},
1025915e4e84SJonathan Cameron 		.init = sec_alg_skcipher_init,
1026915e4e84SJonathan Cameron 		.exit = sec_alg_skcipher_exit,
1027915e4e84SJonathan Cameron 		.setkey = sec_alg_skcipher_setkey_des_ecb,
1028915e4e84SJonathan Cameron 		.decrypt = sec_alg_skcipher_decrypt,
1029915e4e84SJonathan Cameron 		.encrypt = sec_alg_skcipher_encrypt,
1030915e4e84SJonathan Cameron 		.min_keysize = DES_KEY_SIZE,
1031915e4e84SJonathan Cameron 		.max_keysize = DES_KEY_SIZE,
1032915e4e84SJonathan Cameron 		.ivsize = 0,
1033915e4e84SJonathan Cameron 	}, {
1034915e4e84SJonathan Cameron 		.base = {
1035915e4e84SJonathan Cameron 			.cra_name = "cbc(des)",
1036915e4e84SJonathan Cameron 			.cra_driver_name = "hisi_sec_des_cbc",
1037915e4e84SJonathan Cameron 			.cra_priority = 4001,
1038b8aa7dc5SMikulas Patocka 			.cra_flags = CRYPTO_ALG_ASYNC |
1039b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY,
1040915e4e84SJonathan Cameron 			.cra_blocksize = DES_BLOCK_SIZE,
1041915e4e84SJonathan Cameron 			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
1042915e4e84SJonathan Cameron 			.cra_alignmask = 0,
1043915e4e84SJonathan Cameron 			.cra_module = THIS_MODULE,
1044915e4e84SJonathan Cameron 		},
1045915e4e84SJonathan Cameron 		.init = sec_alg_skcipher_init_with_queue,
1046915e4e84SJonathan Cameron 		.exit = sec_alg_skcipher_exit_with_queue,
1047915e4e84SJonathan Cameron 		.setkey = sec_alg_skcipher_setkey_des_cbc,
1048915e4e84SJonathan Cameron 		.decrypt = sec_alg_skcipher_decrypt,
1049915e4e84SJonathan Cameron 		.encrypt = sec_alg_skcipher_encrypt,
1050915e4e84SJonathan Cameron 		.min_keysize = DES_KEY_SIZE,
1051915e4e84SJonathan Cameron 		.max_keysize = DES_KEY_SIZE,
1052915e4e84SJonathan Cameron 		.ivsize = DES_BLOCK_SIZE,
1053915e4e84SJonathan Cameron 	}, {
1054915e4e84SJonathan Cameron 		.base = {
1055915e4e84SJonathan Cameron 			.cra_name = "cbc(des3_ede)",
1056915e4e84SJonathan Cameron 			.cra_driver_name = "hisi_sec_3des_cbc",
1057915e4e84SJonathan Cameron 			.cra_priority = 4001,
1058b8aa7dc5SMikulas Patocka 			.cra_flags = CRYPTO_ALG_ASYNC |
1059b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY,
1060915e4e84SJonathan Cameron 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1061915e4e84SJonathan Cameron 			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
1062915e4e84SJonathan Cameron 			.cra_alignmask = 0,
1063915e4e84SJonathan Cameron 			.cra_module = THIS_MODULE,
1064915e4e84SJonathan Cameron 		},
1065915e4e84SJonathan Cameron 		.init = sec_alg_skcipher_init_with_queue,
1066915e4e84SJonathan Cameron 		.exit = sec_alg_skcipher_exit_with_queue,
1067915e4e84SJonathan Cameron 		.setkey = sec_alg_skcipher_setkey_3des_cbc,
1068915e4e84SJonathan Cameron 		.decrypt = sec_alg_skcipher_decrypt,
1069915e4e84SJonathan Cameron 		.encrypt = sec_alg_skcipher_encrypt,
1070915e4e84SJonathan Cameron 		.min_keysize = DES3_EDE_KEY_SIZE,
1071915e4e84SJonathan Cameron 		.max_keysize = DES3_EDE_KEY_SIZE,
1072915e4e84SJonathan Cameron 		.ivsize = DES3_EDE_BLOCK_SIZE,
1073915e4e84SJonathan Cameron 	}, {
1074915e4e84SJonathan Cameron 		.base = {
1075915e4e84SJonathan Cameron 			.cra_name = "ecb(des3_ede)",
1076915e4e84SJonathan Cameron 			.cra_driver_name = "hisi_sec_3des_ecb",
1077915e4e84SJonathan Cameron 			.cra_priority = 4001,
1078b8aa7dc5SMikulas Patocka 			.cra_flags = CRYPTO_ALG_ASYNC |
1079b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY,
1080915e4e84SJonathan Cameron 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1081915e4e84SJonathan Cameron 			.cra_ctxsize = sizeof(struct sec_alg_tfm_ctx),
1082915e4e84SJonathan Cameron 			.cra_alignmask = 0,
1083915e4e84SJonathan Cameron 			.cra_module = THIS_MODULE,
1084915e4e84SJonathan Cameron 		},
1085915e4e84SJonathan Cameron 		.init = sec_alg_skcipher_init,
1086915e4e84SJonathan Cameron 		.exit = sec_alg_skcipher_exit,
1087915e4e84SJonathan Cameron 		.setkey = sec_alg_skcipher_setkey_3des_ecb,
1088915e4e84SJonathan Cameron 		.decrypt = sec_alg_skcipher_decrypt,
1089915e4e84SJonathan Cameron 		.encrypt = sec_alg_skcipher_encrypt,
1090915e4e84SJonathan Cameron 		.min_keysize = DES3_EDE_KEY_SIZE,
1091915e4e84SJonathan Cameron 		.max_keysize = DES3_EDE_KEY_SIZE,
1092915e4e84SJonathan Cameron 		.ivsize = 0,
1093915e4e84SJonathan Cameron 	}
1094915e4e84SJonathan Cameron };
1095915e4e84SJonathan Cameron 
sec_algs_register(void)1096915e4e84SJonathan Cameron int sec_algs_register(void)
1097915e4e84SJonathan Cameron {
1098915e4e84SJonathan Cameron 	int ret = 0;
1099915e4e84SJonathan Cameron 
1100915e4e84SJonathan Cameron 	mutex_lock(&algs_lock);
1101915e4e84SJonathan Cameron 	if (++active_devs != 1)
1102915e4e84SJonathan Cameron 		goto unlock;
1103915e4e84SJonathan Cameron 
1104915e4e84SJonathan Cameron 	ret = crypto_register_skciphers(sec_algs, ARRAY_SIZE(sec_algs));
1105915e4e84SJonathan Cameron 	if (ret)
1106915e4e84SJonathan Cameron 		--active_devs;
1107915e4e84SJonathan Cameron unlock:
1108915e4e84SJonathan Cameron 	mutex_unlock(&algs_lock);
1109915e4e84SJonathan Cameron 
1110915e4e84SJonathan Cameron 	return ret;
1111915e4e84SJonathan Cameron }
1112915e4e84SJonathan Cameron 
sec_algs_unregister(void)1113915e4e84SJonathan Cameron void sec_algs_unregister(void)
1114915e4e84SJonathan Cameron {
1115915e4e84SJonathan Cameron 	mutex_lock(&algs_lock);
1116915e4e84SJonathan Cameron 	if (--active_devs != 0)
1117915e4e84SJonathan Cameron 		goto unlock;
1118915e4e84SJonathan Cameron 	crypto_unregister_skciphers(sec_algs, ARRAY_SIZE(sec_algs));
1119915e4e84SJonathan Cameron 
1120915e4e84SJonathan Cameron unlock:
1121915e4e84SJonathan Cameron 	mutex_unlock(&algs_lock);
1122915e4e84SJonathan Cameron }
1123