xref: /linux/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
1fbf31dd5STom Zanussi // SPDX-License-Identifier: GPL-2.0-only
2fbf31dd5STom Zanussi /*
3fbf31dd5STom Zanussi  * Intel Keem Bay OCS AES Crypto Driver.
4fbf31dd5STom Zanussi  *
5fbf31dd5STom Zanussi  * Copyright (C) 2018-2020 Intel Corporation
6fbf31dd5STom Zanussi  */
7fbf31dd5STom Zanussi 
8fbf31dd5STom Zanussi #include <crypto/aes.h>
9fbf31dd5STom Zanussi #include <crypto/engine.h>
10fbf31dd5STom Zanussi #include <crypto/gcm.h>
11fbf31dd5STom Zanussi #include <crypto/internal/aead.h>
12fbf31dd5STom Zanussi #include <crypto/internal/skcipher.h>
13530d7b00SHerbert Xu #include <crypto/scatterwalk.h>
14530d7b00SHerbert Xu #include <linux/clk.h>
15530d7b00SHerbert Xu #include <linux/completion.h>
16530d7b00SHerbert Xu #include <linux/dma-mapping.h>
17530d7b00SHerbert Xu #include <linux/err.h>
18530d7b00SHerbert Xu #include <linux/interrupt.h>
19530d7b00SHerbert Xu #include <linux/io.h>
20530d7b00SHerbert Xu #include <linux/kernel.h>
21530d7b00SHerbert Xu #include <linux/module.h>
22530d7b00SHerbert Xu #include <linux/of.h>
23530d7b00SHerbert Xu #include <linux/platform_device.h>
24530d7b00SHerbert Xu #include <linux/string.h>
25fbf31dd5STom Zanussi 
26fbf31dd5STom Zanussi #include "ocs-aes.h"
27fbf31dd5STom Zanussi 
28fbf31dd5STom Zanussi #define KMB_OCS_PRIORITY	350
29fbf31dd5STom Zanussi #define DRV_NAME		"keembay-ocs-aes"
30fbf31dd5STom Zanussi 
31fbf31dd5STom Zanussi #define OCS_AES_MIN_KEY_SIZE	16
32fbf31dd5STom Zanussi #define OCS_AES_MAX_KEY_SIZE	32
33fbf31dd5STom Zanussi #define OCS_AES_KEYSIZE_128	16
34fbf31dd5STom Zanussi #define OCS_AES_KEYSIZE_192	24
35fbf31dd5STom Zanussi #define OCS_AES_KEYSIZE_256	32
36fbf31dd5STom Zanussi #define OCS_SM4_KEY_SIZE	16
37fbf31dd5STom Zanussi 
38fbf31dd5STom Zanussi /**
39fbf31dd5STom Zanussi  * struct ocs_aes_tctx - OCS AES Transform context
40fbf31dd5STom Zanussi  * @aes_dev:		The OCS AES device.
41fbf31dd5STom Zanussi  * @key:		AES/SM4 key.
42fbf31dd5STom Zanussi  * @key_len:		The length (in bytes) of @key.
43fbf31dd5STom Zanussi  * @cipher:		OCS cipher to use (either AES or SM4).
44fbf31dd5STom Zanussi  * @sw_cipher:		The cipher to use as fallback.
45fbf31dd5STom Zanussi  * @use_fallback:	Whether or not fallback cipher should be used.
46fbf31dd5STom Zanussi  */
47fbf31dd5STom Zanussi struct ocs_aes_tctx {
48fbf31dd5STom Zanussi 	struct ocs_aes_dev *aes_dev;
49fbf31dd5STom Zanussi 	u8 key[OCS_AES_KEYSIZE_256];
50fbf31dd5STom Zanussi 	unsigned int key_len;
51fbf31dd5STom Zanussi 	enum ocs_cipher cipher;
52fbf31dd5STom Zanussi 	union {
53fbf31dd5STom Zanussi 		struct crypto_sync_skcipher *sk;
54fbf31dd5STom Zanussi 		struct crypto_aead *aead;
55fbf31dd5STom Zanussi 	} sw_cipher;
56fbf31dd5STom Zanussi 	bool use_fallback;
57fbf31dd5STom Zanussi };
58fbf31dd5STom Zanussi 
59fbf31dd5STom Zanussi /**
60fbf31dd5STom Zanussi  * struct ocs_aes_rctx - OCS AES Request context.
61fbf31dd5STom Zanussi  * @instruction:	Instruction to be executed (encrypt / decrypt).
62fbf31dd5STom Zanussi  * @mode:		Mode to use (ECB, CBC, CTR, CCm, GCM, CTS)
63fbf31dd5STom Zanussi  * @src_nents:		Number of source SG entries.
64fbf31dd5STom Zanussi  * @dst_nents:		Number of destination SG entries.
65fbf31dd5STom Zanussi  * @src_dma_count:	The number of DMA-mapped entries of the source SG.
66fbf31dd5STom Zanussi  * @dst_dma_count:	The number of DMA-mapped entries of the destination SG.
67fbf31dd5STom Zanussi  * @in_place:		Whether or not this is an in place request, i.e.,
68fbf31dd5STom Zanussi  *			src_sg == dst_sg.
69fbf31dd5STom Zanussi  * @src_dll:		OCS DMA linked list for input data.
70fbf31dd5STom Zanussi  * @dst_dll:		OCS DMA linked list for output data.
71fbf31dd5STom Zanussi  * @last_ct_blk:	Buffer to hold last cipher text block (only used in CBC
72fbf31dd5STom Zanussi  *			mode).
73fbf31dd5STom Zanussi  * @cts_swap:		Whether or not CTS swap must be performed.
74fbf31dd5STom Zanussi  * @aad_src_dll:	OCS DMA linked list for input AAD data.
75fbf31dd5STom Zanussi  * @aad_dst_dll:	OCS DMA linked list for output AAD data.
76fbf31dd5STom Zanussi  * @in_tag:		Buffer to hold input encrypted tag (only used for
77fbf31dd5STom Zanussi  *			CCM/GCM decrypt).
78fbf31dd5STom Zanussi  * @out_tag:		Buffer to hold output encrypted / decrypted tag (only
79fbf31dd5STom Zanussi  *			used for GCM encrypt / decrypt).
80fbf31dd5STom Zanussi  */
81fbf31dd5STom Zanussi struct ocs_aes_rctx {
82fbf31dd5STom Zanussi 	/* Fields common across all modes. */
83fbf31dd5STom Zanussi 	enum ocs_instruction	instruction;
84fbf31dd5STom Zanussi 	enum ocs_mode		mode;
85fbf31dd5STom Zanussi 	int			src_nents;
86fbf31dd5STom Zanussi 	int			dst_nents;
87fbf31dd5STom Zanussi 	int			src_dma_count;
88fbf31dd5STom Zanussi 	int			dst_dma_count;
89fbf31dd5STom Zanussi 	bool			in_place;
90fbf31dd5STom Zanussi 	struct ocs_dll_desc	src_dll;
91fbf31dd5STom Zanussi 	struct ocs_dll_desc	dst_dll;
92fbf31dd5STom Zanussi 
93fbf31dd5STom Zanussi 	/* CBC specific */
94fbf31dd5STom Zanussi 	u8			last_ct_blk[AES_BLOCK_SIZE];
95fbf31dd5STom Zanussi 
96fbf31dd5STom Zanussi 	/* CTS specific */
97fbf31dd5STom Zanussi 	int			cts_swap;
98fbf31dd5STom Zanussi 
99fbf31dd5STom Zanussi 	/* CCM/GCM specific */
100fbf31dd5STom Zanussi 	struct ocs_dll_desc	aad_src_dll;
101fbf31dd5STom Zanussi 	struct ocs_dll_desc	aad_dst_dll;
102fbf31dd5STom Zanussi 	u8			in_tag[AES_BLOCK_SIZE];
103fbf31dd5STom Zanussi 
104fbf31dd5STom Zanussi 	/* GCM specific */
105fbf31dd5STom Zanussi 	u8			out_tag[AES_BLOCK_SIZE];
106fbf31dd5STom Zanussi };
107fbf31dd5STom Zanussi 
108fbf31dd5STom Zanussi /* Driver data. */
109fbf31dd5STom Zanussi struct ocs_aes_drv {
110fbf31dd5STom Zanussi 	struct list_head dev_list;
111fbf31dd5STom Zanussi 	spinlock_t lock;	/* Protects dev_list. */
112fbf31dd5STom Zanussi };
113fbf31dd5STom Zanussi 
114fbf31dd5STom Zanussi static struct ocs_aes_drv ocs_aes = {
115fbf31dd5STom Zanussi 	.dev_list = LIST_HEAD_INIT(ocs_aes.dev_list),
116fbf31dd5STom Zanussi 	.lock = __SPIN_LOCK_UNLOCKED(ocs_aes.lock),
117fbf31dd5STom Zanussi };
118fbf31dd5STom Zanussi 
kmb_ocs_aes_find_dev(struct ocs_aes_tctx * tctx)119fbf31dd5STom Zanussi static struct ocs_aes_dev *kmb_ocs_aes_find_dev(struct ocs_aes_tctx *tctx)
120fbf31dd5STom Zanussi {
121fbf31dd5STom Zanussi 	struct ocs_aes_dev *aes_dev;
122fbf31dd5STom Zanussi 
123fbf31dd5STom Zanussi 	spin_lock(&ocs_aes.lock);
124fbf31dd5STom Zanussi 
125fbf31dd5STom Zanussi 	if (tctx->aes_dev) {
126fbf31dd5STom Zanussi 		aes_dev = tctx->aes_dev;
127fbf31dd5STom Zanussi 		goto exit;
128fbf31dd5STom Zanussi 	}
129fbf31dd5STom Zanussi 
130fbf31dd5STom Zanussi 	/* Only a single OCS device available */
131fbf31dd5STom Zanussi 	aes_dev = list_first_entry(&ocs_aes.dev_list, struct ocs_aes_dev, list);
132fbf31dd5STom Zanussi 	tctx->aes_dev = aes_dev;
133fbf31dd5STom Zanussi 
134fbf31dd5STom Zanussi exit:
135fbf31dd5STom Zanussi 	spin_unlock(&ocs_aes.lock);
136fbf31dd5STom Zanussi 
137fbf31dd5STom Zanussi 	return aes_dev;
138fbf31dd5STom Zanussi }
139fbf31dd5STom Zanussi 
140fbf31dd5STom Zanussi /*
141fbf31dd5STom Zanussi  * Ensure key is 128-bit or 256-bit for AES or 128-bit for SM4 and an actual
142fbf31dd5STom Zanussi  * key is being passed in.
143fbf31dd5STom Zanussi  *
144fbf31dd5STom Zanussi  * Return: 0 if key is valid, -EINVAL otherwise.
145fbf31dd5STom Zanussi  */
check_key(const u8 * in_key,size_t key_len,enum ocs_cipher cipher)146fbf31dd5STom Zanussi static int check_key(const u8 *in_key, size_t key_len, enum ocs_cipher cipher)
147fbf31dd5STom Zanussi {
148fbf31dd5STom Zanussi 	if (!in_key)
149fbf31dd5STom Zanussi 		return -EINVAL;
150fbf31dd5STom Zanussi 
151fbf31dd5STom Zanussi 	/* For AES, only 128-byte or 256-byte keys are supported. */
152fbf31dd5STom Zanussi 	if (cipher == OCS_AES && (key_len == OCS_AES_KEYSIZE_128 ||
153fbf31dd5STom Zanussi 				  key_len == OCS_AES_KEYSIZE_256))
154fbf31dd5STom Zanussi 		return 0;
155fbf31dd5STom Zanussi 
156fbf31dd5STom Zanussi 	/* For SM4, only 128-byte keys are supported. */
157fbf31dd5STom Zanussi 	if (cipher == OCS_SM4 && key_len == OCS_AES_KEYSIZE_128)
158fbf31dd5STom Zanussi 		return 0;
159fbf31dd5STom Zanussi 
160fbf31dd5STom Zanussi 	/* Everything else is unsupported. */
161fbf31dd5STom Zanussi 	return -EINVAL;
162fbf31dd5STom Zanussi }
163fbf31dd5STom Zanussi 
164fbf31dd5STom Zanussi /* Save key into transformation context. */
save_key(struct ocs_aes_tctx * tctx,const u8 * in_key,size_t key_len,enum ocs_cipher cipher)165fbf31dd5STom Zanussi static int save_key(struct ocs_aes_tctx *tctx, const u8 *in_key, size_t key_len,
166fbf31dd5STom Zanussi 		    enum ocs_cipher cipher)
167fbf31dd5STom Zanussi {
168fbf31dd5STom Zanussi 	int ret;
169fbf31dd5STom Zanussi 
170fbf31dd5STom Zanussi 	ret = check_key(in_key, key_len, cipher);
171fbf31dd5STom Zanussi 	if (ret)
172fbf31dd5STom Zanussi 		return ret;
173fbf31dd5STom Zanussi 
174fbf31dd5STom Zanussi 	memcpy(tctx->key, in_key, key_len);
175fbf31dd5STom Zanussi 	tctx->key_len = key_len;
176fbf31dd5STom Zanussi 	tctx->cipher = cipher;
177fbf31dd5STom Zanussi 
178fbf31dd5STom Zanussi 	return 0;
179fbf31dd5STom Zanussi }
180fbf31dd5STom Zanussi 
181fbf31dd5STom Zanussi /* Set key for symmetric cypher. */
kmb_ocs_sk_set_key(struct crypto_skcipher * tfm,const u8 * in_key,size_t key_len,enum ocs_cipher cipher)182fbf31dd5STom Zanussi static int kmb_ocs_sk_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
183fbf31dd5STom Zanussi 			      size_t key_len, enum ocs_cipher cipher)
184fbf31dd5STom Zanussi {
185fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm);
186fbf31dd5STom Zanussi 
187fbf31dd5STom Zanussi 	/* Fallback is used for AES with 192-bit key. */
188fbf31dd5STom Zanussi 	tctx->use_fallback = (cipher == OCS_AES &&
189fbf31dd5STom Zanussi 			      key_len == OCS_AES_KEYSIZE_192);
190fbf31dd5STom Zanussi 
191fbf31dd5STom Zanussi 	if (!tctx->use_fallback)
192fbf31dd5STom Zanussi 		return save_key(tctx, in_key, key_len, cipher);
193fbf31dd5STom Zanussi 
194fbf31dd5STom Zanussi 	crypto_sync_skcipher_clear_flags(tctx->sw_cipher.sk,
195fbf31dd5STom Zanussi 					 CRYPTO_TFM_REQ_MASK);
196fbf31dd5STom Zanussi 	crypto_sync_skcipher_set_flags(tctx->sw_cipher.sk,
197fbf31dd5STom Zanussi 				       tfm->base.crt_flags &
198fbf31dd5STom Zanussi 				       CRYPTO_TFM_REQ_MASK);
199fbf31dd5STom Zanussi 
200fbf31dd5STom Zanussi 	return crypto_sync_skcipher_setkey(tctx->sw_cipher.sk, in_key, key_len);
201fbf31dd5STom Zanussi }
202fbf31dd5STom Zanussi 
203fbf31dd5STom Zanussi /* Set key for AEAD cipher. */
kmb_ocs_aead_set_key(struct crypto_aead * tfm,const u8 * in_key,size_t key_len,enum ocs_cipher cipher)204fbf31dd5STom Zanussi static int kmb_ocs_aead_set_key(struct crypto_aead *tfm, const u8 *in_key,
205fbf31dd5STom Zanussi 				size_t key_len, enum ocs_cipher cipher)
206fbf31dd5STom Zanussi {
207fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_aead_ctx(tfm);
208fbf31dd5STom Zanussi 
209fbf31dd5STom Zanussi 	/* Fallback is used for AES with 192-bit key. */
210fbf31dd5STom Zanussi 	tctx->use_fallback = (cipher == OCS_AES &&
211fbf31dd5STom Zanussi 			      key_len == OCS_AES_KEYSIZE_192);
212fbf31dd5STom Zanussi 
213fbf31dd5STom Zanussi 	if (!tctx->use_fallback)
214fbf31dd5STom Zanussi 		return save_key(tctx, in_key, key_len, cipher);
215fbf31dd5STom Zanussi 
216fbf31dd5STom Zanussi 	crypto_aead_clear_flags(tctx->sw_cipher.aead, CRYPTO_TFM_REQ_MASK);
217fbf31dd5STom Zanussi 	crypto_aead_set_flags(tctx->sw_cipher.aead,
218fbf31dd5STom Zanussi 			      crypto_aead_get_flags(tfm) & CRYPTO_TFM_REQ_MASK);
219fbf31dd5STom Zanussi 
220fbf31dd5STom Zanussi 	return crypto_aead_setkey(tctx->sw_cipher.aead, in_key, key_len);
221fbf31dd5STom Zanussi }
222fbf31dd5STom Zanussi 
223fbf31dd5STom Zanussi /* Swap two AES blocks in SG lists. */
sg_swap_blocks(struct scatterlist * sgl,unsigned int nents,off_t blk1_offset,off_t blk2_offset)224fbf31dd5STom Zanussi static void sg_swap_blocks(struct scatterlist *sgl, unsigned int nents,
225fbf31dd5STom Zanussi 			   off_t blk1_offset, off_t blk2_offset)
226fbf31dd5STom Zanussi {
227fbf31dd5STom Zanussi 	u8 tmp_buf1[AES_BLOCK_SIZE], tmp_buf2[AES_BLOCK_SIZE];
228fbf31dd5STom Zanussi 
229fbf31dd5STom Zanussi 	/*
230fbf31dd5STom Zanussi 	 * No easy way to copy within sg list, so copy both blocks to temporary
231fbf31dd5STom Zanussi 	 * buffers first.
232fbf31dd5STom Zanussi 	 */
233fbf31dd5STom Zanussi 	sg_pcopy_to_buffer(sgl, nents, tmp_buf1, AES_BLOCK_SIZE, blk1_offset);
234fbf31dd5STom Zanussi 	sg_pcopy_to_buffer(sgl, nents, tmp_buf2, AES_BLOCK_SIZE, blk2_offset);
235fbf31dd5STom Zanussi 	sg_pcopy_from_buffer(sgl, nents, tmp_buf1, AES_BLOCK_SIZE, blk2_offset);
236fbf31dd5STom Zanussi 	sg_pcopy_from_buffer(sgl, nents, tmp_buf2, AES_BLOCK_SIZE, blk1_offset);
237fbf31dd5STom Zanussi }
238fbf31dd5STom Zanussi 
239fbf31dd5STom Zanussi /* Initialize request context to default values. */
ocs_aes_init_rctx(struct ocs_aes_rctx * rctx)240fbf31dd5STom Zanussi static void ocs_aes_init_rctx(struct ocs_aes_rctx *rctx)
241fbf31dd5STom Zanussi {
242fbf31dd5STom Zanussi 	/* Zero everything. */
243fbf31dd5STom Zanussi 	memset(rctx, 0, sizeof(*rctx));
244fbf31dd5STom Zanussi 
245fbf31dd5STom Zanussi 	/* Set initial value for DMA addresses. */
246fbf31dd5STom Zanussi 	rctx->src_dll.dma_addr = DMA_MAPPING_ERROR;
247fbf31dd5STom Zanussi 	rctx->dst_dll.dma_addr = DMA_MAPPING_ERROR;
248fbf31dd5STom Zanussi 	rctx->aad_src_dll.dma_addr = DMA_MAPPING_ERROR;
249fbf31dd5STom Zanussi 	rctx->aad_dst_dll.dma_addr = DMA_MAPPING_ERROR;
250fbf31dd5STom Zanussi }
251fbf31dd5STom Zanussi 
kmb_ocs_sk_validate_input(struct skcipher_request * req,enum ocs_mode mode)252fbf31dd5STom Zanussi static int kmb_ocs_sk_validate_input(struct skcipher_request *req,
253fbf31dd5STom Zanussi 				     enum ocs_mode mode)
254fbf31dd5STom Zanussi {
255fbf31dd5STom Zanussi 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
256fbf31dd5STom Zanussi 	int iv_size = crypto_skcipher_ivsize(tfm);
257fbf31dd5STom Zanussi 
258fbf31dd5STom Zanussi 	switch (mode) {
259fbf31dd5STom Zanussi 	case OCS_MODE_ECB:
260fbf31dd5STom Zanussi 		/* Ensure input length is multiple of block size */
261fbf31dd5STom Zanussi 		if (req->cryptlen % AES_BLOCK_SIZE != 0)
262fbf31dd5STom Zanussi 			return -EINVAL;
263fbf31dd5STom Zanussi 
264fbf31dd5STom Zanussi 		return 0;
265fbf31dd5STom Zanussi 
266fbf31dd5STom Zanussi 	case OCS_MODE_CBC:
267fbf31dd5STom Zanussi 		/* Ensure input length is multiple of block size */
268fbf31dd5STom Zanussi 		if (req->cryptlen % AES_BLOCK_SIZE != 0)
269fbf31dd5STom Zanussi 			return -EINVAL;
270fbf31dd5STom Zanussi 
271fbf31dd5STom Zanussi 		/* Ensure IV is present and block size in length */
272fbf31dd5STom Zanussi 		if (!req->iv || iv_size != AES_BLOCK_SIZE)
273fbf31dd5STom Zanussi 			return -EINVAL;
274fbf31dd5STom Zanussi 		/*
275fbf31dd5STom Zanussi 		 * NOTE: Since req->cryptlen == 0 case was already handled in
276fbf31dd5STom Zanussi 		 * kmb_ocs_sk_common(), the above two conditions also guarantee
277fbf31dd5STom Zanussi 		 * that: cryptlen >= iv_size
278fbf31dd5STom Zanussi 		 */
279fbf31dd5STom Zanussi 		return 0;
280fbf31dd5STom Zanussi 
281fbf31dd5STom Zanussi 	case OCS_MODE_CTR:
282fbf31dd5STom Zanussi 		/* Ensure IV is present and block size in length */
283fbf31dd5STom Zanussi 		if (!req->iv || iv_size != AES_BLOCK_SIZE)
284fbf31dd5STom Zanussi 			return -EINVAL;
285fbf31dd5STom Zanussi 		return 0;
286fbf31dd5STom Zanussi 
287fbf31dd5STom Zanussi 	case OCS_MODE_CTS:
288fbf31dd5STom Zanussi 		/* Ensure input length >= block size */
289fbf31dd5STom Zanussi 		if (req->cryptlen < AES_BLOCK_SIZE)
290fbf31dd5STom Zanussi 			return -EINVAL;
291fbf31dd5STom Zanussi 
292fbf31dd5STom Zanussi 		/* Ensure IV is present and block size in length */
293fbf31dd5STom Zanussi 		if (!req->iv || iv_size != AES_BLOCK_SIZE)
294fbf31dd5STom Zanussi 			return -EINVAL;
295fbf31dd5STom Zanussi 
296fbf31dd5STom Zanussi 		return 0;
297fbf31dd5STom Zanussi 	default:
298fbf31dd5STom Zanussi 		return -EINVAL;
299fbf31dd5STom Zanussi 	}
300fbf31dd5STom Zanussi }
301fbf31dd5STom Zanussi 
302fbf31dd5STom Zanussi /*
303fbf31dd5STom Zanussi  * Called by encrypt() / decrypt() skcipher functions.
304fbf31dd5STom Zanussi  *
305fbf31dd5STom Zanussi  * Use fallback if needed, otherwise initialize context and enqueue request
306fbf31dd5STom Zanussi  * into engine.
307fbf31dd5STom Zanussi  */
kmb_ocs_sk_common(struct skcipher_request * req,enum ocs_cipher cipher,enum ocs_instruction instruction,enum ocs_mode mode)308fbf31dd5STom Zanussi static int kmb_ocs_sk_common(struct skcipher_request *req,
309fbf31dd5STom Zanussi 			     enum ocs_cipher cipher,
310fbf31dd5STom Zanussi 			     enum ocs_instruction instruction,
311fbf31dd5STom Zanussi 			     enum ocs_mode mode)
312fbf31dd5STom Zanussi {
313fbf31dd5STom Zanussi 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
314fbf31dd5STom Zanussi 	struct ocs_aes_rctx *rctx = skcipher_request_ctx(req);
315fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm);
316fbf31dd5STom Zanussi 	struct ocs_aes_dev *aes_dev;
317fbf31dd5STom Zanussi 	int rc;
318fbf31dd5STom Zanussi 
319fbf31dd5STom Zanussi 	if (tctx->use_fallback) {
320fbf31dd5STom Zanussi 		SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, tctx->sw_cipher.sk);
321fbf31dd5STom Zanussi 
322fbf31dd5STom Zanussi 		skcipher_request_set_sync_tfm(subreq, tctx->sw_cipher.sk);
323fbf31dd5STom Zanussi 		skcipher_request_set_callback(subreq, req->base.flags, NULL,
324fbf31dd5STom Zanussi 					      NULL);
325fbf31dd5STom Zanussi 		skcipher_request_set_crypt(subreq, req->src, req->dst,
326fbf31dd5STom Zanussi 					   req->cryptlen, req->iv);
327fbf31dd5STom Zanussi 
328fbf31dd5STom Zanussi 		if (instruction == OCS_ENCRYPT)
329fbf31dd5STom Zanussi 			rc = crypto_skcipher_encrypt(subreq);
330fbf31dd5STom Zanussi 		else
331fbf31dd5STom Zanussi 			rc = crypto_skcipher_decrypt(subreq);
332fbf31dd5STom Zanussi 
333fbf31dd5STom Zanussi 		skcipher_request_zero(subreq);
334fbf31dd5STom Zanussi 
335fbf31dd5STom Zanussi 		return rc;
336fbf31dd5STom Zanussi 	}
337fbf31dd5STom Zanussi 
338fbf31dd5STom Zanussi 	/*
339fbf31dd5STom Zanussi 	 * If cryptlen == 0, no processing needed for ECB, CBC and CTR.
340fbf31dd5STom Zanussi 	 *
341fbf31dd5STom Zanussi 	 * For CTS continue: kmb_ocs_sk_validate_input() will return -EINVAL.
342fbf31dd5STom Zanussi 	 */
343fbf31dd5STom Zanussi 	if (!req->cryptlen && mode != OCS_MODE_CTS)
344fbf31dd5STom Zanussi 		return 0;
345fbf31dd5STom Zanussi 
346fbf31dd5STom Zanussi 	rc = kmb_ocs_sk_validate_input(req, mode);
347fbf31dd5STom Zanussi 	if (rc)
348fbf31dd5STom Zanussi 		return rc;
349fbf31dd5STom Zanussi 
350fbf31dd5STom Zanussi 	aes_dev = kmb_ocs_aes_find_dev(tctx);
351fbf31dd5STom Zanussi 	if (!aes_dev)
352fbf31dd5STom Zanussi 		return -ENODEV;
353fbf31dd5STom Zanussi 
354fbf31dd5STom Zanussi 	if (cipher != tctx->cipher)
355fbf31dd5STom Zanussi 		return -EINVAL;
356fbf31dd5STom Zanussi 
357fbf31dd5STom Zanussi 	ocs_aes_init_rctx(rctx);
358fbf31dd5STom Zanussi 	rctx->instruction = instruction;
359fbf31dd5STom Zanussi 	rctx->mode = mode;
360fbf31dd5STom Zanussi 
361fbf31dd5STom Zanussi 	return crypto_transfer_skcipher_request_to_engine(aes_dev->engine, req);
362fbf31dd5STom Zanussi }
363fbf31dd5STom Zanussi 
cleanup_ocs_dma_linked_list(struct device * dev,struct ocs_dll_desc * dll)364fbf31dd5STom Zanussi static void cleanup_ocs_dma_linked_list(struct device *dev,
365fbf31dd5STom Zanussi 					struct ocs_dll_desc *dll)
366fbf31dd5STom Zanussi {
367fbf31dd5STom Zanussi 	if (dll->vaddr)
368fbf31dd5STom Zanussi 		dma_free_coherent(dev, dll->size, dll->vaddr, dll->dma_addr);
369fbf31dd5STom Zanussi 	dll->vaddr = NULL;
370fbf31dd5STom Zanussi 	dll->size = 0;
371fbf31dd5STom Zanussi 	dll->dma_addr = DMA_MAPPING_ERROR;
372fbf31dd5STom Zanussi }
373fbf31dd5STom Zanussi 
kmb_ocs_sk_dma_cleanup(struct skcipher_request * req)374fbf31dd5STom Zanussi static void kmb_ocs_sk_dma_cleanup(struct skcipher_request *req)
375fbf31dd5STom Zanussi {
376fbf31dd5STom Zanussi 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
377fbf31dd5STom Zanussi 	struct ocs_aes_rctx *rctx = skcipher_request_ctx(req);
378fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm);
379fbf31dd5STom Zanussi 	struct device *dev = tctx->aes_dev->dev;
380fbf31dd5STom Zanussi 
381fbf31dd5STom Zanussi 	if (rctx->src_dma_count) {
382fbf31dd5STom Zanussi 		dma_unmap_sg(dev, req->src, rctx->src_nents, DMA_TO_DEVICE);
383fbf31dd5STom Zanussi 		rctx->src_dma_count = 0;
384fbf31dd5STom Zanussi 	}
385fbf31dd5STom Zanussi 
386fbf31dd5STom Zanussi 	if (rctx->dst_dma_count) {
387fbf31dd5STom Zanussi 		dma_unmap_sg(dev, req->dst, rctx->dst_nents, rctx->in_place ?
388fbf31dd5STom Zanussi 							     DMA_BIDIRECTIONAL :
389fbf31dd5STom Zanussi 							     DMA_FROM_DEVICE);
390fbf31dd5STom Zanussi 		rctx->dst_dma_count = 0;
391fbf31dd5STom Zanussi 	}
392fbf31dd5STom Zanussi 
393fbf31dd5STom Zanussi 	/* Clean up OCS DMA linked lists */
394fbf31dd5STom Zanussi 	cleanup_ocs_dma_linked_list(dev, &rctx->src_dll);
395fbf31dd5STom Zanussi 	cleanup_ocs_dma_linked_list(dev, &rctx->dst_dll);
396fbf31dd5STom Zanussi }
397fbf31dd5STom Zanussi 
kmb_ocs_sk_prepare_inplace(struct skcipher_request * req)398fbf31dd5STom Zanussi static int kmb_ocs_sk_prepare_inplace(struct skcipher_request *req)
399fbf31dd5STom Zanussi {
400fbf31dd5STom Zanussi 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
401fbf31dd5STom Zanussi 	struct ocs_aes_rctx *rctx = skcipher_request_ctx(req);
402fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm);
403fbf31dd5STom Zanussi 	int iv_size = crypto_skcipher_ivsize(tfm);
404fbf31dd5STom Zanussi 	int rc;
405fbf31dd5STom Zanussi 
406fbf31dd5STom Zanussi 	/*
407fbf31dd5STom Zanussi 	 * For CBC decrypt, save last block (iv) to last_ct_blk buffer.
408fbf31dd5STom Zanussi 	 *
409fbf31dd5STom Zanussi 	 * Note: if we are here, we already checked that cryptlen >= iv_size
410fbf31dd5STom Zanussi 	 * and iv_size == AES_BLOCK_SIZE (i.e., the size of last_ct_blk); see
411fbf31dd5STom Zanussi 	 * kmb_ocs_sk_validate_input().
412fbf31dd5STom Zanussi 	 */
413fbf31dd5STom Zanussi 	if (rctx->mode == OCS_MODE_CBC && rctx->instruction == OCS_DECRYPT)
414fbf31dd5STom Zanussi 		scatterwalk_map_and_copy(rctx->last_ct_blk, req->src,
415fbf31dd5STom Zanussi 					 req->cryptlen - iv_size, iv_size, 0);
416fbf31dd5STom Zanussi 
417fbf31dd5STom Zanussi 	/* For CTS decrypt, swap last two blocks, if needed. */
418fbf31dd5STom Zanussi 	if (rctx->cts_swap && rctx->instruction == OCS_DECRYPT)
419fbf31dd5STom Zanussi 		sg_swap_blocks(req->dst, rctx->dst_nents,
420fbf31dd5STom Zanussi 			       req->cryptlen - AES_BLOCK_SIZE,
421fbf31dd5STom Zanussi 			       req->cryptlen - (2 * AES_BLOCK_SIZE));
422fbf31dd5STom Zanussi 
423fbf31dd5STom Zanussi 	/* src and dst buffers are the same, use bidirectional DMA mapping. */
424fbf31dd5STom Zanussi 	rctx->dst_dma_count = dma_map_sg(tctx->aes_dev->dev, req->dst,
425fbf31dd5STom Zanussi 					 rctx->dst_nents, DMA_BIDIRECTIONAL);
426fbf31dd5STom Zanussi 	if (rctx->dst_dma_count == 0) {
427fbf31dd5STom Zanussi 		dev_err(tctx->aes_dev->dev, "Failed to map destination sg\n");
428fbf31dd5STom Zanussi 		return -ENOMEM;
429fbf31dd5STom Zanussi 	}
430fbf31dd5STom Zanussi 
431fbf31dd5STom Zanussi 	/* Create DST linked list */
432fbf31dd5STom Zanussi 	rc = ocs_create_linked_list_from_sg(tctx->aes_dev, req->dst,
433fbf31dd5STom Zanussi 					    rctx->dst_dma_count, &rctx->dst_dll,
434fbf31dd5STom Zanussi 					    req->cryptlen, 0);
435fbf31dd5STom Zanussi 	if (rc)
436fbf31dd5STom Zanussi 		return rc;
437fbf31dd5STom Zanussi 	/*
438fbf31dd5STom Zanussi 	 * If descriptor creation was successful, set the src_dll.dma_addr to
439fbf31dd5STom Zanussi 	 * the value of dst_dll.dma_addr, as we do in-place AES operation on
440fbf31dd5STom Zanussi 	 * the src.
441fbf31dd5STom Zanussi 	 */
442fbf31dd5STom Zanussi 	rctx->src_dll.dma_addr = rctx->dst_dll.dma_addr;
443fbf31dd5STom Zanussi 
444fbf31dd5STom Zanussi 	return 0;
445fbf31dd5STom Zanussi }
446fbf31dd5STom Zanussi 
kmb_ocs_sk_prepare_notinplace(struct skcipher_request * req)447fbf31dd5STom Zanussi static int kmb_ocs_sk_prepare_notinplace(struct skcipher_request *req)
448fbf31dd5STom Zanussi {
449fbf31dd5STom Zanussi 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
450fbf31dd5STom Zanussi 	struct ocs_aes_rctx *rctx = skcipher_request_ctx(req);
451fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm);
452fbf31dd5STom Zanussi 	int rc;
453fbf31dd5STom Zanussi 
454fbf31dd5STom Zanussi 	rctx->src_nents =  sg_nents_for_len(req->src, req->cryptlen);
455fbf31dd5STom Zanussi 	if (rctx->src_nents < 0)
456fbf31dd5STom Zanussi 		return -EBADMSG;
457fbf31dd5STom Zanussi 
458fbf31dd5STom Zanussi 	/* Map SRC SG. */
459fbf31dd5STom Zanussi 	rctx->src_dma_count = dma_map_sg(tctx->aes_dev->dev, req->src,
460fbf31dd5STom Zanussi 					 rctx->src_nents, DMA_TO_DEVICE);
461fbf31dd5STom Zanussi 	if (rctx->src_dma_count == 0) {
462fbf31dd5STom Zanussi 		dev_err(tctx->aes_dev->dev, "Failed to map source sg\n");
463fbf31dd5STom Zanussi 		return -ENOMEM;
464fbf31dd5STom Zanussi 	}
465fbf31dd5STom Zanussi 
466fbf31dd5STom Zanussi 	/* Create SRC linked list */
467fbf31dd5STom Zanussi 	rc = ocs_create_linked_list_from_sg(tctx->aes_dev, req->src,
468fbf31dd5STom Zanussi 					    rctx->src_dma_count, &rctx->src_dll,
469fbf31dd5STom Zanussi 					    req->cryptlen, 0);
470fbf31dd5STom Zanussi 	if (rc)
471fbf31dd5STom Zanussi 		return rc;
472fbf31dd5STom Zanussi 
473fbf31dd5STom Zanussi 	/* Map DST SG. */
474fbf31dd5STom Zanussi 	rctx->dst_dma_count = dma_map_sg(tctx->aes_dev->dev, req->dst,
475fbf31dd5STom Zanussi 					 rctx->dst_nents, DMA_FROM_DEVICE);
476fbf31dd5STom Zanussi 	if (rctx->dst_dma_count == 0) {
477fbf31dd5STom Zanussi 		dev_err(tctx->aes_dev->dev, "Failed to map destination sg\n");
478fbf31dd5STom Zanussi 		return -ENOMEM;
479fbf31dd5STom Zanussi 	}
480fbf31dd5STom Zanussi 
481fbf31dd5STom Zanussi 	/* Create DST linked list */
482fbf31dd5STom Zanussi 	rc = ocs_create_linked_list_from_sg(tctx->aes_dev, req->dst,
483fbf31dd5STom Zanussi 					    rctx->dst_dma_count, &rctx->dst_dll,
484fbf31dd5STom Zanussi 					    req->cryptlen, 0);
485fbf31dd5STom Zanussi 	if (rc)
486fbf31dd5STom Zanussi 		return rc;
487fbf31dd5STom Zanussi 
488fbf31dd5STom Zanussi 	/* If this is not a CTS decrypt operation with swapping, we are done. */
489fbf31dd5STom Zanussi 	if (!(rctx->cts_swap && rctx->instruction == OCS_DECRYPT))
490fbf31dd5STom Zanussi 		return 0;
491fbf31dd5STom Zanussi 
492fbf31dd5STom Zanussi 	/*
493fbf31dd5STom Zanussi 	 * Otherwise, we have to copy src to dst (as we cannot modify src).
494fbf31dd5STom Zanussi 	 * Use OCS AES bypass mode to copy src to dst via DMA.
495fbf31dd5STom Zanussi 	 *
496fbf31dd5STom Zanussi 	 * NOTE: for anything other than small data sizes this is rather
497fbf31dd5STom Zanussi 	 * inefficient.
498fbf31dd5STom Zanussi 	 */
499fbf31dd5STom Zanussi 	rc = ocs_aes_bypass_op(tctx->aes_dev, rctx->dst_dll.dma_addr,
500fbf31dd5STom Zanussi 			       rctx->src_dll.dma_addr, req->cryptlen);
501fbf31dd5STom Zanussi 	if (rc)
502fbf31dd5STom Zanussi 		return rc;
503fbf31dd5STom Zanussi 
504fbf31dd5STom Zanussi 	/*
505fbf31dd5STom Zanussi 	 * Now dst == src, so clean up what we did so far and use in_place
506fbf31dd5STom Zanussi 	 * logic.
507fbf31dd5STom Zanussi 	 */
508fbf31dd5STom Zanussi 	kmb_ocs_sk_dma_cleanup(req);
509fbf31dd5STom Zanussi 	rctx->in_place = true;
510fbf31dd5STom Zanussi 
511fbf31dd5STom Zanussi 	return kmb_ocs_sk_prepare_inplace(req);
512fbf31dd5STom Zanussi }
513fbf31dd5STom Zanussi 
kmb_ocs_sk_run(struct skcipher_request * req)514fbf31dd5STom Zanussi static int kmb_ocs_sk_run(struct skcipher_request *req)
515fbf31dd5STom Zanussi {
516fbf31dd5STom Zanussi 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
517fbf31dd5STom Zanussi 	struct ocs_aes_rctx *rctx = skcipher_request_ctx(req);
518fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm);
519fbf31dd5STom Zanussi 	struct ocs_aes_dev *aes_dev = tctx->aes_dev;
520fbf31dd5STom Zanussi 	int iv_size = crypto_skcipher_ivsize(tfm);
521fbf31dd5STom Zanussi 	int rc;
522fbf31dd5STom Zanussi 
523fbf31dd5STom Zanussi 	rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen);
524fbf31dd5STom Zanussi 	if (rctx->dst_nents < 0)
525fbf31dd5STom Zanussi 		return -EBADMSG;
526fbf31dd5STom Zanussi 
527fbf31dd5STom Zanussi 	/*
528fbf31dd5STom Zanussi 	 * If 2 blocks or greater, and multiple of block size swap last two
529fbf31dd5STom Zanussi 	 * blocks to be compatible with other crypto API CTS implementations:
530fbf31dd5STom Zanussi 	 * OCS mode uses CBC-CS2, whereas other crypto API implementations use
531fbf31dd5STom Zanussi 	 * CBC-CS3.
532fbf31dd5STom Zanussi 	 * CBC-CS2 and CBC-CS3 defined by:
533fbf31dd5STom Zanussi 	 * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a-add.pdf
534fbf31dd5STom Zanussi 	 */
535fbf31dd5STom Zanussi 	rctx->cts_swap = (rctx->mode == OCS_MODE_CTS &&
536fbf31dd5STom Zanussi 			  req->cryptlen > AES_BLOCK_SIZE &&
537fbf31dd5STom Zanussi 			  req->cryptlen % AES_BLOCK_SIZE == 0);
538fbf31dd5STom Zanussi 
539fbf31dd5STom Zanussi 	rctx->in_place = (req->src == req->dst);
540fbf31dd5STom Zanussi 
541fbf31dd5STom Zanussi 	if (rctx->in_place)
542fbf31dd5STom Zanussi 		rc = kmb_ocs_sk_prepare_inplace(req);
543fbf31dd5STom Zanussi 	else
544fbf31dd5STom Zanussi 		rc = kmb_ocs_sk_prepare_notinplace(req);
545fbf31dd5STom Zanussi 
546fbf31dd5STom Zanussi 	if (rc)
547fbf31dd5STom Zanussi 		goto error;
548fbf31dd5STom Zanussi 
549fbf31dd5STom Zanussi 	rc = ocs_aes_op(aes_dev, rctx->mode, tctx->cipher, rctx->instruction,
550fbf31dd5STom Zanussi 			rctx->dst_dll.dma_addr, rctx->src_dll.dma_addr,
551fbf31dd5STom Zanussi 			req->cryptlen, req->iv, iv_size);
552fbf31dd5STom Zanussi 	if (rc)
553fbf31dd5STom Zanussi 		goto error;
554fbf31dd5STom Zanussi 
555fbf31dd5STom Zanussi 	/* Clean-up DMA before further processing output. */
556fbf31dd5STom Zanussi 	kmb_ocs_sk_dma_cleanup(req);
557fbf31dd5STom Zanussi 
558fbf31dd5STom Zanussi 	/* For CTS Encrypt, swap last 2 blocks, if needed. */
559fbf31dd5STom Zanussi 	if (rctx->cts_swap && rctx->instruction == OCS_ENCRYPT) {
560fbf31dd5STom Zanussi 		sg_swap_blocks(req->dst, rctx->dst_nents,
561fbf31dd5STom Zanussi 			       req->cryptlen - AES_BLOCK_SIZE,
562fbf31dd5STom Zanussi 			       req->cryptlen - (2 * AES_BLOCK_SIZE));
563fbf31dd5STom Zanussi 		return 0;
564fbf31dd5STom Zanussi 	}
565fbf31dd5STom Zanussi 
566fbf31dd5STom Zanussi 	/* For CBC copy IV to req->IV. */
567fbf31dd5STom Zanussi 	if (rctx->mode == OCS_MODE_CBC) {
568fbf31dd5STom Zanussi 		/* CBC encrypt case. */
569fbf31dd5STom Zanussi 		if (rctx->instruction == OCS_ENCRYPT) {
570fbf31dd5STom Zanussi 			scatterwalk_map_and_copy(req->iv, req->dst,
571fbf31dd5STom Zanussi 						 req->cryptlen - iv_size,
572fbf31dd5STom Zanussi 						 iv_size, 0);
573fbf31dd5STom Zanussi 			return 0;
574fbf31dd5STom Zanussi 		}
575fbf31dd5STom Zanussi 		/* CBC decrypt case. */
576fbf31dd5STom Zanussi 		if (rctx->in_place)
577fbf31dd5STom Zanussi 			memcpy(req->iv, rctx->last_ct_blk, iv_size);
578fbf31dd5STom Zanussi 		else
579fbf31dd5STom Zanussi 			scatterwalk_map_and_copy(req->iv, req->src,
580fbf31dd5STom Zanussi 						 req->cryptlen - iv_size,
581fbf31dd5STom Zanussi 						 iv_size, 0);
582fbf31dd5STom Zanussi 		return 0;
583fbf31dd5STom Zanussi 	}
584fbf31dd5STom Zanussi 	/* For all other modes there's nothing to do. */
585fbf31dd5STom Zanussi 
586fbf31dd5STom Zanussi 	return 0;
587fbf31dd5STom Zanussi 
588fbf31dd5STom Zanussi error:
589fbf31dd5STom Zanussi 	kmb_ocs_sk_dma_cleanup(req);
590fbf31dd5STom Zanussi 
591fbf31dd5STom Zanussi 	return rc;
592fbf31dd5STom Zanussi }
593fbf31dd5STom Zanussi 
kmb_ocs_aead_validate_input(struct aead_request * req,enum ocs_instruction instruction,enum ocs_mode mode)594fbf31dd5STom Zanussi static int kmb_ocs_aead_validate_input(struct aead_request *req,
595fbf31dd5STom Zanussi 				       enum ocs_instruction instruction,
596fbf31dd5STom Zanussi 				       enum ocs_mode mode)
597fbf31dd5STom Zanussi {
598fbf31dd5STom Zanussi 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
599fbf31dd5STom Zanussi 	int tag_size = crypto_aead_authsize(tfm);
600fbf31dd5STom Zanussi 	int iv_size = crypto_aead_ivsize(tfm);
601fbf31dd5STom Zanussi 
602fbf31dd5STom Zanussi 	/* For decrypt crytplen == len(PT) + len(tag). */
603fbf31dd5STom Zanussi 	if (instruction == OCS_DECRYPT && req->cryptlen < tag_size)
604fbf31dd5STom Zanussi 		return -EINVAL;
605fbf31dd5STom Zanussi 
606fbf31dd5STom Zanussi 	/* IV is mandatory. */
607fbf31dd5STom Zanussi 	if (!req->iv)
608fbf31dd5STom Zanussi 		return -EINVAL;
609fbf31dd5STom Zanussi 
610fbf31dd5STom Zanussi 	switch (mode) {
611fbf31dd5STom Zanussi 	case OCS_MODE_GCM:
612fbf31dd5STom Zanussi 		if (iv_size != GCM_AES_IV_SIZE)
613fbf31dd5STom Zanussi 			return -EINVAL;
614fbf31dd5STom Zanussi 
615fbf31dd5STom Zanussi 		return 0;
616fbf31dd5STom Zanussi 
617fbf31dd5STom Zanussi 	case OCS_MODE_CCM:
618fbf31dd5STom Zanussi 		/* Ensure IV is present and block size in length */
619fbf31dd5STom Zanussi 		if (iv_size != AES_BLOCK_SIZE)
620fbf31dd5STom Zanussi 			return -EINVAL;
621fbf31dd5STom Zanussi 
622fbf31dd5STom Zanussi 		return 0;
623fbf31dd5STom Zanussi 
624fbf31dd5STom Zanussi 	default:
625fbf31dd5STom Zanussi 		return -EINVAL;
626fbf31dd5STom Zanussi 	}
627fbf31dd5STom Zanussi }
628fbf31dd5STom Zanussi 
629fbf31dd5STom Zanussi /*
630fbf31dd5STom Zanussi  * Called by encrypt() / decrypt() aead functions.
631fbf31dd5STom Zanussi  *
632fbf31dd5STom Zanussi  * Use fallback if needed, otherwise initialize context and enqueue request
633fbf31dd5STom Zanussi  * into engine.
634fbf31dd5STom Zanussi  */
kmb_ocs_aead_common(struct aead_request * req,enum ocs_cipher cipher,enum ocs_instruction instruction,enum ocs_mode mode)635fbf31dd5STom Zanussi static int kmb_ocs_aead_common(struct aead_request *req,
636fbf31dd5STom Zanussi 			       enum ocs_cipher cipher,
637fbf31dd5STom Zanussi 			       enum ocs_instruction instruction,
638fbf31dd5STom Zanussi 			       enum ocs_mode mode)
639fbf31dd5STom Zanussi {
640fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
641fbf31dd5STom Zanussi 	struct ocs_aes_rctx *rctx = aead_request_ctx(req);
642fbf31dd5STom Zanussi 	struct ocs_aes_dev *dd;
643fbf31dd5STom Zanussi 	int rc;
644fbf31dd5STom Zanussi 
645fbf31dd5STom Zanussi 	if (tctx->use_fallback) {
646fbf31dd5STom Zanussi 		struct aead_request *subreq = aead_request_ctx(req);
647fbf31dd5STom Zanussi 
648fbf31dd5STom Zanussi 		aead_request_set_tfm(subreq, tctx->sw_cipher.aead);
649fbf31dd5STom Zanussi 		aead_request_set_callback(subreq, req->base.flags,
650fbf31dd5STom Zanussi 					  req->base.complete, req->base.data);
651fbf31dd5STom Zanussi 		aead_request_set_crypt(subreq, req->src, req->dst,
652fbf31dd5STom Zanussi 				       req->cryptlen, req->iv);
653fbf31dd5STom Zanussi 		aead_request_set_ad(subreq, req->assoclen);
654fbf31dd5STom Zanussi 		rc = crypto_aead_setauthsize(tctx->sw_cipher.aead,
655fbf31dd5STom Zanussi 					     crypto_aead_authsize(crypto_aead_reqtfm(req)));
656fbf31dd5STom Zanussi 		if (rc)
657fbf31dd5STom Zanussi 			return rc;
658fbf31dd5STom Zanussi 
659fbf31dd5STom Zanussi 		return (instruction == OCS_ENCRYPT) ?
660fbf31dd5STom Zanussi 		       crypto_aead_encrypt(subreq) :
661fbf31dd5STom Zanussi 		       crypto_aead_decrypt(subreq);
662fbf31dd5STom Zanussi 	}
663fbf31dd5STom Zanussi 
664fbf31dd5STom Zanussi 	rc = kmb_ocs_aead_validate_input(req, instruction, mode);
665fbf31dd5STom Zanussi 	if (rc)
666fbf31dd5STom Zanussi 		return rc;
667fbf31dd5STom Zanussi 
668fbf31dd5STom Zanussi 	dd = kmb_ocs_aes_find_dev(tctx);
669fbf31dd5STom Zanussi 	if (!dd)
670fbf31dd5STom Zanussi 		return -ENODEV;
671fbf31dd5STom Zanussi 
672fbf31dd5STom Zanussi 	if (cipher != tctx->cipher)
673fbf31dd5STom Zanussi 		return -EINVAL;
674fbf31dd5STom Zanussi 
675fbf31dd5STom Zanussi 	ocs_aes_init_rctx(rctx);
676fbf31dd5STom Zanussi 	rctx->instruction = instruction;
677fbf31dd5STom Zanussi 	rctx->mode = mode;
678fbf31dd5STom Zanussi 
679fbf31dd5STom Zanussi 	return crypto_transfer_aead_request_to_engine(dd->engine, req);
680fbf31dd5STom Zanussi }
681fbf31dd5STom Zanussi 
kmb_ocs_aead_dma_cleanup(struct aead_request * req)682fbf31dd5STom Zanussi static void kmb_ocs_aead_dma_cleanup(struct aead_request *req)
683fbf31dd5STom Zanussi {
684fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
685fbf31dd5STom Zanussi 	struct ocs_aes_rctx *rctx = aead_request_ctx(req);
686fbf31dd5STom Zanussi 	struct device *dev = tctx->aes_dev->dev;
687fbf31dd5STom Zanussi 
688fbf31dd5STom Zanussi 	if (rctx->src_dma_count) {
689fbf31dd5STom Zanussi 		dma_unmap_sg(dev, req->src, rctx->src_nents, DMA_TO_DEVICE);
690fbf31dd5STom Zanussi 		rctx->src_dma_count = 0;
691fbf31dd5STom Zanussi 	}
692fbf31dd5STom Zanussi 
693fbf31dd5STom Zanussi 	if (rctx->dst_dma_count) {
694fbf31dd5STom Zanussi 		dma_unmap_sg(dev, req->dst, rctx->dst_nents, rctx->in_place ?
695fbf31dd5STom Zanussi 							     DMA_BIDIRECTIONAL :
696fbf31dd5STom Zanussi 							     DMA_FROM_DEVICE);
697fbf31dd5STom Zanussi 		rctx->dst_dma_count = 0;
698fbf31dd5STom Zanussi 	}
699fbf31dd5STom Zanussi 	/* Clean up OCS DMA linked lists */
700fbf31dd5STom Zanussi 	cleanup_ocs_dma_linked_list(dev, &rctx->src_dll);
701fbf31dd5STom Zanussi 	cleanup_ocs_dma_linked_list(dev, &rctx->dst_dll);
702fbf31dd5STom Zanussi 	cleanup_ocs_dma_linked_list(dev, &rctx->aad_src_dll);
703fbf31dd5STom Zanussi 	cleanup_ocs_dma_linked_list(dev, &rctx->aad_dst_dll);
704fbf31dd5STom Zanussi }
705fbf31dd5STom Zanussi 
706fbf31dd5STom Zanussi /**
707fbf31dd5STom Zanussi  * kmb_ocs_aead_dma_prepare() - Do DMA mapping for AEAD processing.
708fbf31dd5STom Zanussi  * @req:		The AEAD request being processed.
709fbf31dd5STom Zanussi  * @src_dll_size:	Where to store the length of the data mapped into the
710fbf31dd5STom Zanussi  *			src_dll OCS DMA list.
711fbf31dd5STom Zanussi  *
712fbf31dd5STom Zanussi  * Do the following:
713fbf31dd5STom Zanussi  * - DMA map req->src and req->dst
714fbf31dd5STom Zanussi  * - Initialize the following OCS DMA linked lists: rctx->src_dll,
715fbf31dd5STom Zanussi  *   rctx->dst_dll, rctx->aad_src_dll and rxtc->aad_dst_dll.
716fbf31dd5STom Zanussi  *
717fbf31dd5STom Zanussi  * Return: 0 on success, negative error code otherwise.
718fbf31dd5STom Zanussi  */
kmb_ocs_aead_dma_prepare(struct aead_request * req,u32 * src_dll_size)719fbf31dd5STom Zanussi static int kmb_ocs_aead_dma_prepare(struct aead_request *req, u32 *src_dll_size)
720fbf31dd5STom Zanussi {
721fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
722fbf31dd5STom Zanussi 	const int tag_size = crypto_aead_authsize(crypto_aead_reqtfm(req));
723fbf31dd5STom Zanussi 	struct ocs_aes_rctx *rctx = aead_request_ctx(req);
724fbf31dd5STom Zanussi 	u32 in_size;	/* The length of the data to be mapped by src_dll. */
725fbf31dd5STom Zanussi 	u32 out_size;	/* The length of the data to be mapped by dst_dll. */
726fbf31dd5STom Zanussi 	u32 dst_size;	/* The length of the data in dst_sg. */
727fbf31dd5STom Zanussi 	int rc;
728fbf31dd5STom Zanussi 
729fbf31dd5STom Zanussi 	/* Get number of entries in input data SG list. */
730fbf31dd5STom Zanussi 	rctx->src_nents = sg_nents_for_len(req->src,
731fbf31dd5STom Zanussi 					   req->assoclen + req->cryptlen);
732fbf31dd5STom Zanussi 	if (rctx->src_nents < 0)
733fbf31dd5STom Zanussi 		return -EBADMSG;
734fbf31dd5STom Zanussi 
735fbf31dd5STom Zanussi 	if (rctx->instruction == OCS_DECRYPT) {
736fbf31dd5STom Zanussi 		/*
737fbf31dd5STom Zanussi 		 * For decrypt:
738fbf31dd5STom Zanussi 		 * - src sg list is:		AAD|CT|tag
739fbf31dd5STom Zanussi 		 * - dst sg list expects:	AAD|PT
740fbf31dd5STom Zanussi 		 *
741fbf31dd5STom Zanussi 		 * in_size == len(CT); out_size == len(PT)
742fbf31dd5STom Zanussi 		 */
743fbf31dd5STom Zanussi 
744fbf31dd5STom Zanussi 		/* req->cryptlen includes both CT and tag. */
745fbf31dd5STom Zanussi 		in_size = req->cryptlen - tag_size;
746fbf31dd5STom Zanussi 
747fbf31dd5STom Zanussi 		/* out_size = PT size == CT size */
748fbf31dd5STom Zanussi 		out_size = in_size;
749fbf31dd5STom Zanussi 
750fbf31dd5STom Zanussi 		/* len(dst_sg) == len(AAD) + len(PT) */
751fbf31dd5STom Zanussi 		dst_size = req->assoclen + out_size;
752fbf31dd5STom Zanussi 
753fbf31dd5STom Zanussi 		/*
754fbf31dd5STom Zanussi 		 * Copy tag from source SG list to 'in_tag' buffer.
755fbf31dd5STom Zanussi 		 *
756fbf31dd5STom Zanussi 		 * Note: this needs to be done here, before DMA mapping src_sg.
757fbf31dd5STom Zanussi 		 */
758fbf31dd5STom Zanussi 		sg_pcopy_to_buffer(req->src, rctx->src_nents, rctx->in_tag,
759fbf31dd5STom Zanussi 				   tag_size, req->assoclen + in_size);
760fbf31dd5STom Zanussi 
761fbf31dd5STom Zanussi 	} else { /* OCS_ENCRYPT */
762fbf31dd5STom Zanussi 		/*
763fbf31dd5STom Zanussi 		 * For encrypt:
764fbf31dd5STom Zanussi 		 *	src sg list is:		AAD|PT
765fbf31dd5STom Zanussi 		 *	dst sg list expects:	AAD|CT|tag
766fbf31dd5STom Zanussi 		 */
767fbf31dd5STom Zanussi 		/* in_size == len(PT) */
768fbf31dd5STom Zanussi 		in_size = req->cryptlen;
769fbf31dd5STom Zanussi 
770fbf31dd5STom Zanussi 		/*
771fbf31dd5STom Zanussi 		 * In CCM mode the OCS engine appends the tag to the ciphertext,
772fbf31dd5STom Zanussi 		 * but in GCM mode the tag must be read from the tag registers
773fbf31dd5STom Zanussi 		 * and appended manually below
774fbf31dd5STom Zanussi 		 */
775fbf31dd5STom Zanussi 		out_size = (rctx->mode == OCS_MODE_CCM) ? in_size + tag_size :
776fbf31dd5STom Zanussi 							  in_size;
777fbf31dd5STom Zanussi 		/* len(dst_sg) == len(AAD) + len(CT) + len(tag) */
778fbf31dd5STom Zanussi 		dst_size = req->assoclen + in_size + tag_size;
779fbf31dd5STom Zanussi 	}
780fbf31dd5STom Zanussi 	*src_dll_size = in_size;
781fbf31dd5STom Zanussi 
782fbf31dd5STom Zanussi 	/* Get number of entries in output data SG list. */
783fbf31dd5STom Zanussi 	rctx->dst_nents = sg_nents_for_len(req->dst, dst_size);
784fbf31dd5STom Zanussi 	if (rctx->dst_nents < 0)
785fbf31dd5STom Zanussi 		return -EBADMSG;
786fbf31dd5STom Zanussi 
787fbf31dd5STom Zanussi 	rctx->in_place = (req->src == req->dst) ? 1 : 0;
788fbf31dd5STom Zanussi 
789fbf31dd5STom Zanussi 	/* Map destination; use bidirectional mapping for in-place case. */
790fbf31dd5STom Zanussi 	rctx->dst_dma_count = dma_map_sg(tctx->aes_dev->dev, req->dst,
791fbf31dd5STom Zanussi 					 rctx->dst_nents,
792fbf31dd5STom Zanussi 					 rctx->in_place ? DMA_BIDIRECTIONAL :
793fbf31dd5STom Zanussi 							  DMA_FROM_DEVICE);
794fbf31dd5STom Zanussi 	if (rctx->dst_dma_count == 0 && rctx->dst_nents != 0) {
795fbf31dd5STom Zanussi 		dev_err(tctx->aes_dev->dev, "Failed to map destination sg\n");
796fbf31dd5STom Zanussi 		return -ENOMEM;
797fbf31dd5STom Zanussi 	}
798fbf31dd5STom Zanussi 
799fbf31dd5STom Zanussi 	/* Create AAD DST list: maps dst[0:AAD_SIZE-1]. */
800fbf31dd5STom Zanussi 	rc = ocs_create_linked_list_from_sg(tctx->aes_dev, req->dst,
801fbf31dd5STom Zanussi 					    rctx->dst_dma_count,
802fbf31dd5STom Zanussi 					    &rctx->aad_dst_dll, req->assoclen,
803fbf31dd5STom Zanussi 					    0);
804fbf31dd5STom Zanussi 	if (rc)
805fbf31dd5STom Zanussi 		return rc;
806fbf31dd5STom Zanussi 
807fbf31dd5STom Zanussi 	/* Create DST list: maps dst[AAD_SIZE:out_size] */
808fbf31dd5STom Zanussi 	rc = ocs_create_linked_list_from_sg(tctx->aes_dev, req->dst,
809fbf31dd5STom Zanussi 					    rctx->dst_dma_count, &rctx->dst_dll,
810fbf31dd5STom Zanussi 					    out_size, req->assoclen);
811fbf31dd5STom Zanussi 	if (rc)
812fbf31dd5STom Zanussi 		return rc;
813fbf31dd5STom Zanussi 
814fbf31dd5STom Zanussi 	if (rctx->in_place) {
815fbf31dd5STom Zanussi 		/* If this is not CCM encrypt, we are done. */
816fbf31dd5STom Zanussi 		if (!(rctx->mode == OCS_MODE_CCM &&
817fbf31dd5STom Zanussi 		      rctx->instruction == OCS_ENCRYPT)) {
818fbf31dd5STom Zanussi 			/*
819fbf31dd5STom Zanussi 			 * SRC and DST are the same, so re-use the same DMA
820fbf31dd5STom Zanussi 			 * addresses (to avoid allocating new DMA lists
821fbf31dd5STom Zanussi 			 * identical to the dst ones).
822fbf31dd5STom Zanussi 			 */
823fbf31dd5STom Zanussi 			rctx->src_dll.dma_addr = rctx->dst_dll.dma_addr;
824fbf31dd5STom Zanussi 			rctx->aad_src_dll.dma_addr = rctx->aad_dst_dll.dma_addr;
825fbf31dd5STom Zanussi 
826fbf31dd5STom Zanussi 			return 0;
827fbf31dd5STom Zanussi 		}
828fbf31dd5STom Zanussi 		/*
829fbf31dd5STom Zanussi 		 * For CCM encrypt the input and output linked lists contain
830fbf31dd5STom Zanussi 		 * different amounts of data, so, we need to create different
831fbf31dd5STom Zanussi 		 * SRC and AAD SRC lists, even for the in-place case.
832fbf31dd5STom Zanussi 		 */
833fbf31dd5STom Zanussi 		rc = ocs_create_linked_list_from_sg(tctx->aes_dev, req->dst,
834fbf31dd5STom Zanussi 						    rctx->dst_dma_count,
835fbf31dd5STom Zanussi 						    &rctx->aad_src_dll,
836fbf31dd5STom Zanussi 						    req->assoclen, 0);
837fbf31dd5STom Zanussi 		if (rc)
838fbf31dd5STom Zanussi 			return rc;
839fbf31dd5STom Zanussi 		rc = ocs_create_linked_list_from_sg(tctx->aes_dev, req->dst,
840fbf31dd5STom Zanussi 						    rctx->dst_dma_count,
841fbf31dd5STom Zanussi 						    &rctx->src_dll, in_size,
842fbf31dd5STom Zanussi 						    req->assoclen);
843fbf31dd5STom Zanussi 		if (rc)
844fbf31dd5STom Zanussi 			return rc;
845fbf31dd5STom Zanussi 
846fbf31dd5STom Zanussi 		return 0;
847fbf31dd5STom Zanussi 	}
848fbf31dd5STom Zanussi 	/* Not in-place case. */
849fbf31dd5STom Zanussi 
850fbf31dd5STom Zanussi 	/* Map source SG. */
851fbf31dd5STom Zanussi 	rctx->src_dma_count = dma_map_sg(tctx->aes_dev->dev, req->src,
852fbf31dd5STom Zanussi 					 rctx->src_nents, DMA_TO_DEVICE);
853fbf31dd5STom Zanussi 	if (rctx->src_dma_count == 0 && rctx->src_nents != 0) {
854fbf31dd5STom Zanussi 		dev_err(tctx->aes_dev->dev, "Failed to map source sg\n");
855fbf31dd5STom Zanussi 		return -ENOMEM;
856fbf31dd5STom Zanussi 	}
857fbf31dd5STom Zanussi 
858fbf31dd5STom Zanussi 	/* Create AAD SRC list. */
859fbf31dd5STom Zanussi 	rc = ocs_create_linked_list_from_sg(tctx->aes_dev, req->src,
860fbf31dd5STom Zanussi 					    rctx->src_dma_count,
861fbf31dd5STom Zanussi 					    &rctx->aad_src_dll,
862fbf31dd5STom Zanussi 					    req->assoclen, 0);
863fbf31dd5STom Zanussi 	if (rc)
864fbf31dd5STom Zanussi 		return rc;
865fbf31dd5STom Zanussi 
866fbf31dd5STom Zanussi 	/* Create SRC list. */
867fbf31dd5STom Zanussi 	rc = ocs_create_linked_list_from_sg(tctx->aes_dev, req->src,
868fbf31dd5STom Zanussi 					    rctx->src_dma_count,
869fbf31dd5STom Zanussi 					    &rctx->src_dll, in_size,
870fbf31dd5STom Zanussi 					    req->assoclen);
871fbf31dd5STom Zanussi 	if (rc)
872fbf31dd5STom Zanussi 		return rc;
873fbf31dd5STom Zanussi 
874fbf31dd5STom Zanussi 	if (req->assoclen == 0)
875fbf31dd5STom Zanussi 		return 0;
876fbf31dd5STom Zanussi 
877fbf31dd5STom Zanussi 	/* Copy AAD from src sg to dst sg using OCS DMA. */
878fbf31dd5STom Zanussi 	rc = ocs_aes_bypass_op(tctx->aes_dev, rctx->aad_dst_dll.dma_addr,
879fbf31dd5STom Zanussi 			       rctx->aad_src_dll.dma_addr, req->cryptlen);
880fbf31dd5STom Zanussi 	if (rc)
881fbf31dd5STom Zanussi 		dev_err(tctx->aes_dev->dev,
882fbf31dd5STom Zanussi 			"Failed to copy source AAD to destination AAD\n");
883fbf31dd5STom Zanussi 
884fbf31dd5STom Zanussi 	return rc;
885fbf31dd5STom Zanussi }
886fbf31dd5STom Zanussi 
kmb_ocs_aead_run(struct aead_request * req)887fbf31dd5STom Zanussi static int kmb_ocs_aead_run(struct aead_request *req)
888fbf31dd5STom Zanussi {
889fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
890fbf31dd5STom Zanussi 	const int tag_size = crypto_aead_authsize(crypto_aead_reqtfm(req));
891fbf31dd5STom Zanussi 	struct ocs_aes_rctx *rctx = aead_request_ctx(req);
892fbf31dd5STom Zanussi 	u32 in_size;	/* The length of the data mapped by src_dll. */
893fbf31dd5STom Zanussi 	int rc;
894fbf31dd5STom Zanussi 
895fbf31dd5STom Zanussi 	rc = kmb_ocs_aead_dma_prepare(req, &in_size);
896fbf31dd5STom Zanussi 	if (rc)
897fbf31dd5STom Zanussi 		goto exit;
898fbf31dd5STom Zanussi 
899fbf31dd5STom Zanussi 	/* For CCM, we just call the OCS processing and we are done. */
900fbf31dd5STom Zanussi 	if (rctx->mode == OCS_MODE_CCM) {
901fbf31dd5STom Zanussi 		rc = ocs_aes_ccm_op(tctx->aes_dev, tctx->cipher,
902fbf31dd5STom Zanussi 				    rctx->instruction, rctx->dst_dll.dma_addr,
903fbf31dd5STom Zanussi 				    rctx->src_dll.dma_addr, in_size,
904fbf31dd5STom Zanussi 				    req->iv,
905fbf31dd5STom Zanussi 				    rctx->aad_src_dll.dma_addr, req->assoclen,
906fbf31dd5STom Zanussi 				    rctx->in_tag, tag_size);
907fbf31dd5STom Zanussi 		goto exit;
908fbf31dd5STom Zanussi 	}
909fbf31dd5STom Zanussi 	/* GCM case; invoke OCS processing. */
910fbf31dd5STom Zanussi 	rc = ocs_aes_gcm_op(tctx->aes_dev, tctx->cipher,
911fbf31dd5STom Zanussi 			    rctx->instruction,
912fbf31dd5STom Zanussi 			    rctx->dst_dll.dma_addr,
913fbf31dd5STom Zanussi 			    rctx->src_dll.dma_addr, in_size,
914fbf31dd5STom Zanussi 			    req->iv,
915fbf31dd5STom Zanussi 			    rctx->aad_src_dll.dma_addr, req->assoclen,
916fbf31dd5STom Zanussi 			    rctx->out_tag, tag_size);
917fbf31dd5STom Zanussi 	if (rc)
918fbf31dd5STom Zanussi 		goto exit;
919fbf31dd5STom Zanussi 
920fbf31dd5STom Zanussi 	/* For GCM decrypt, we have to compare in_tag with out_tag. */
921fbf31dd5STom Zanussi 	if (rctx->instruction == OCS_DECRYPT) {
922fbf31dd5STom Zanussi 		rc = memcmp(rctx->in_tag, rctx->out_tag, tag_size) ?
923fbf31dd5STom Zanussi 		     -EBADMSG : 0;
924fbf31dd5STom Zanussi 		goto exit;
925fbf31dd5STom Zanussi 	}
926fbf31dd5STom Zanussi 
927fbf31dd5STom Zanussi 	/* For GCM encrypt, we must manually copy out_tag to DST sg. */
928fbf31dd5STom Zanussi 
929fbf31dd5STom Zanussi 	/* Clean-up must be called before the sg_pcopy_from_buffer() below. */
930fbf31dd5STom Zanussi 	kmb_ocs_aead_dma_cleanup(req);
931fbf31dd5STom Zanussi 
932fbf31dd5STom Zanussi 	/* Copy tag to destination sg after AAD and CT. */
933fbf31dd5STom Zanussi 	sg_pcopy_from_buffer(req->dst, rctx->dst_nents, rctx->out_tag,
934fbf31dd5STom Zanussi 			     tag_size, req->assoclen + req->cryptlen);
935fbf31dd5STom Zanussi 
936fbf31dd5STom Zanussi 	/* Return directly as DMA cleanup already done. */
937fbf31dd5STom Zanussi 	return 0;
938fbf31dd5STom Zanussi 
939fbf31dd5STom Zanussi exit:
940fbf31dd5STom Zanussi 	kmb_ocs_aead_dma_cleanup(req);
941fbf31dd5STom Zanussi 
942fbf31dd5STom Zanussi 	return rc;
943fbf31dd5STom Zanussi }
944fbf31dd5STom Zanussi 
kmb_ocs_aes_sk_do_one_request(struct crypto_engine * engine,void * areq)945fbf31dd5STom Zanussi static int kmb_ocs_aes_sk_do_one_request(struct crypto_engine *engine,
946fbf31dd5STom Zanussi 					 void *areq)
947fbf31dd5STom Zanussi {
948fbf31dd5STom Zanussi 	struct skcipher_request *req =
949fbf31dd5STom Zanussi 			container_of(areq, struct skcipher_request, base);
950fbf31dd5STom Zanussi 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
951fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm);
952fbf31dd5STom Zanussi 	int err;
953fbf31dd5STom Zanussi 
954fbf31dd5STom Zanussi 	if (!tctx->aes_dev) {
955fbf31dd5STom Zanussi 		err = -ENODEV;
956fbf31dd5STom Zanussi 		goto exit;
957fbf31dd5STom Zanussi 	}
958fbf31dd5STom Zanussi 
959fbf31dd5STom Zanussi 	err = ocs_aes_set_key(tctx->aes_dev, tctx->key_len, tctx->key,
960fbf31dd5STom Zanussi 			      tctx->cipher);
961fbf31dd5STom Zanussi 	if (err)
962fbf31dd5STom Zanussi 		goto exit;
963fbf31dd5STom Zanussi 
964fbf31dd5STom Zanussi 	err = kmb_ocs_sk_run(req);
965fbf31dd5STom Zanussi 
966fbf31dd5STom Zanussi exit:
967fbf31dd5STom Zanussi 	crypto_finalize_skcipher_request(engine, req, err);
968fbf31dd5STom Zanussi 
969fbf31dd5STom Zanussi 	return 0;
970fbf31dd5STom Zanussi }
971fbf31dd5STom Zanussi 
kmb_ocs_aes_aead_do_one_request(struct crypto_engine * engine,void * areq)972fbf31dd5STom Zanussi static int kmb_ocs_aes_aead_do_one_request(struct crypto_engine *engine,
973fbf31dd5STom Zanussi 					   void *areq)
974fbf31dd5STom Zanussi {
975fbf31dd5STom Zanussi 	struct aead_request *req = container_of(areq,
976fbf31dd5STom Zanussi 						struct aead_request, base);
977fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
978fbf31dd5STom Zanussi 	int err;
979fbf31dd5STom Zanussi 
980fbf31dd5STom Zanussi 	if (!tctx->aes_dev)
981fbf31dd5STom Zanussi 		return -ENODEV;
982fbf31dd5STom Zanussi 
983fbf31dd5STom Zanussi 	err = ocs_aes_set_key(tctx->aes_dev, tctx->key_len, tctx->key,
984fbf31dd5STom Zanussi 			      tctx->cipher);
985fbf31dd5STom Zanussi 	if (err)
986fbf31dd5STom Zanussi 		goto exit;
987fbf31dd5STom Zanussi 
988fbf31dd5STom Zanussi 	err = kmb_ocs_aead_run(req);
989fbf31dd5STom Zanussi 
990fbf31dd5STom Zanussi exit:
991fbf31dd5STom Zanussi 	crypto_finalize_aead_request(tctx->aes_dev->engine, req, err);
992fbf31dd5STom Zanussi 
993fbf31dd5STom Zanussi 	return 0;
994fbf31dd5STom Zanussi }
995fbf31dd5STom Zanussi 
kmb_ocs_aes_set_key(struct crypto_skcipher * tfm,const u8 * in_key,unsigned int key_len)996fbf31dd5STom Zanussi static int kmb_ocs_aes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
997fbf31dd5STom Zanussi 			       unsigned int key_len)
998fbf31dd5STom Zanussi {
999fbf31dd5STom Zanussi 	return kmb_ocs_sk_set_key(tfm, in_key, key_len, OCS_AES);
1000fbf31dd5STom Zanussi }
1001fbf31dd5STom Zanussi 
kmb_ocs_aes_aead_set_key(struct crypto_aead * tfm,const u8 * in_key,unsigned int key_len)1002fbf31dd5STom Zanussi static int kmb_ocs_aes_aead_set_key(struct crypto_aead *tfm, const u8 *in_key,
1003fbf31dd5STom Zanussi 				    unsigned int key_len)
1004fbf31dd5STom Zanussi {
1005fbf31dd5STom Zanussi 	return kmb_ocs_aead_set_key(tfm, in_key, key_len, OCS_AES);
1006fbf31dd5STom Zanussi }
1007fbf31dd5STom Zanussi 
1008fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB
kmb_ocs_aes_ecb_encrypt(struct skcipher_request * req)1009fbf31dd5STom Zanussi static int kmb_ocs_aes_ecb_encrypt(struct skcipher_request *req)
1010fbf31dd5STom Zanussi {
1011fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_AES, OCS_ENCRYPT, OCS_MODE_ECB);
1012fbf31dd5STom Zanussi }
1013fbf31dd5STom Zanussi 
kmb_ocs_aes_ecb_decrypt(struct skcipher_request * req)1014fbf31dd5STom Zanussi static int kmb_ocs_aes_ecb_decrypt(struct skcipher_request *req)
1015fbf31dd5STom Zanussi {
1016fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_AES, OCS_DECRYPT, OCS_MODE_ECB);
1017fbf31dd5STom Zanussi }
1018fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB */
1019fbf31dd5STom Zanussi 
kmb_ocs_aes_cbc_encrypt(struct skcipher_request * req)1020fbf31dd5STom Zanussi static int kmb_ocs_aes_cbc_encrypt(struct skcipher_request *req)
1021fbf31dd5STom Zanussi {
1022fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_AES, OCS_ENCRYPT, OCS_MODE_CBC);
1023fbf31dd5STom Zanussi }
1024fbf31dd5STom Zanussi 
kmb_ocs_aes_cbc_decrypt(struct skcipher_request * req)1025fbf31dd5STom Zanussi static int kmb_ocs_aes_cbc_decrypt(struct skcipher_request *req)
1026fbf31dd5STom Zanussi {
1027fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_AES, OCS_DECRYPT, OCS_MODE_CBC);
1028fbf31dd5STom Zanussi }
1029fbf31dd5STom Zanussi 
kmb_ocs_aes_ctr_encrypt(struct skcipher_request * req)1030fbf31dd5STom Zanussi static int kmb_ocs_aes_ctr_encrypt(struct skcipher_request *req)
1031fbf31dd5STom Zanussi {
1032fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_AES, OCS_ENCRYPT, OCS_MODE_CTR);
1033fbf31dd5STom Zanussi }
1034fbf31dd5STom Zanussi 
kmb_ocs_aes_ctr_decrypt(struct skcipher_request * req)1035fbf31dd5STom Zanussi static int kmb_ocs_aes_ctr_decrypt(struct skcipher_request *req)
1036fbf31dd5STom Zanussi {
1037fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_AES, OCS_DECRYPT, OCS_MODE_CTR);
1038fbf31dd5STom Zanussi }
1039fbf31dd5STom Zanussi 
1040fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS
kmb_ocs_aes_cts_encrypt(struct skcipher_request * req)1041fbf31dd5STom Zanussi static int kmb_ocs_aes_cts_encrypt(struct skcipher_request *req)
1042fbf31dd5STom Zanussi {
1043fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_AES, OCS_ENCRYPT, OCS_MODE_CTS);
1044fbf31dd5STom Zanussi }
1045fbf31dd5STom Zanussi 
kmb_ocs_aes_cts_decrypt(struct skcipher_request * req)1046fbf31dd5STom Zanussi static int kmb_ocs_aes_cts_decrypt(struct skcipher_request *req)
1047fbf31dd5STom Zanussi {
1048fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_AES, OCS_DECRYPT, OCS_MODE_CTS);
1049fbf31dd5STom Zanussi }
1050fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS */
1051fbf31dd5STom Zanussi 
kmb_ocs_aes_gcm_encrypt(struct aead_request * req)1052fbf31dd5STom Zanussi static int kmb_ocs_aes_gcm_encrypt(struct aead_request *req)
1053fbf31dd5STom Zanussi {
1054fbf31dd5STom Zanussi 	return kmb_ocs_aead_common(req, OCS_AES, OCS_ENCRYPT, OCS_MODE_GCM);
1055fbf31dd5STom Zanussi }
1056fbf31dd5STom Zanussi 
kmb_ocs_aes_gcm_decrypt(struct aead_request * req)1057fbf31dd5STom Zanussi static int kmb_ocs_aes_gcm_decrypt(struct aead_request *req)
1058fbf31dd5STom Zanussi {
1059fbf31dd5STom Zanussi 	return kmb_ocs_aead_common(req, OCS_AES, OCS_DECRYPT, OCS_MODE_GCM);
1060fbf31dd5STom Zanussi }
1061fbf31dd5STom Zanussi 
kmb_ocs_aes_ccm_encrypt(struct aead_request * req)1062fbf31dd5STom Zanussi static int kmb_ocs_aes_ccm_encrypt(struct aead_request *req)
1063fbf31dd5STom Zanussi {
1064fbf31dd5STom Zanussi 	return kmb_ocs_aead_common(req, OCS_AES, OCS_ENCRYPT, OCS_MODE_CCM);
1065fbf31dd5STom Zanussi }
1066fbf31dd5STom Zanussi 
kmb_ocs_aes_ccm_decrypt(struct aead_request * req)1067fbf31dd5STom Zanussi static int kmb_ocs_aes_ccm_decrypt(struct aead_request *req)
1068fbf31dd5STom Zanussi {
1069fbf31dd5STom Zanussi 	return kmb_ocs_aead_common(req, OCS_AES, OCS_DECRYPT, OCS_MODE_CCM);
1070fbf31dd5STom Zanussi }
1071fbf31dd5STom Zanussi 
kmb_ocs_sm4_set_key(struct crypto_skcipher * tfm,const u8 * in_key,unsigned int key_len)1072fbf31dd5STom Zanussi static int kmb_ocs_sm4_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
1073fbf31dd5STom Zanussi 			       unsigned int key_len)
1074fbf31dd5STom Zanussi {
1075fbf31dd5STom Zanussi 	return kmb_ocs_sk_set_key(tfm, in_key, key_len, OCS_SM4);
1076fbf31dd5STom Zanussi }
1077fbf31dd5STom Zanussi 
kmb_ocs_sm4_aead_set_key(struct crypto_aead * tfm,const u8 * in_key,unsigned int key_len)1078fbf31dd5STom Zanussi static int kmb_ocs_sm4_aead_set_key(struct crypto_aead *tfm, const u8 *in_key,
1079fbf31dd5STom Zanussi 				    unsigned int key_len)
1080fbf31dd5STom Zanussi {
1081fbf31dd5STom Zanussi 	return kmb_ocs_aead_set_key(tfm, in_key, key_len, OCS_SM4);
1082fbf31dd5STom Zanussi }
1083fbf31dd5STom Zanussi 
1084fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB
kmb_ocs_sm4_ecb_encrypt(struct skcipher_request * req)1085fbf31dd5STom Zanussi static int kmb_ocs_sm4_ecb_encrypt(struct skcipher_request *req)
1086fbf31dd5STom Zanussi {
1087fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_SM4, OCS_ENCRYPT, OCS_MODE_ECB);
1088fbf31dd5STom Zanussi }
1089fbf31dd5STom Zanussi 
kmb_ocs_sm4_ecb_decrypt(struct skcipher_request * req)1090fbf31dd5STom Zanussi static int kmb_ocs_sm4_ecb_decrypt(struct skcipher_request *req)
1091fbf31dd5STom Zanussi {
1092fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_SM4, OCS_DECRYPT, OCS_MODE_ECB);
1093fbf31dd5STom Zanussi }
1094fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB */
1095fbf31dd5STom Zanussi 
kmb_ocs_sm4_cbc_encrypt(struct skcipher_request * req)1096fbf31dd5STom Zanussi static int kmb_ocs_sm4_cbc_encrypt(struct skcipher_request *req)
1097fbf31dd5STom Zanussi {
1098fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_SM4, OCS_ENCRYPT, OCS_MODE_CBC);
1099fbf31dd5STom Zanussi }
1100fbf31dd5STom Zanussi 
kmb_ocs_sm4_cbc_decrypt(struct skcipher_request * req)1101fbf31dd5STom Zanussi static int kmb_ocs_sm4_cbc_decrypt(struct skcipher_request *req)
1102fbf31dd5STom Zanussi {
1103fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_SM4, OCS_DECRYPT, OCS_MODE_CBC);
1104fbf31dd5STom Zanussi }
1105fbf31dd5STom Zanussi 
kmb_ocs_sm4_ctr_encrypt(struct skcipher_request * req)1106fbf31dd5STom Zanussi static int kmb_ocs_sm4_ctr_encrypt(struct skcipher_request *req)
1107fbf31dd5STom Zanussi {
1108fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_SM4, OCS_ENCRYPT, OCS_MODE_CTR);
1109fbf31dd5STom Zanussi }
1110fbf31dd5STom Zanussi 
kmb_ocs_sm4_ctr_decrypt(struct skcipher_request * req)1111fbf31dd5STom Zanussi static int kmb_ocs_sm4_ctr_decrypt(struct skcipher_request *req)
1112fbf31dd5STom Zanussi {
1113fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_SM4, OCS_DECRYPT, OCS_MODE_CTR);
1114fbf31dd5STom Zanussi }
1115fbf31dd5STom Zanussi 
1116fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS
kmb_ocs_sm4_cts_encrypt(struct skcipher_request * req)1117fbf31dd5STom Zanussi static int kmb_ocs_sm4_cts_encrypt(struct skcipher_request *req)
1118fbf31dd5STom Zanussi {
1119fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_SM4, OCS_ENCRYPT, OCS_MODE_CTS);
1120fbf31dd5STom Zanussi }
1121fbf31dd5STom Zanussi 
kmb_ocs_sm4_cts_decrypt(struct skcipher_request * req)1122fbf31dd5STom Zanussi static int kmb_ocs_sm4_cts_decrypt(struct skcipher_request *req)
1123fbf31dd5STom Zanussi {
1124fbf31dd5STom Zanussi 	return kmb_ocs_sk_common(req, OCS_SM4, OCS_DECRYPT, OCS_MODE_CTS);
1125fbf31dd5STom Zanussi }
1126fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS */
1127fbf31dd5STom Zanussi 
kmb_ocs_sm4_gcm_encrypt(struct aead_request * req)1128fbf31dd5STom Zanussi static int kmb_ocs_sm4_gcm_encrypt(struct aead_request *req)
1129fbf31dd5STom Zanussi {
1130fbf31dd5STom Zanussi 	return kmb_ocs_aead_common(req, OCS_SM4, OCS_ENCRYPT, OCS_MODE_GCM);
1131fbf31dd5STom Zanussi }
1132fbf31dd5STom Zanussi 
kmb_ocs_sm4_gcm_decrypt(struct aead_request * req)1133fbf31dd5STom Zanussi static int kmb_ocs_sm4_gcm_decrypt(struct aead_request *req)
1134fbf31dd5STom Zanussi {
1135fbf31dd5STom Zanussi 	return kmb_ocs_aead_common(req, OCS_SM4, OCS_DECRYPT, OCS_MODE_GCM);
1136fbf31dd5STom Zanussi }
1137fbf31dd5STom Zanussi 
kmb_ocs_sm4_ccm_encrypt(struct aead_request * req)1138fbf31dd5STom Zanussi static int kmb_ocs_sm4_ccm_encrypt(struct aead_request *req)
1139fbf31dd5STom Zanussi {
1140fbf31dd5STom Zanussi 	return kmb_ocs_aead_common(req, OCS_SM4, OCS_ENCRYPT, OCS_MODE_CCM);
1141fbf31dd5STom Zanussi }
1142fbf31dd5STom Zanussi 
kmb_ocs_sm4_ccm_decrypt(struct aead_request * req)1143fbf31dd5STom Zanussi static int kmb_ocs_sm4_ccm_decrypt(struct aead_request *req)
1144fbf31dd5STom Zanussi {
1145fbf31dd5STom Zanussi 	return kmb_ocs_aead_common(req, OCS_SM4, OCS_DECRYPT, OCS_MODE_CCM);
1146fbf31dd5STom Zanussi }
1147fbf31dd5STom Zanussi 
ocs_aes_init_tfm(struct crypto_skcipher * tfm)1148fbf31dd5STom Zanussi static int ocs_aes_init_tfm(struct crypto_skcipher *tfm)
1149fbf31dd5STom Zanussi {
1150fbf31dd5STom Zanussi 	const char *alg_name = crypto_tfm_alg_name(&tfm->base);
1151fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm);
1152fbf31dd5STom Zanussi 	struct crypto_sync_skcipher *blk;
1153fbf31dd5STom Zanussi 
1154fbf31dd5STom Zanussi 	/* set fallback cipher in case it will be needed */
1155fbf31dd5STom Zanussi 	blk = crypto_alloc_sync_skcipher(alg_name, 0, CRYPTO_ALG_NEED_FALLBACK);
1156fbf31dd5STom Zanussi 	if (IS_ERR(blk))
1157fbf31dd5STom Zanussi 		return PTR_ERR(blk);
1158fbf31dd5STom Zanussi 
1159fbf31dd5STom Zanussi 	tctx->sw_cipher.sk = blk;
1160fbf31dd5STom Zanussi 
1161fbf31dd5STom Zanussi 	crypto_skcipher_set_reqsize(tfm, sizeof(struct ocs_aes_rctx));
1162fbf31dd5STom Zanussi 
1163530d7b00SHerbert Xu 	return 0;
1164fbf31dd5STom Zanussi }
1165fbf31dd5STom Zanussi 
ocs_sm4_init_tfm(struct crypto_skcipher * tfm)1166fbf31dd5STom Zanussi static int ocs_sm4_init_tfm(struct crypto_skcipher *tfm)
1167fbf31dd5STom Zanussi {
1168fbf31dd5STom Zanussi 	crypto_skcipher_set_reqsize(tfm, sizeof(struct ocs_aes_rctx));
1169fbf31dd5STom Zanussi 
1170530d7b00SHerbert Xu 	return 0;
1171fbf31dd5STom Zanussi }
1172fbf31dd5STom Zanussi 
clear_key(struct ocs_aes_tctx * tctx)1173fbf31dd5STom Zanussi static inline void clear_key(struct ocs_aes_tctx *tctx)
1174fbf31dd5STom Zanussi {
1175fbf31dd5STom Zanussi 	memzero_explicit(tctx->key, OCS_AES_KEYSIZE_256);
1176fbf31dd5STom Zanussi 
1177fbf31dd5STom Zanussi 	/* Zero key registers if set */
1178fbf31dd5STom Zanussi 	if (tctx->aes_dev)
1179fbf31dd5STom Zanussi 		ocs_aes_set_key(tctx->aes_dev, OCS_AES_KEYSIZE_256,
1180fbf31dd5STom Zanussi 				tctx->key, OCS_AES);
1181fbf31dd5STom Zanussi }
1182fbf31dd5STom Zanussi 
ocs_exit_tfm(struct crypto_skcipher * tfm)1183fbf31dd5STom Zanussi static void ocs_exit_tfm(struct crypto_skcipher *tfm)
1184fbf31dd5STom Zanussi {
1185fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm);
1186fbf31dd5STom Zanussi 
1187fbf31dd5STom Zanussi 	clear_key(tctx);
1188fbf31dd5STom Zanussi 
1189fbf31dd5STom Zanussi 	if (tctx->sw_cipher.sk) {
1190fbf31dd5STom Zanussi 		crypto_free_sync_skcipher(tctx->sw_cipher.sk);
1191fbf31dd5STom Zanussi 		tctx->sw_cipher.sk = NULL;
1192fbf31dd5STom Zanussi 	}
1193fbf31dd5STom Zanussi }
1194fbf31dd5STom Zanussi 
ocs_aes_aead_cra_init(struct crypto_aead * tfm)1195fbf31dd5STom Zanussi static int ocs_aes_aead_cra_init(struct crypto_aead *tfm)
1196fbf31dd5STom Zanussi {
1197fbf31dd5STom Zanussi 	const char *alg_name = crypto_tfm_alg_name(&tfm->base);
1198fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_aead_ctx(tfm);
1199fbf31dd5STom Zanussi 	struct crypto_aead *blk;
1200fbf31dd5STom Zanussi 
1201fbf31dd5STom Zanussi 	/* Set fallback cipher in case it will be needed */
1202fbf31dd5STom Zanussi 	blk = crypto_alloc_aead(alg_name, 0, CRYPTO_ALG_NEED_FALLBACK);
1203fbf31dd5STom Zanussi 	if (IS_ERR(blk))
1204fbf31dd5STom Zanussi 		return PTR_ERR(blk);
1205fbf31dd5STom Zanussi 
1206fbf31dd5STom Zanussi 	tctx->sw_cipher.aead = blk;
1207fbf31dd5STom Zanussi 
1208fbf31dd5STom Zanussi 	crypto_aead_set_reqsize(tfm,
1209fbf31dd5STom Zanussi 				max(sizeof(struct ocs_aes_rctx),
1210fbf31dd5STom Zanussi 				    (sizeof(struct aead_request) +
1211fbf31dd5STom Zanussi 				     crypto_aead_reqsize(tctx->sw_cipher.aead))));
1212fbf31dd5STom Zanussi 
1213530d7b00SHerbert Xu 	return 0;
1214fbf31dd5STom Zanussi }
1215fbf31dd5STom Zanussi 
kmb_ocs_aead_ccm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)1216fbf31dd5STom Zanussi static int kmb_ocs_aead_ccm_setauthsize(struct crypto_aead *tfm,
1217fbf31dd5STom Zanussi 					unsigned int authsize)
1218fbf31dd5STom Zanussi {
1219fbf31dd5STom Zanussi 	switch (authsize) {
1220fbf31dd5STom Zanussi 	case 4:
1221fbf31dd5STom Zanussi 	case 6:
1222fbf31dd5STom Zanussi 	case 8:
1223fbf31dd5STom Zanussi 	case 10:
1224fbf31dd5STom Zanussi 	case 12:
1225fbf31dd5STom Zanussi 	case 14:
1226fbf31dd5STom Zanussi 	case 16:
1227fbf31dd5STom Zanussi 		return 0;
1228fbf31dd5STom Zanussi 	default:
1229fbf31dd5STom Zanussi 		return -EINVAL;
1230fbf31dd5STom Zanussi 	}
1231fbf31dd5STom Zanussi }
1232fbf31dd5STom Zanussi 
kmb_ocs_aead_gcm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)1233fbf31dd5STom Zanussi static int kmb_ocs_aead_gcm_setauthsize(struct crypto_aead *tfm,
1234fbf31dd5STom Zanussi 					unsigned int authsize)
1235fbf31dd5STom Zanussi {
1236fbf31dd5STom Zanussi 	return crypto_gcm_check_authsize(authsize);
1237fbf31dd5STom Zanussi }
1238fbf31dd5STom Zanussi 
ocs_sm4_aead_cra_init(struct crypto_aead * tfm)1239fbf31dd5STom Zanussi static int ocs_sm4_aead_cra_init(struct crypto_aead *tfm)
1240fbf31dd5STom Zanussi {
1241fbf31dd5STom Zanussi 	crypto_aead_set_reqsize(tfm, sizeof(struct ocs_aes_rctx));
1242fbf31dd5STom Zanussi 
1243530d7b00SHerbert Xu 	return 0;
1244fbf31dd5STom Zanussi }
1245fbf31dd5STom Zanussi 
ocs_aead_cra_exit(struct crypto_aead * tfm)1246fbf31dd5STom Zanussi static void ocs_aead_cra_exit(struct crypto_aead *tfm)
1247fbf31dd5STom Zanussi {
1248fbf31dd5STom Zanussi 	struct ocs_aes_tctx *tctx = crypto_aead_ctx(tfm);
1249fbf31dd5STom Zanussi 
1250fbf31dd5STom Zanussi 	clear_key(tctx);
1251fbf31dd5STom Zanussi 
1252fbf31dd5STom Zanussi 	if (tctx->sw_cipher.aead) {
1253fbf31dd5STom Zanussi 		crypto_free_aead(tctx->sw_cipher.aead);
1254fbf31dd5STom Zanussi 		tctx->sw_cipher.aead = NULL;
1255fbf31dd5STom Zanussi 	}
1256fbf31dd5STom Zanussi }
1257fbf31dd5STom Zanussi 
1258530d7b00SHerbert Xu static struct skcipher_engine_alg algs[] = {
1259fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB
1260fbf31dd5STom Zanussi 	{
1261530d7b00SHerbert Xu 		.base.base.cra_name = "ecb(aes)",
1262530d7b00SHerbert Xu 		.base.base.cra_driver_name = "ecb-aes-keembay-ocs",
1263530d7b00SHerbert Xu 		.base.base.cra_priority = KMB_OCS_PRIORITY,
1264530d7b00SHerbert Xu 		.base.base.cra_flags = CRYPTO_ALG_ASYNC |
1265fbf31dd5STom Zanussi 				       CRYPTO_ALG_KERN_DRIVER_ONLY |
1266fbf31dd5STom Zanussi 				       CRYPTO_ALG_NEED_FALLBACK,
1267530d7b00SHerbert Xu 		.base.base.cra_blocksize = AES_BLOCK_SIZE,
1268530d7b00SHerbert Xu 		.base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1269530d7b00SHerbert Xu 		.base.base.cra_module = THIS_MODULE,
1270530d7b00SHerbert Xu 		.base.base.cra_alignmask = 0,
1271fbf31dd5STom Zanussi 
1272530d7b00SHerbert Xu 		.base.min_keysize = OCS_AES_MIN_KEY_SIZE,
1273530d7b00SHerbert Xu 		.base.max_keysize = OCS_AES_MAX_KEY_SIZE,
1274530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_aes_set_key,
1275530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_aes_ecb_encrypt,
1276530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_aes_ecb_decrypt,
1277530d7b00SHerbert Xu 		.base.init = ocs_aes_init_tfm,
1278530d7b00SHerbert Xu 		.base.exit = ocs_exit_tfm,
1279530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_sk_do_one_request,
1280fbf31dd5STom Zanussi 	},
1281fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB */
1282fbf31dd5STom Zanussi 	{
1283530d7b00SHerbert Xu 		.base.base.cra_name = "cbc(aes)",
1284530d7b00SHerbert Xu 		.base.base.cra_driver_name = "cbc-aes-keembay-ocs",
1285530d7b00SHerbert Xu 		.base.base.cra_priority = KMB_OCS_PRIORITY,
1286530d7b00SHerbert Xu 		.base.base.cra_flags = CRYPTO_ALG_ASYNC |
1287fbf31dd5STom Zanussi 				       CRYPTO_ALG_KERN_DRIVER_ONLY |
1288fbf31dd5STom Zanussi 				       CRYPTO_ALG_NEED_FALLBACK,
1289530d7b00SHerbert Xu 		.base.base.cra_blocksize = AES_BLOCK_SIZE,
1290530d7b00SHerbert Xu 		.base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1291530d7b00SHerbert Xu 		.base.base.cra_module = THIS_MODULE,
1292530d7b00SHerbert Xu 		.base.base.cra_alignmask = 0,
1293fbf31dd5STom Zanussi 
1294530d7b00SHerbert Xu 		.base.min_keysize = OCS_AES_MIN_KEY_SIZE,
1295530d7b00SHerbert Xu 		.base.max_keysize = OCS_AES_MAX_KEY_SIZE,
1296530d7b00SHerbert Xu 		.base.ivsize = AES_BLOCK_SIZE,
1297530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_aes_set_key,
1298530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_aes_cbc_encrypt,
1299530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_aes_cbc_decrypt,
1300530d7b00SHerbert Xu 		.base.init = ocs_aes_init_tfm,
1301530d7b00SHerbert Xu 		.base.exit = ocs_exit_tfm,
1302530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_sk_do_one_request,
1303fbf31dd5STom Zanussi 	},
1304fbf31dd5STom Zanussi 	{
1305530d7b00SHerbert Xu 		.base.base.cra_name = "ctr(aes)",
1306530d7b00SHerbert Xu 		.base.base.cra_driver_name = "ctr-aes-keembay-ocs",
1307530d7b00SHerbert Xu 		.base.base.cra_priority = KMB_OCS_PRIORITY,
1308530d7b00SHerbert Xu 		.base.base.cra_flags = CRYPTO_ALG_ASYNC |
1309fbf31dd5STom Zanussi 				       CRYPTO_ALG_KERN_DRIVER_ONLY |
1310fbf31dd5STom Zanussi 				       CRYPTO_ALG_NEED_FALLBACK,
1311530d7b00SHerbert Xu 		.base.base.cra_blocksize = 1,
1312530d7b00SHerbert Xu 		.base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1313530d7b00SHerbert Xu 		.base.base.cra_module = THIS_MODULE,
1314530d7b00SHerbert Xu 		.base.base.cra_alignmask = 0,
1315fbf31dd5STom Zanussi 
1316530d7b00SHerbert Xu 		.base.min_keysize = OCS_AES_MIN_KEY_SIZE,
1317530d7b00SHerbert Xu 		.base.max_keysize = OCS_AES_MAX_KEY_SIZE,
1318530d7b00SHerbert Xu 		.base.ivsize = AES_BLOCK_SIZE,
1319530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_aes_set_key,
1320530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_aes_ctr_encrypt,
1321530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_aes_ctr_decrypt,
1322530d7b00SHerbert Xu 		.base.init = ocs_aes_init_tfm,
1323530d7b00SHerbert Xu 		.base.exit = ocs_exit_tfm,
1324530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_sk_do_one_request,
1325fbf31dd5STom Zanussi 	},
1326fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS
1327fbf31dd5STom Zanussi 	{
1328530d7b00SHerbert Xu 		.base.base.cra_name = "cts(cbc(aes))",
1329530d7b00SHerbert Xu 		.base.base.cra_driver_name = "cts-aes-keembay-ocs",
1330530d7b00SHerbert Xu 		.base.base.cra_priority = KMB_OCS_PRIORITY,
1331530d7b00SHerbert Xu 		.base.base.cra_flags = CRYPTO_ALG_ASYNC |
1332fbf31dd5STom Zanussi 				       CRYPTO_ALG_KERN_DRIVER_ONLY |
1333fbf31dd5STom Zanussi 				       CRYPTO_ALG_NEED_FALLBACK,
1334530d7b00SHerbert Xu 		.base.base.cra_blocksize = AES_BLOCK_SIZE,
1335530d7b00SHerbert Xu 		.base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1336530d7b00SHerbert Xu 		.base.base.cra_module = THIS_MODULE,
1337530d7b00SHerbert Xu 		.base.base.cra_alignmask = 0,
1338fbf31dd5STom Zanussi 
1339530d7b00SHerbert Xu 		.base.min_keysize = OCS_AES_MIN_KEY_SIZE,
1340530d7b00SHerbert Xu 		.base.max_keysize = OCS_AES_MAX_KEY_SIZE,
1341530d7b00SHerbert Xu 		.base.ivsize = AES_BLOCK_SIZE,
1342530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_aes_set_key,
1343530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_aes_cts_encrypt,
1344530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_aes_cts_decrypt,
1345530d7b00SHerbert Xu 		.base.init = ocs_aes_init_tfm,
1346530d7b00SHerbert Xu 		.base.exit = ocs_exit_tfm,
1347530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_sk_do_one_request,
1348fbf31dd5STom Zanussi 	},
1349fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS */
1350fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB
1351fbf31dd5STom Zanussi 	{
1352530d7b00SHerbert Xu 		.base.base.cra_name = "ecb(sm4)",
1353530d7b00SHerbert Xu 		.base.base.cra_driver_name = "ecb-sm4-keembay-ocs",
1354530d7b00SHerbert Xu 		.base.base.cra_priority = KMB_OCS_PRIORITY,
1355530d7b00SHerbert Xu 		.base.base.cra_flags = CRYPTO_ALG_ASYNC |
1356fbf31dd5STom Zanussi 				       CRYPTO_ALG_KERN_DRIVER_ONLY,
1357530d7b00SHerbert Xu 		.base.base.cra_blocksize = AES_BLOCK_SIZE,
1358530d7b00SHerbert Xu 		.base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1359530d7b00SHerbert Xu 		.base.base.cra_module = THIS_MODULE,
1360530d7b00SHerbert Xu 		.base.base.cra_alignmask = 0,
1361fbf31dd5STom Zanussi 
1362530d7b00SHerbert Xu 		.base.min_keysize = OCS_SM4_KEY_SIZE,
1363530d7b00SHerbert Xu 		.base.max_keysize = OCS_SM4_KEY_SIZE,
1364530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_sm4_set_key,
1365530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_sm4_ecb_encrypt,
1366530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_sm4_ecb_decrypt,
1367530d7b00SHerbert Xu 		.base.init = ocs_sm4_init_tfm,
1368530d7b00SHerbert Xu 		.base.exit = ocs_exit_tfm,
1369530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_sk_do_one_request,
1370fbf31dd5STom Zanussi 	},
1371fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB */
1372fbf31dd5STom Zanussi 	{
1373530d7b00SHerbert Xu 		.base.base.cra_name = "cbc(sm4)",
1374530d7b00SHerbert Xu 		.base.base.cra_driver_name = "cbc-sm4-keembay-ocs",
1375530d7b00SHerbert Xu 		.base.base.cra_priority = KMB_OCS_PRIORITY,
1376530d7b00SHerbert Xu 		.base.base.cra_flags = CRYPTO_ALG_ASYNC |
1377fbf31dd5STom Zanussi 				       CRYPTO_ALG_KERN_DRIVER_ONLY,
1378530d7b00SHerbert Xu 		.base.base.cra_blocksize = AES_BLOCK_SIZE,
1379530d7b00SHerbert Xu 		.base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1380530d7b00SHerbert Xu 		.base.base.cra_module = THIS_MODULE,
1381530d7b00SHerbert Xu 		.base.base.cra_alignmask = 0,
1382fbf31dd5STom Zanussi 
1383530d7b00SHerbert Xu 		.base.min_keysize = OCS_SM4_KEY_SIZE,
1384530d7b00SHerbert Xu 		.base.max_keysize = OCS_SM4_KEY_SIZE,
1385530d7b00SHerbert Xu 		.base.ivsize = AES_BLOCK_SIZE,
1386530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_sm4_set_key,
1387530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_sm4_cbc_encrypt,
1388530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_sm4_cbc_decrypt,
1389530d7b00SHerbert Xu 		.base.init = ocs_sm4_init_tfm,
1390530d7b00SHerbert Xu 		.base.exit = ocs_exit_tfm,
1391530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_sk_do_one_request,
1392fbf31dd5STom Zanussi 	},
1393fbf31dd5STom Zanussi 	{
1394530d7b00SHerbert Xu 		.base.base.cra_name = "ctr(sm4)",
1395530d7b00SHerbert Xu 		.base.base.cra_driver_name = "ctr-sm4-keembay-ocs",
1396530d7b00SHerbert Xu 		.base.base.cra_priority = KMB_OCS_PRIORITY,
1397530d7b00SHerbert Xu 		.base.base.cra_flags = CRYPTO_ALG_ASYNC |
1398fbf31dd5STom Zanussi 				       CRYPTO_ALG_KERN_DRIVER_ONLY,
1399530d7b00SHerbert Xu 		.base.base.cra_blocksize = 1,
1400530d7b00SHerbert Xu 		.base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1401530d7b00SHerbert Xu 		.base.base.cra_module = THIS_MODULE,
1402530d7b00SHerbert Xu 		.base.base.cra_alignmask = 0,
1403fbf31dd5STom Zanussi 
1404530d7b00SHerbert Xu 		.base.min_keysize = OCS_SM4_KEY_SIZE,
1405530d7b00SHerbert Xu 		.base.max_keysize = OCS_SM4_KEY_SIZE,
1406530d7b00SHerbert Xu 		.base.ivsize = AES_BLOCK_SIZE,
1407530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_sm4_set_key,
1408530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_sm4_ctr_encrypt,
1409530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_sm4_ctr_decrypt,
1410530d7b00SHerbert Xu 		.base.init = ocs_sm4_init_tfm,
1411530d7b00SHerbert Xu 		.base.exit = ocs_exit_tfm,
1412530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_sk_do_one_request,
1413fbf31dd5STom Zanussi 	},
1414fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS
1415fbf31dd5STom Zanussi 	{
1416530d7b00SHerbert Xu 		.base.base.cra_name = "cts(cbc(sm4))",
1417530d7b00SHerbert Xu 		.base.base.cra_driver_name = "cts-sm4-keembay-ocs",
1418530d7b00SHerbert Xu 		.base.base.cra_priority = KMB_OCS_PRIORITY,
1419530d7b00SHerbert Xu 		.base.base.cra_flags = CRYPTO_ALG_ASYNC |
1420fbf31dd5STom Zanussi 				       CRYPTO_ALG_KERN_DRIVER_ONLY,
1421530d7b00SHerbert Xu 		.base.base.cra_blocksize = AES_BLOCK_SIZE,
1422530d7b00SHerbert Xu 		.base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1423530d7b00SHerbert Xu 		.base.base.cra_module = THIS_MODULE,
1424530d7b00SHerbert Xu 		.base.base.cra_alignmask = 0,
1425fbf31dd5STom Zanussi 
1426530d7b00SHerbert Xu 		.base.min_keysize = OCS_SM4_KEY_SIZE,
1427530d7b00SHerbert Xu 		.base.max_keysize = OCS_SM4_KEY_SIZE,
1428530d7b00SHerbert Xu 		.base.ivsize = AES_BLOCK_SIZE,
1429530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_sm4_set_key,
1430530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_sm4_cts_encrypt,
1431530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_sm4_cts_decrypt,
1432530d7b00SHerbert Xu 		.base.init = ocs_sm4_init_tfm,
1433530d7b00SHerbert Xu 		.base.exit = ocs_exit_tfm,
1434530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_sk_do_one_request,
1435fbf31dd5STom Zanussi 	}
1436fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS */
1437fbf31dd5STom Zanussi };
1438fbf31dd5STom Zanussi 
1439530d7b00SHerbert Xu static struct aead_engine_alg algs_aead[] = {
1440fbf31dd5STom Zanussi 	{
1441530d7b00SHerbert Xu 		.base.base = {
1442fbf31dd5STom Zanussi 			.cra_name = "gcm(aes)",
1443fbf31dd5STom Zanussi 			.cra_driver_name = "gcm-aes-keembay-ocs",
1444fbf31dd5STom Zanussi 			.cra_priority = KMB_OCS_PRIORITY,
1445fbf31dd5STom Zanussi 			.cra_flags = CRYPTO_ALG_ASYNC |
1446fbf31dd5STom Zanussi 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
1447fbf31dd5STom Zanussi 				     CRYPTO_ALG_NEED_FALLBACK,
1448fbf31dd5STom Zanussi 			.cra_blocksize = 1,
1449fbf31dd5STom Zanussi 			.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1450fbf31dd5STom Zanussi 			.cra_alignmask = 0,
1451fbf31dd5STom Zanussi 			.cra_module = THIS_MODULE,
1452fbf31dd5STom Zanussi 		},
1453530d7b00SHerbert Xu 		.base.init = ocs_aes_aead_cra_init,
1454530d7b00SHerbert Xu 		.base.exit = ocs_aead_cra_exit,
1455530d7b00SHerbert Xu 		.base.ivsize = GCM_AES_IV_SIZE,
1456530d7b00SHerbert Xu 		.base.maxauthsize = AES_BLOCK_SIZE,
1457530d7b00SHerbert Xu 		.base.setauthsize = kmb_ocs_aead_gcm_setauthsize,
1458530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_aes_aead_set_key,
1459530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_aes_gcm_encrypt,
1460530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_aes_gcm_decrypt,
1461530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_aead_do_one_request,
1462fbf31dd5STom Zanussi 	},
1463fbf31dd5STom Zanussi 	{
1464530d7b00SHerbert Xu 		.base.base = {
1465fbf31dd5STom Zanussi 			.cra_name = "ccm(aes)",
1466fbf31dd5STom Zanussi 			.cra_driver_name = "ccm-aes-keembay-ocs",
1467fbf31dd5STom Zanussi 			.cra_priority = KMB_OCS_PRIORITY,
1468fbf31dd5STom Zanussi 			.cra_flags = CRYPTO_ALG_ASYNC |
1469fbf31dd5STom Zanussi 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
1470fbf31dd5STom Zanussi 				     CRYPTO_ALG_NEED_FALLBACK,
1471fbf31dd5STom Zanussi 			.cra_blocksize = 1,
1472fbf31dd5STom Zanussi 			.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1473fbf31dd5STom Zanussi 			.cra_alignmask = 0,
1474fbf31dd5STom Zanussi 			.cra_module = THIS_MODULE,
1475fbf31dd5STom Zanussi 		},
1476530d7b00SHerbert Xu 		.base.init = ocs_aes_aead_cra_init,
1477530d7b00SHerbert Xu 		.base.exit = ocs_aead_cra_exit,
1478530d7b00SHerbert Xu 		.base.ivsize = AES_BLOCK_SIZE,
1479530d7b00SHerbert Xu 		.base.maxauthsize = AES_BLOCK_SIZE,
1480530d7b00SHerbert Xu 		.base.setauthsize = kmb_ocs_aead_ccm_setauthsize,
1481530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_aes_aead_set_key,
1482530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_aes_ccm_encrypt,
1483530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_aes_ccm_decrypt,
1484530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_aead_do_one_request,
1485fbf31dd5STom Zanussi 	},
1486fbf31dd5STom Zanussi 	{
1487530d7b00SHerbert Xu 		.base.base = {
1488fbf31dd5STom Zanussi 			.cra_name = "gcm(sm4)",
1489fbf31dd5STom Zanussi 			.cra_driver_name = "gcm-sm4-keembay-ocs",
1490fbf31dd5STom Zanussi 			.cra_priority = KMB_OCS_PRIORITY,
1491fbf31dd5STom Zanussi 			.cra_flags = CRYPTO_ALG_ASYNC |
1492fbf31dd5STom Zanussi 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1493fbf31dd5STom Zanussi 			.cra_blocksize = 1,
1494fbf31dd5STom Zanussi 			.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1495fbf31dd5STom Zanussi 			.cra_alignmask = 0,
1496fbf31dd5STom Zanussi 			.cra_module = THIS_MODULE,
1497fbf31dd5STom Zanussi 		},
1498530d7b00SHerbert Xu 		.base.init = ocs_sm4_aead_cra_init,
1499530d7b00SHerbert Xu 		.base.exit = ocs_aead_cra_exit,
1500530d7b00SHerbert Xu 		.base.ivsize = GCM_AES_IV_SIZE,
1501530d7b00SHerbert Xu 		.base.maxauthsize = AES_BLOCK_SIZE,
1502530d7b00SHerbert Xu 		.base.setauthsize = kmb_ocs_aead_gcm_setauthsize,
1503530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_sm4_aead_set_key,
1504530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_sm4_gcm_encrypt,
1505530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_sm4_gcm_decrypt,
1506530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_aead_do_one_request,
1507fbf31dd5STom Zanussi 	},
1508fbf31dd5STom Zanussi 	{
1509530d7b00SHerbert Xu 		.base.base = {
1510fbf31dd5STom Zanussi 			.cra_name = "ccm(sm4)",
1511fbf31dd5STom Zanussi 			.cra_driver_name = "ccm-sm4-keembay-ocs",
1512fbf31dd5STom Zanussi 			.cra_priority = KMB_OCS_PRIORITY,
1513fbf31dd5STom Zanussi 			.cra_flags = CRYPTO_ALG_ASYNC |
1514fbf31dd5STom Zanussi 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1515fbf31dd5STom Zanussi 			.cra_blocksize = 1,
1516fbf31dd5STom Zanussi 			.cra_ctxsize = sizeof(struct ocs_aes_tctx),
1517fbf31dd5STom Zanussi 			.cra_alignmask = 0,
1518fbf31dd5STom Zanussi 			.cra_module = THIS_MODULE,
1519fbf31dd5STom Zanussi 		},
1520530d7b00SHerbert Xu 		.base.init = ocs_sm4_aead_cra_init,
1521530d7b00SHerbert Xu 		.base.exit = ocs_aead_cra_exit,
1522530d7b00SHerbert Xu 		.base.ivsize = AES_BLOCK_SIZE,
1523530d7b00SHerbert Xu 		.base.maxauthsize = AES_BLOCK_SIZE,
1524530d7b00SHerbert Xu 		.base.setauthsize = kmb_ocs_aead_ccm_setauthsize,
1525530d7b00SHerbert Xu 		.base.setkey = kmb_ocs_sm4_aead_set_key,
1526530d7b00SHerbert Xu 		.base.encrypt = kmb_ocs_sm4_ccm_encrypt,
1527530d7b00SHerbert Xu 		.base.decrypt = kmb_ocs_sm4_ccm_decrypt,
1528530d7b00SHerbert Xu 		.op.do_one_request = kmb_ocs_aes_aead_do_one_request,
1529fbf31dd5STom Zanussi 	}
1530fbf31dd5STom Zanussi };
1531fbf31dd5STom Zanussi 
unregister_aes_algs(struct ocs_aes_dev * aes_dev)1532fbf31dd5STom Zanussi static void unregister_aes_algs(struct ocs_aes_dev *aes_dev)
1533fbf31dd5STom Zanussi {
1534530d7b00SHerbert Xu 	crypto_engine_unregister_aeads(algs_aead, ARRAY_SIZE(algs_aead));
1535530d7b00SHerbert Xu 	crypto_engine_unregister_skciphers(algs, ARRAY_SIZE(algs));
1536fbf31dd5STom Zanussi }
1537fbf31dd5STom Zanussi 
register_aes_algs(struct ocs_aes_dev * aes_dev)1538fbf31dd5STom Zanussi static int register_aes_algs(struct ocs_aes_dev *aes_dev)
1539fbf31dd5STom Zanussi {
1540fbf31dd5STom Zanussi 	int ret;
1541fbf31dd5STom Zanussi 
1542fbf31dd5STom Zanussi 	/*
1543fbf31dd5STom Zanussi 	 * If any algorithm fails to register, all preceding algorithms that
1544fbf31dd5STom Zanussi 	 * were successfully registered will be automatically unregistered.
1545fbf31dd5STom Zanussi 	 */
1546530d7b00SHerbert Xu 	ret = crypto_engine_register_aeads(algs_aead, ARRAY_SIZE(algs_aead));
1547fbf31dd5STom Zanussi 	if (ret)
1548fbf31dd5STom Zanussi 		return ret;
1549fbf31dd5STom Zanussi 
1550530d7b00SHerbert Xu 	ret = crypto_engine_register_skciphers(algs, ARRAY_SIZE(algs));
1551fbf31dd5STom Zanussi 	if (ret)
1552530d7b00SHerbert Xu 		crypto_engine_unregister_aeads(algs_aead, ARRAY_SIZE(algs));
1553fbf31dd5STom Zanussi 
1554fbf31dd5STom Zanussi 	return ret;
1555fbf31dd5STom Zanussi }
1556fbf31dd5STom Zanussi 
1557fbf31dd5STom Zanussi /* Device tree driver match. */
1558fbf31dd5STom Zanussi static const struct of_device_id kmb_ocs_aes_of_match[] = {
1559fbf31dd5STom Zanussi 	{
1560fbf31dd5STom Zanussi 		.compatible = "intel,keembay-ocs-aes",
1561fbf31dd5STom Zanussi 	},
1562fbf31dd5STom Zanussi 	{}
1563fbf31dd5STom Zanussi };
1564fbf31dd5STom Zanussi 
kmb_ocs_aes_remove(struct platform_device * pdev)1565*98272bf6SUwe Kleine-König static void kmb_ocs_aes_remove(struct platform_device *pdev)
1566fbf31dd5STom Zanussi {
1567fbf31dd5STom Zanussi 	struct ocs_aes_dev *aes_dev;
1568fbf31dd5STom Zanussi 
1569fbf31dd5STom Zanussi 	aes_dev = platform_get_drvdata(pdev);
1570fbf31dd5STom Zanussi 
1571fbf31dd5STom Zanussi 	unregister_aes_algs(aes_dev);
1572fbf31dd5STom Zanussi 
1573fbf31dd5STom Zanussi 	spin_lock(&ocs_aes.lock);
1574fbf31dd5STom Zanussi 	list_del(&aes_dev->list);
1575fbf31dd5STom Zanussi 	spin_unlock(&ocs_aes.lock);
1576fbf31dd5STom Zanussi 
1577fbf31dd5STom Zanussi 	crypto_engine_exit(aes_dev->engine);
1578fbf31dd5STom Zanussi }
1579fbf31dd5STom Zanussi 
kmb_ocs_aes_probe(struct platform_device * pdev)1580fbf31dd5STom Zanussi static int kmb_ocs_aes_probe(struct platform_device *pdev)
1581fbf31dd5STom Zanussi {
1582fbf31dd5STom Zanussi 	struct device *dev = &pdev->dev;
1583fbf31dd5STom Zanussi 	struct ocs_aes_dev *aes_dev;
1584fbf31dd5STom Zanussi 	int rc;
1585fbf31dd5STom Zanussi 
1586fbf31dd5STom Zanussi 	aes_dev = devm_kzalloc(dev, sizeof(*aes_dev), GFP_KERNEL);
1587fbf31dd5STom Zanussi 	if (!aes_dev)
1588fbf31dd5STom Zanussi 		return -ENOMEM;
1589fbf31dd5STom Zanussi 
1590fbf31dd5STom Zanussi 	aes_dev->dev = dev;
1591fbf31dd5STom Zanussi 
1592fbf31dd5STom Zanussi 	platform_set_drvdata(pdev, aes_dev);
1593fbf31dd5STom Zanussi 
1594fbf31dd5STom Zanussi 	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
1595fbf31dd5STom Zanussi 	if (rc) {
1596fbf31dd5STom Zanussi 		dev_err(dev, "Failed to set 32 bit dma mask %d\n", rc);
1597fbf31dd5STom Zanussi 		return rc;
1598fbf31dd5STom Zanussi 	}
1599fbf31dd5STom Zanussi 
1600fbf31dd5STom Zanussi 	/* Get base register address. */
1601fbf31dd5STom Zanussi 	aes_dev->base_reg = devm_platform_ioremap_resource(pdev, 0);
1602fbf31dd5STom Zanussi 	if (IS_ERR(aes_dev->base_reg))
1603fbf31dd5STom Zanussi 		return PTR_ERR(aes_dev->base_reg);
1604fbf31dd5STom Zanussi 
1605fbf31dd5STom Zanussi 	/* Get and request IRQ */
1606fbf31dd5STom Zanussi 	aes_dev->irq = platform_get_irq(pdev, 0);
1607fbf31dd5STom Zanussi 	if (aes_dev->irq < 0)
1608fbf31dd5STom Zanussi 		return aes_dev->irq;
1609fbf31dd5STom Zanussi 
1610fbf31dd5STom Zanussi 	rc = devm_request_threaded_irq(dev, aes_dev->irq, ocs_aes_irq_handler,
1611fbf31dd5STom Zanussi 				       NULL, 0, "keembay-ocs-aes", aes_dev);
1612fbf31dd5STom Zanussi 	if (rc < 0) {
1613fbf31dd5STom Zanussi 		dev_err(dev, "Could not request IRQ\n");
1614fbf31dd5STom Zanussi 		return rc;
1615fbf31dd5STom Zanussi 	}
1616fbf31dd5STom Zanussi 
1617fbf31dd5STom Zanussi 	INIT_LIST_HEAD(&aes_dev->list);
1618fbf31dd5STom Zanussi 	spin_lock(&ocs_aes.lock);
1619fbf31dd5STom Zanussi 	list_add_tail(&aes_dev->list, &ocs_aes.dev_list);
1620fbf31dd5STom Zanussi 	spin_unlock(&ocs_aes.lock);
1621fbf31dd5STom Zanussi 
1622fbf31dd5STom Zanussi 	init_completion(&aes_dev->irq_completion);
1623fbf31dd5STom Zanussi 
1624fbf31dd5STom Zanussi 	/* Initialize crypto engine */
1625fbf31dd5STom Zanussi 	aes_dev->engine = crypto_engine_alloc_init(dev, true);
1626fbf31dd5STom Zanussi 	if (!aes_dev->engine) {
1627fbf31dd5STom Zanussi 		rc = -ENOMEM;
1628fbf31dd5STom Zanussi 		goto list_del;
1629fbf31dd5STom Zanussi 	}
1630fbf31dd5STom Zanussi 
1631fbf31dd5STom Zanussi 	rc = crypto_engine_start(aes_dev->engine);
1632fbf31dd5STom Zanussi 	if (rc) {
1633fbf31dd5STom Zanussi 		dev_err(dev, "Could not start crypto engine\n");
1634fbf31dd5STom Zanussi 		goto cleanup;
1635fbf31dd5STom Zanussi 	}
1636fbf31dd5STom Zanussi 
1637fbf31dd5STom Zanussi 	rc = register_aes_algs(aes_dev);
1638fbf31dd5STom Zanussi 	if (rc) {
1639fbf31dd5STom Zanussi 		dev_err(dev,
1640fbf31dd5STom Zanussi 			"Could not register OCS algorithms with Crypto API\n");
1641fbf31dd5STom Zanussi 		goto cleanup;
1642fbf31dd5STom Zanussi 	}
1643fbf31dd5STom Zanussi 
1644fbf31dd5STom Zanussi 	return 0;
1645fbf31dd5STom Zanussi 
1646fbf31dd5STom Zanussi cleanup:
1647fbf31dd5STom Zanussi 	crypto_engine_exit(aes_dev->engine);
1648fbf31dd5STom Zanussi list_del:
1649fbf31dd5STom Zanussi 	spin_lock(&ocs_aes.lock);
1650fbf31dd5STom Zanussi 	list_del(&aes_dev->list);
1651fbf31dd5STom Zanussi 	spin_unlock(&ocs_aes.lock);
1652fbf31dd5STom Zanussi 
1653fbf31dd5STom Zanussi 	return rc;
1654fbf31dd5STom Zanussi }
1655fbf31dd5STom Zanussi 
1656fbf31dd5STom Zanussi /* The OCS driver is a platform device. */
1657fbf31dd5STom Zanussi static struct platform_driver kmb_ocs_aes_driver = {
1658fbf31dd5STom Zanussi 	.probe = kmb_ocs_aes_probe,
1659*98272bf6SUwe Kleine-König 	.remove_new = kmb_ocs_aes_remove,
1660fbf31dd5STom Zanussi 	.driver = {
1661fbf31dd5STom Zanussi 			.name = DRV_NAME,
1662fbf31dd5STom Zanussi 			.of_match_table = kmb_ocs_aes_of_match,
1663fbf31dd5STom Zanussi 		},
1664fbf31dd5STom Zanussi };
1665fbf31dd5STom Zanussi 
1666fbf31dd5STom Zanussi module_platform_driver(kmb_ocs_aes_driver);
1667fbf31dd5STom Zanussi 
1668fbf31dd5STom Zanussi MODULE_DESCRIPTION("Intel Keem Bay Offload and Crypto Subsystem (OCS) AES/SM4 Driver");
1669fbf31dd5STom Zanussi MODULE_LICENSE("GPL");
1670fbf31dd5STom Zanussi 
1671fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("cbc-aes-keembay-ocs");
1672fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("ctr-aes-keembay-ocs");
1673fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("gcm-aes-keembay-ocs");
1674fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("ccm-aes-keembay-ocs");
1675fbf31dd5STom Zanussi 
1676fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("cbc-sm4-keembay-ocs");
1677fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("ctr-sm4-keembay-ocs");
1678fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("gcm-sm4-keembay-ocs");
1679fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("ccm-sm4-keembay-ocs");
1680fbf31dd5STom Zanussi 
1681fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB
1682fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("ecb-aes-keembay-ocs");
1683fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("ecb-sm4-keembay-ocs");
1684fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB */
1685fbf31dd5STom Zanussi 
1686fbf31dd5STom Zanussi #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS
1687fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("cts-aes-keembay-ocs");
1688fbf31dd5STom Zanussi MODULE_ALIAS_CRYPTO("cts-sm4-keembay-ocs");
1689fbf31dd5STom Zanussi #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS */
1690