11b44c5a6SAntoine Ténart /*
21b44c5a6SAntoine Ténart  * Copyright (C) 2017 Marvell
31b44c5a6SAntoine Ténart  *
41b44c5a6SAntoine Ténart  * Antoine Tenart <antoine.tenart@free-electrons.com>
51b44c5a6SAntoine Ténart  *
61b44c5a6SAntoine Ténart  * This file is licensed under the terms of the GNU General Public
71b44c5a6SAntoine Ténart  * License version 2. This program is licensed "as is" without any
81b44c5a6SAntoine Ténart  * warranty of any kind, whether express or implied.
91b44c5a6SAntoine Ténart  */
101b44c5a6SAntoine Ténart 
111b44c5a6SAntoine Ténart #include <linux/device.h>
121b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
131b44c5a6SAntoine Ténart #include <linux/dmapool.h>
141b44c5a6SAntoine Ténart 
15f6beaea3SAntoine Tenart #include <crypto/aead.h>
161b44c5a6SAntoine Ténart #include <crypto/aes.h>
17f6beaea3SAntoine Tenart #include <crypto/authenc.h>
18f6beaea3SAntoine Tenart #include <crypto/sha.h>
191b44c5a6SAntoine Ténart #include <crypto/skcipher.h>
20f6beaea3SAntoine Tenart #include <crypto/internal/aead.h>
211eb7b403SOfer Heifetz #include <crypto/internal/skcipher.h>
221b44c5a6SAntoine Ténart 
231b44c5a6SAntoine Ténart #include "safexcel.h"
241b44c5a6SAntoine Ténart 
251b44c5a6SAntoine Ténart enum safexcel_cipher_direction {
261b44c5a6SAntoine Ténart 	SAFEXCEL_ENCRYPT,
271b44c5a6SAntoine Ténart 	SAFEXCEL_DECRYPT,
281b44c5a6SAntoine Ténart };
291b44c5a6SAntoine Ténart 
301b44c5a6SAntoine Ténart struct safexcel_cipher_ctx {
311b44c5a6SAntoine Ténart 	struct safexcel_context base;
321b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
331b44c5a6SAntoine Ténart 
341b44c5a6SAntoine Ténart 	u32 mode;
35f6beaea3SAntoine Tenart 	bool aead;
361b44c5a6SAntoine Ténart 
371b44c5a6SAntoine Ténart 	__le32 key[8];
381b44c5a6SAntoine Ténart 	unsigned int key_len;
39f6beaea3SAntoine Tenart 
40f6beaea3SAntoine Tenart 	/* All the below is AEAD specific */
41f6beaea3SAntoine Tenart 	u32 alg;
42f6beaea3SAntoine Tenart 	u32 state_sz;
43f6beaea3SAntoine Tenart 	u32 ipad[SHA256_DIGEST_SIZE / sizeof(u32)];
44f6beaea3SAntoine Tenart 	u32 opad[SHA256_DIGEST_SIZE / sizeof(u32)];
451b44c5a6SAntoine Ténart };
461b44c5a6SAntoine Ténart 
471eb7b403SOfer Heifetz struct safexcel_cipher_req {
48847ccfc5SOfer Heifetz 	enum safexcel_cipher_direction direction;
491eb7b403SOfer Heifetz 	bool needs_inv;
501eb7b403SOfer Heifetz };
511eb7b403SOfer Heifetz 
528ac1283eSAntoine Tenart static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
531b44c5a6SAntoine Ténart 				    struct safexcel_command_desc *cdesc,
541b44c5a6SAntoine Ténart 				    u32 length)
551b44c5a6SAntoine Ténart {
561b44c5a6SAntoine Ténart 	struct safexcel_token *token;
571b44c5a6SAntoine Ténart 	unsigned offset = 0;
581b44c5a6SAntoine Ténart 
591b44c5a6SAntoine Ténart 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) {
601b44c5a6SAntoine Ténart 		offset = AES_BLOCK_SIZE / sizeof(u32);
618ac1283eSAntoine Tenart 		memcpy(cdesc->control_data.token, iv, AES_BLOCK_SIZE);
621b44c5a6SAntoine Ténart 
631b44c5a6SAntoine Ténart 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
641b44c5a6SAntoine Ténart 	}
651b44c5a6SAntoine Ténart 
661b44c5a6SAntoine Ténart 	token = (struct safexcel_token *)(cdesc->control_data.token + offset);
671b44c5a6SAntoine Ténart 
681b44c5a6SAntoine Ténart 	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
691b44c5a6SAntoine Ténart 	token[0].packet_length = length;
7015f64ee0SAntoine Tenart 	token[0].stat = EIP197_TOKEN_STAT_LAST_PACKET |
7115f64ee0SAntoine Tenart 			EIP197_TOKEN_STAT_LAST_HASH;
721b44c5a6SAntoine Ténart 	token[0].instructions = EIP197_TOKEN_INS_LAST |
731b44c5a6SAntoine Ténart 				EIP197_TOKEN_INS_TYPE_CRYTO |
741b44c5a6SAntoine Ténart 				EIP197_TOKEN_INS_TYPE_OUTPUT;
751b44c5a6SAntoine Ténart }
761b44c5a6SAntoine Ténart 
77f6beaea3SAntoine Tenart static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
78f6beaea3SAntoine Tenart 				struct safexcel_command_desc *cdesc,
79f6beaea3SAntoine Tenart 				enum safexcel_cipher_direction direction,
80f6beaea3SAntoine Tenart 				u32 cryptlen, u32 assoclen, u32 digestsize)
81f6beaea3SAntoine Tenart {
82f6beaea3SAntoine Tenart 	struct safexcel_token *token;
83f6beaea3SAntoine Tenart 	unsigned offset = 0;
84f6beaea3SAntoine Tenart 
85f6beaea3SAntoine Tenart 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) {
86f6beaea3SAntoine Tenart 		offset = AES_BLOCK_SIZE / sizeof(u32);
87f6beaea3SAntoine Tenart 		memcpy(cdesc->control_data.token, iv, AES_BLOCK_SIZE);
88f6beaea3SAntoine Tenart 
89f6beaea3SAntoine Tenart 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
90f6beaea3SAntoine Tenart 	}
91f6beaea3SAntoine Tenart 
92f6beaea3SAntoine Tenart 	token = (struct safexcel_token *)(cdesc->control_data.token + offset);
93f6beaea3SAntoine Tenart 
94f6beaea3SAntoine Tenart 	if (direction == SAFEXCEL_DECRYPT)
95f6beaea3SAntoine Tenart 		cryptlen -= digestsize;
96f6beaea3SAntoine Tenart 
97f6beaea3SAntoine Tenart 	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
98f6beaea3SAntoine Tenart 	token[0].packet_length = assoclen;
99f6beaea3SAntoine Tenart 	token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH |
100f6beaea3SAntoine Tenart 				EIP197_TOKEN_INS_TYPE_OUTPUT;
101f6beaea3SAntoine Tenart 
102f6beaea3SAntoine Tenart 	token[1].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
103f6beaea3SAntoine Tenart 	token[1].packet_length = cryptlen;
104f6beaea3SAntoine Tenart 	token[1].stat = EIP197_TOKEN_STAT_LAST_HASH;
105f6beaea3SAntoine Tenart 	token[1].instructions = EIP197_TOKEN_INS_LAST |
106f6beaea3SAntoine Tenart 				EIP197_TOKEN_INS_TYPE_CRYTO |
107f6beaea3SAntoine Tenart 				EIP197_TOKEN_INS_TYPE_HASH |
108f6beaea3SAntoine Tenart 				EIP197_TOKEN_INS_TYPE_OUTPUT;
109f6beaea3SAntoine Tenart 
110f6beaea3SAntoine Tenart 	if (direction == SAFEXCEL_ENCRYPT) {
111f6beaea3SAntoine Tenart 		token[2].opcode = EIP197_TOKEN_OPCODE_INSERT;
112f6beaea3SAntoine Tenart 		token[2].packet_length = digestsize;
113f6beaea3SAntoine Tenart 		token[2].stat = EIP197_TOKEN_STAT_LAST_HASH |
114f6beaea3SAntoine Tenart 				EIP197_TOKEN_STAT_LAST_PACKET;
115f6beaea3SAntoine Tenart 		token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
116f6beaea3SAntoine Tenart 					EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
117f6beaea3SAntoine Tenart 	} else {
118f6beaea3SAntoine Tenart 		token[2].opcode = EIP197_TOKEN_OPCODE_RETRIEVE;
119f6beaea3SAntoine Tenart 		token[2].packet_length = digestsize;
120f6beaea3SAntoine Tenart 		token[2].stat = EIP197_TOKEN_STAT_LAST_HASH |
121f6beaea3SAntoine Tenart 				EIP197_TOKEN_STAT_LAST_PACKET;
122f6beaea3SAntoine Tenart 		token[2].instructions = EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
123f6beaea3SAntoine Tenart 
124f6beaea3SAntoine Tenart 		token[3].opcode = EIP197_TOKEN_OPCODE_VERIFY;
125f6beaea3SAntoine Tenart 		token[3].packet_length = digestsize |
126f6beaea3SAntoine Tenart 					 EIP197_TOKEN_HASH_RESULT_VERIFY;
127f6beaea3SAntoine Tenart 		token[3].stat = EIP197_TOKEN_STAT_LAST_HASH |
128f6beaea3SAntoine Tenart 				EIP197_TOKEN_STAT_LAST_PACKET;
129f6beaea3SAntoine Tenart 		token[3].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT;
130f6beaea3SAntoine Tenart 	}
131f6beaea3SAntoine Tenart }
132f6beaea3SAntoine Tenart 
1338ac1283eSAntoine Tenart static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm,
1348ac1283eSAntoine Tenart 					const u8 *key, unsigned int len)
1351b44c5a6SAntoine Ténart {
1361b44c5a6SAntoine Ténart 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
1371b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
138871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
1391b44c5a6SAntoine Ténart 	struct crypto_aes_ctx aes;
1401b44c5a6SAntoine Ténart 	int ret, i;
1411b44c5a6SAntoine Ténart 
1421b44c5a6SAntoine Ténart 	ret = crypto_aes_expand_key(&aes, key, len);
1431b44c5a6SAntoine Ténart 	if (ret) {
1441b44c5a6SAntoine Ténart 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
1451b44c5a6SAntoine Ténart 		return ret;
1461b44c5a6SAntoine Ténart 	}
1471b44c5a6SAntoine Ténart 
148871df319SAntoine Ténart 	if (priv->version == EIP197 && ctx->base.ctxr_dma) {
1491b44c5a6SAntoine Ténart 		for (i = 0; i < len / sizeof(u32); i++) {
1501b44c5a6SAntoine Ténart 			if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) {
1511b44c5a6SAntoine Ténart 				ctx->base.needs_inv = true;
1521b44c5a6SAntoine Ténart 				break;
1531b44c5a6SAntoine Ténart 			}
1541b44c5a6SAntoine Ténart 		}
155c4daf4ccSOfer Heifetz 	}
1561b44c5a6SAntoine Ténart 
1571b44c5a6SAntoine Ténart 	for (i = 0; i < len / sizeof(u32); i++)
1581b44c5a6SAntoine Ténart 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
1591b44c5a6SAntoine Ténart 
1601b44c5a6SAntoine Ténart 	ctx->key_len = len;
1611b44c5a6SAntoine Ténart 
1621b44c5a6SAntoine Ténart 	memzero_explicit(&aes, sizeof(aes));
1631b44c5a6SAntoine Ténart 	return 0;
1641b44c5a6SAntoine Ténart }
1651b44c5a6SAntoine Ténart 
166f6beaea3SAntoine Tenart static int safexcel_aead_aes_setkey(struct crypto_aead *ctfm, const u8 *key,
167f6beaea3SAntoine Tenart 				    unsigned int len)
168f6beaea3SAntoine Tenart {
169f6beaea3SAntoine Tenart 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
170f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
171f6beaea3SAntoine Tenart 	struct safexcel_ahash_export_state istate, ostate;
172f6beaea3SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
173f6beaea3SAntoine Tenart 	struct crypto_authenc_keys keys;
174f6beaea3SAntoine Tenart 
175f6beaea3SAntoine Tenart 	if (crypto_authenc_extractkeys(&keys, key, len) != 0)
176f6beaea3SAntoine Tenart 		goto badkey;
177f6beaea3SAntoine Tenart 
178f6beaea3SAntoine Tenart 	if (keys.enckeylen > sizeof(ctx->key))
179f6beaea3SAntoine Tenart 		goto badkey;
180f6beaea3SAntoine Tenart 
181f6beaea3SAntoine Tenart 	/* Encryption key */
182f6beaea3SAntoine Tenart 	if (priv->version == EIP197 && ctx->base.ctxr_dma &&
183f6beaea3SAntoine Tenart 	    memcmp(ctx->key, keys.enckey, keys.enckeylen))
184f6beaea3SAntoine Tenart 		ctx->base.needs_inv = true;
185f6beaea3SAntoine Tenart 
186f6beaea3SAntoine Tenart 	/* Auth key */
187f6beaea3SAntoine Tenart 	if (safexcel_hmac_setkey("safexcel-sha256", keys.authkey,
188f6beaea3SAntoine Tenart 				 keys.authkeylen, &istate, &ostate))
189f6beaea3SAntoine Tenart 		goto badkey;
190f6beaea3SAntoine Tenart 
191f6beaea3SAntoine Tenart 	crypto_aead_set_flags(ctfm, crypto_aead_get_flags(ctfm) &
192f6beaea3SAntoine Tenart 				    CRYPTO_TFM_RES_MASK);
193f6beaea3SAntoine Tenart 
194f6beaea3SAntoine Tenart 	if (priv->version == EIP197 && ctx->base.ctxr_dma &&
195f6beaea3SAntoine Tenart 	    (memcmp(ctx->ipad, istate.state, ctx->state_sz) ||
196f6beaea3SAntoine Tenart 	     memcmp(ctx->opad, ostate.state, ctx->state_sz)))
197f6beaea3SAntoine Tenart 		ctx->base.needs_inv = true;
198f6beaea3SAntoine Tenart 
199f6beaea3SAntoine Tenart 	/* Now copy the keys into the context */
200f6beaea3SAntoine Tenart 	memcpy(ctx->key, keys.enckey, keys.enckeylen);
201f6beaea3SAntoine Tenart 	ctx->key_len = keys.enckeylen;
202f6beaea3SAntoine Tenart 
203f6beaea3SAntoine Tenart 	memcpy(ctx->ipad, &istate.state, ctx->state_sz);
204f6beaea3SAntoine Tenart 	memcpy(ctx->opad, &ostate.state, ctx->state_sz);
205f6beaea3SAntoine Tenart 
206f6beaea3SAntoine Tenart 	memzero_explicit(&keys, sizeof(keys));
207f6beaea3SAntoine Tenart 	return 0;
208f6beaea3SAntoine Tenart 
209f6beaea3SAntoine Tenart badkey:
210f6beaea3SAntoine Tenart 	crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
211f6beaea3SAntoine Tenart 	memzero_explicit(&keys, sizeof(keys));
212f6beaea3SAntoine Tenart 	return -EINVAL;
213f6beaea3SAntoine Tenart }
214f6beaea3SAntoine Tenart 
2151b44c5a6SAntoine Ténart static int safexcel_context_control(struct safexcel_cipher_ctx *ctx,
216847ccfc5SOfer Heifetz 				    struct crypto_async_request *async,
2178ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
2181b44c5a6SAntoine Ténart 				    struct safexcel_command_desc *cdesc)
2191b44c5a6SAntoine Ténart {
2201b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
2211b44c5a6SAntoine Ténart 	int ctrl_size;
2221b44c5a6SAntoine Ténart 
223f6beaea3SAntoine Tenart 	if (ctx->aead) {
224f6beaea3SAntoine Tenart 		if (sreq->direction == SAFEXCEL_ENCRYPT)
225f6beaea3SAntoine Tenart 			cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT;
226f6beaea3SAntoine Tenart 		else
227f6beaea3SAntoine Tenart 			cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN;
228f6beaea3SAntoine Tenart 	} else {
2291b44c5a6SAntoine Ténart 		cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_CRYPTO_OUT;
2303a5ca230SAntoine Tenart 
231f6beaea3SAntoine Tenart 		/* The decryption control type is a combination of the
232f6beaea3SAntoine Tenart 		 * encryption type and CONTEXT_CONTROL_TYPE_NULL_IN, for all
233f6beaea3SAntoine Tenart 		 * types.
2343a5ca230SAntoine Tenart 		 */
2353a5ca230SAntoine Tenart 		if (sreq->direction == SAFEXCEL_DECRYPT)
2363a5ca230SAntoine Tenart 			cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_NULL_IN;
237f6beaea3SAntoine Tenart 	}
2381b44c5a6SAntoine Ténart 
2391b44c5a6SAntoine Ténart 	cdesc->control_data.control0 |= CONTEXT_CONTROL_KEY_EN;
2401b44c5a6SAntoine Ténart 	cdesc->control_data.control1 |= ctx->mode;
2411b44c5a6SAntoine Ténart 
242f6beaea3SAntoine Tenart 	if (ctx->aead)
243f6beaea3SAntoine Tenart 		cdesc->control_data.control0 |= CONTEXT_CONTROL_DIGEST_HMAC |
244f6beaea3SAntoine Tenart 						ctx->alg;
245f6beaea3SAntoine Tenart 
2461b44c5a6SAntoine Ténart 	switch (ctx->key_len) {
2471b44c5a6SAntoine Ténart 	case AES_KEYSIZE_128:
2481b44c5a6SAntoine Ténart 		cdesc->control_data.control0 |= CONTEXT_CONTROL_CRYPTO_ALG_AES128;
2491b44c5a6SAntoine Ténart 		break;
2501b44c5a6SAntoine Ténart 	case AES_KEYSIZE_192:
2511b44c5a6SAntoine Ténart 		cdesc->control_data.control0 |= CONTEXT_CONTROL_CRYPTO_ALG_AES192;
2521b44c5a6SAntoine Ténart 		break;
2531b44c5a6SAntoine Ténart 	case AES_KEYSIZE_256:
2541b44c5a6SAntoine Ténart 		cdesc->control_data.control0 |= CONTEXT_CONTROL_CRYPTO_ALG_AES256;
2551b44c5a6SAntoine Ténart 		break;
2561b44c5a6SAntoine Ténart 	default:
2571b44c5a6SAntoine Ténart 		dev_err(priv->dev, "aes keysize not supported: %u\n",
2581b44c5a6SAntoine Ténart 			ctx->key_len);
2591b44c5a6SAntoine Ténart 		return -EINVAL;
2601b44c5a6SAntoine Ténart 	}
261fef0cfe5SAntoine Tenart 
262fef0cfe5SAntoine Tenart 	ctrl_size = ctx->key_len / sizeof(u32);
263f6beaea3SAntoine Tenart 	if (ctx->aead)
264f6beaea3SAntoine Tenart 		/* Take in account the ipad+opad digests */
265f6beaea3SAntoine Tenart 		ctrl_size += ctx->state_sz / sizeof(u32) * 2;
2661b44c5a6SAntoine Ténart 	cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(ctrl_size);
2671b44c5a6SAntoine Ténart 
2681b44c5a6SAntoine Ténart 	return 0;
2691b44c5a6SAntoine Ténart }
2701b44c5a6SAntoine Ténart 
2711eb7b403SOfer Heifetz static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int ring,
2721b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
2738ac1283eSAntoine Tenart 				      struct scatterlist *src,
2748ac1283eSAntoine Tenart 				      struct scatterlist *dst,
2758ac1283eSAntoine Tenart 				      unsigned int cryptlen,
2768ac1283eSAntoine Tenart 				      struct safexcel_cipher_req *sreq,
2771b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
2781b44c5a6SAntoine Ténart {
2791b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
2801b44c5a6SAntoine Ténart 	int ndesc = 0;
2811b44c5a6SAntoine Ténart 
2821b44c5a6SAntoine Ténart 	*ret = 0;
2831b44c5a6SAntoine Ténart 
2841b44c5a6SAntoine Ténart 	spin_lock_bh(&priv->ring[ring].egress_lock);
2851b44c5a6SAntoine Ténart 	do {
2861b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
2871b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
2881b44c5a6SAntoine Ténart 			dev_err(priv->dev,
2891b44c5a6SAntoine Ténart 				"cipher: result: could not retrieve the result descriptor\n");
2901b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
2911b44c5a6SAntoine Ténart 			break;
2921b44c5a6SAntoine Ténart 		}
2931b44c5a6SAntoine Ténart 
294bdfd1909SAntoine Tenart 		if (likely(!*ret))
295bdfd1909SAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
2961b44c5a6SAntoine Ténart 
2971b44c5a6SAntoine Ténart 		ndesc++;
2981b44c5a6SAntoine Ténart 	} while (!rdesc->last_seg);
2991b44c5a6SAntoine Ténart 
3001b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
3011b44c5a6SAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].egress_lock);
3021b44c5a6SAntoine Ténart 
3038ac1283eSAntoine Tenart 	if (src == dst) {
3048ac1283eSAntoine Tenart 		dma_unmap_sg(priv->dev, src,
3058ac1283eSAntoine Tenart 			     sg_nents_for_len(src, cryptlen),
3061b44c5a6SAntoine Ténart 			     DMA_BIDIRECTIONAL);
3071b44c5a6SAntoine Ténart 	} else {
3088ac1283eSAntoine Tenart 		dma_unmap_sg(priv->dev, src,
3098ac1283eSAntoine Tenart 			     sg_nents_for_len(src, cryptlen),
3101b44c5a6SAntoine Ténart 			     DMA_TO_DEVICE);
3118ac1283eSAntoine Tenart 		dma_unmap_sg(priv->dev, dst,
3128ac1283eSAntoine Tenart 			     sg_nents_for_len(dst, cryptlen),
3131b44c5a6SAntoine Ténart 			     DMA_FROM_DEVICE);
3141b44c5a6SAntoine Ténart 	}
3151b44c5a6SAntoine Ténart 
3161b44c5a6SAntoine Ténart 	*should_complete = true;
3171b44c5a6SAntoine Ténart 
3181b44c5a6SAntoine Ténart 	return ndesc;
3191b44c5a6SAntoine Ténart }
3201b44c5a6SAntoine Ténart 
3218ac1283eSAntoine Tenart static int safexcel_aes_send(struct crypto_async_request *base, int ring,
3228ac1283eSAntoine Tenart 			     struct safexcel_request *request,
3238ac1283eSAntoine Tenart 			     struct safexcel_cipher_req *sreq,
3248ac1283eSAntoine Tenart 			     struct scatterlist *src, struct scatterlist *dst,
325f6beaea3SAntoine Tenart 			     unsigned int cryptlen, unsigned int assoclen,
326f6beaea3SAntoine Tenart 			     unsigned int digestsize, u8 *iv, int *commands,
3278ac1283eSAntoine Tenart 			     int *results)
3281b44c5a6SAntoine Ténart {
3298ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
3301b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
3311b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc;
3321b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
3331b44c5a6SAntoine Ténart 	struct scatterlist *sg;
334f6beaea3SAntoine Tenart 	unsigned int totlen = cryptlen + assoclen;
335f6beaea3SAntoine Tenart 	int nr_src, nr_dst, n_cdesc = 0, n_rdesc = 0, queued = totlen;
3361b44c5a6SAntoine Ténart 	int i, ret = 0;
3371b44c5a6SAntoine Ténart 
3388ac1283eSAntoine Tenart 	if (src == dst) {
3398ac1283eSAntoine Tenart 		nr_src = dma_map_sg(priv->dev, src,
340f6beaea3SAntoine Tenart 				    sg_nents_for_len(src, totlen),
3411b44c5a6SAntoine Ténart 				    DMA_BIDIRECTIONAL);
3421b44c5a6SAntoine Ténart 		nr_dst = nr_src;
3431b44c5a6SAntoine Ténart 		if (!nr_src)
3441b44c5a6SAntoine Ténart 			return -EINVAL;
3451b44c5a6SAntoine Ténart 	} else {
3468ac1283eSAntoine Tenart 		nr_src = dma_map_sg(priv->dev, src,
347f6beaea3SAntoine Tenart 				    sg_nents_for_len(src, totlen),
3481b44c5a6SAntoine Ténart 				    DMA_TO_DEVICE);
3491b44c5a6SAntoine Ténart 		if (!nr_src)
3501b44c5a6SAntoine Ténart 			return -EINVAL;
3511b44c5a6SAntoine Ténart 
3528ac1283eSAntoine Tenart 		nr_dst = dma_map_sg(priv->dev, dst,
353f6beaea3SAntoine Tenart 				    sg_nents_for_len(dst, totlen),
3541b44c5a6SAntoine Ténart 				    DMA_FROM_DEVICE);
3551b44c5a6SAntoine Ténart 		if (!nr_dst) {
3568ac1283eSAntoine Tenart 			dma_unmap_sg(priv->dev, src,
357f6beaea3SAntoine Tenart 				     sg_nents_for_len(src, totlen),
3581b44c5a6SAntoine Ténart 				     DMA_TO_DEVICE);
3591b44c5a6SAntoine Ténart 			return -EINVAL;
3601b44c5a6SAntoine Ténart 		}
3611b44c5a6SAntoine Ténart 	}
3621b44c5a6SAntoine Ténart 
3631b44c5a6SAntoine Ténart 	memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len);
3641b44c5a6SAntoine Ténart 
365f6beaea3SAntoine Tenart 	if (ctx->aead) {
366f6beaea3SAntoine Tenart 		memcpy(ctx->base.ctxr->data + ctx->key_len / sizeof(u32),
367f6beaea3SAntoine Tenart 		       ctx->ipad, ctx->state_sz);
368f6beaea3SAntoine Tenart 		memcpy(ctx->base.ctxr->data + (ctx->key_len + ctx->state_sz) / sizeof(u32),
369f6beaea3SAntoine Tenart 		       ctx->opad, ctx->state_sz);
370f6beaea3SAntoine Tenart 	}
371f6beaea3SAntoine Tenart 
3721b44c5a6SAntoine Ténart 	spin_lock_bh(&priv->ring[ring].egress_lock);
3731b44c5a6SAntoine Ténart 
3741b44c5a6SAntoine Ténart 	/* command descriptors */
3758ac1283eSAntoine Tenart 	for_each_sg(src, sg, nr_src, i) {
3761b44c5a6SAntoine Ténart 		int len = sg_dma_len(sg);
3771b44c5a6SAntoine Ténart 
3781b44c5a6SAntoine Ténart 		/* Do not overflow the request */
3791b44c5a6SAntoine Ténart 		if (queued - len < 0)
3801b44c5a6SAntoine Ténart 			len = queued;
3811b44c5a6SAntoine Ténart 
3821b44c5a6SAntoine Ténart 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, !(queued - len),
383f6beaea3SAntoine Tenart 					   sg_dma_address(sg), len, totlen,
3841b44c5a6SAntoine Ténart 					   ctx->base.ctxr_dma);
3851b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
3861b44c5a6SAntoine Ténart 			/* No space left in the command descriptor ring */
3871b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
3881b44c5a6SAntoine Ténart 			goto cdesc_rollback;
3891b44c5a6SAntoine Ténart 		}
3901b44c5a6SAntoine Ténart 		n_cdesc++;
3911b44c5a6SAntoine Ténart 
3921b44c5a6SAntoine Ténart 		if (n_cdesc == 1) {
3938ac1283eSAntoine Tenart 			safexcel_context_control(ctx, base, sreq, cdesc);
394f6beaea3SAntoine Tenart 			if (ctx->aead)
395f6beaea3SAntoine Tenart 				safexcel_aead_token(ctx, iv, cdesc,
396f6beaea3SAntoine Tenart 						    sreq->direction, cryptlen,
397f6beaea3SAntoine Tenart 						    assoclen, digestsize);
398f6beaea3SAntoine Tenart 			else
399f6beaea3SAntoine Tenart 				safexcel_skcipher_token(ctx, iv, cdesc,
400f6beaea3SAntoine Tenart 							cryptlen);
4011b44c5a6SAntoine Ténart 		}
4021b44c5a6SAntoine Ténart 
4031b44c5a6SAntoine Ténart 		queued -= len;
4041b44c5a6SAntoine Ténart 		if (!queued)
4051b44c5a6SAntoine Ténart 			break;
4061b44c5a6SAntoine Ténart 	}
4071b44c5a6SAntoine Ténart 
4081b44c5a6SAntoine Ténart 	/* result descriptors */
4098ac1283eSAntoine Tenart 	for_each_sg(dst, sg, nr_dst, i) {
4101b44c5a6SAntoine Ténart 		bool first = !i, last = (i == nr_dst - 1);
4111b44c5a6SAntoine Ténart 		u32 len = sg_dma_len(sg);
4121b44c5a6SAntoine Ténart 
4131b44c5a6SAntoine Ténart 		rdesc = safexcel_add_rdesc(priv, ring, first, last,
4141b44c5a6SAntoine Ténart 					   sg_dma_address(sg), len);
4151b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
4161b44c5a6SAntoine Ténart 			/* No space left in the result descriptor ring */
4171b44c5a6SAntoine Ténart 			ret = PTR_ERR(rdesc);
4181b44c5a6SAntoine Ténart 			goto rdesc_rollback;
4191b44c5a6SAntoine Ténart 		}
4201b44c5a6SAntoine Ténart 		n_rdesc++;
4211b44c5a6SAntoine Ténart 	}
4221b44c5a6SAntoine Ténart 
4231b44c5a6SAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].egress_lock);
4241b44c5a6SAntoine Ténart 
4258ac1283eSAntoine Tenart 	request->req = base;
42697858434SAntoine Ténart 
4271b44c5a6SAntoine Ténart 	*commands = n_cdesc;
428152bdf4cSOfer Heifetz 	*results = n_rdesc;
4291b44c5a6SAntoine Ténart 	return 0;
4301b44c5a6SAntoine Ténart 
4311b44c5a6SAntoine Ténart rdesc_rollback:
4321b44c5a6SAntoine Ténart 	for (i = 0; i < n_rdesc; i++)
4331b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].rdr);
4341b44c5a6SAntoine Ténart cdesc_rollback:
4351b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
4361b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
4371b44c5a6SAntoine Ténart 
4381b44c5a6SAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].egress_lock);
4391b44c5a6SAntoine Ténart 
4408ac1283eSAntoine Tenart 	if (src == dst) {
4418ac1283eSAntoine Tenart 		dma_unmap_sg(priv->dev, src,
442f6beaea3SAntoine Tenart 			     sg_nents_for_len(src, totlen),
4431b44c5a6SAntoine Ténart 			     DMA_BIDIRECTIONAL);
4441b44c5a6SAntoine Ténart 	} else {
4458ac1283eSAntoine Tenart 		dma_unmap_sg(priv->dev, src,
446f6beaea3SAntoine Tenart 			     sg_nents_for_len(src, totlen),
4471b44c5a6SAntoine Ténart 			     DMA_TO_DEVICE);
4488ac1283eSAntoine Tenart 		dma_unmap_sg(priv->dev, dst,
449f6beaea3SAntoine Tenart 			     sg_nents_for_len(dst, totlen),
4501b44c5a6SAntoine Ténart 			     DMA_FROM_DEVICE);
4511b44c5a6SAntoine Ténart 	}
4521b44c5a6SAntoine Ténart 
4531b44c5a6SAntoine Ténart 	return ret;
4541b44c5a6SAntoine Ténart }
4551b44c5a6SAntoine Ténart 
4561b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
4571b44c5a6SAntoine Ténart 				      int ring,
4588ac1283eSAntoine Tenart 				      struct crypto_async_request *base,
4591b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
4601b44c5a6SAntoine Ténart {
4618ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
4621b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
4631b44c5a6SAntoine Ténart 	int ndesc = 0, enq_ret;
4641b44c5a6SAntoine Ténart 
4651b44c5a6SAntoine Ténart 	*ret = 0;
4661b44c5a6SAntoine Ténart 
4671b44c5a6SAntoine Ténart 	spin_lock_bh(&priv->ring[ring].egress_lock);
4681b44c5a6SAntoine Ténart 	do {
4691b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
4701b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
4711b44c5a6SAntoine Ténart 			dev_err(priv->dev,
4721b44c5a6SAntoine Ténart 				"cipher: invalidate: could not retrieve the result descriptor\n");
4731b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
4741b44c5a6SAntoine Ténart 			break;
4751b44c5a6SAntoine Ténart 		}
4761b44c5a6SAntoine Ténart 
4771b44c5a6SAntoine Ténart 		if (rdesc->result_data.error_code) {
4781b44c5a6SAntoine Ténart 			dev_err(priv->dev, "cipher: invalidate: result descriptor error (%d)\n",
4791b44c5a6SAntoine Ténart 				rdesc->result_data.error_code);
4801b44c5a6SAntoine Ténart 			*ret = -EIO;
4811b44c5a6SAntoine Ténart 		}
4821b44c5a6SAntoine Ténart 
4831b44c5a6SAntoine Ténart 		ndesc++;
4841b44c5a6SAntoine Ténart 	} while (!rdesc->last_seg);
4851b44c5a6SAntoine Ténart 
4861b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
4871b44c5a6SAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].egress_lock);
4881b44c5a6SAntoine Ténart 
4891b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
4901b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
4911b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
4921b44c5a6SAntoine Ténart 
4931b44c5a6SAntoine Ténart 		*should_complete = true;
4941b44c5a6SAntoine Ténart 
4951b44c5a6SAntoine Ténart 		return ndesc;
4961b44c5a6SAntoine Ténart 	}
4971b44c5a6SAntoine Ténart 
49886671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
49986671abbSAntoine Ténart 	ctx->base.ring = ring;
5001b44c5a6SAntoine Ténart 
50186671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
5028ac1283eSAntoine Tenart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
50386671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
5041b44c5a6SAntoine Ténart 
5051b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
5061b44c5a6SAntoine Ténart 		*ret = enq_ret;
5071b44c5a6SAntoine Ténart 
5088472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
5098472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
51086671abbSAntoine Ténart 
5111b44c5a6SAntoine Ténart 	*should_complete = false;
5121b44c5a6SAntoine Ténart 
5131b44c5a6SAntoine Ténart 	return ndesc;
5141b44c5a6SAntoine Ténart }
5151b44c5a6SAntoine Ténart 
5168ac1283eSAntoine Tenart static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv,
5178ac1283eSAntoine Tenart 					   int ring,
5181eb7b403SOfer Heifetz 					   struct crypto_async_request *async,
5191eb7b403SOfer Heifetz 					   bool *should_complete, int *ret)
5201eb7b403SOfer Heifetz {
5211eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
5221eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
5231eb7b403SOfer Heifetz 	int err;
5241eb7b403SOfer Heifetz 
5251eb7b403SOfer Heifetz 	if (sreq->needs_inv) {
5261eb7b403SOfer Heifetz 		sreq->needs_inv = false;
5271eb7b403SOfer Heifetz 		err = safexcel_handle_inv_result(priv, ring, async,
5281eb7b403SOfer Heifetz 						 should_complete, ret);
5291eb7b403SOfer Heifetz 	} else {
5308ac1283eSAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
5318ac1283eSAntoine Tenart 						 req->dst, req->cryptlen, sreq,
5321eb7b403SOfer Heifetz 						 should_complete, ret);
5331eb7b403SOfer Heifetz 	}
5341eb7b403SOfer Heifetz 
5351eb7b403SOfer Heifetz 	return err;
5361eb7b403SOfer Heifetz }
5371eb7b403SOfer Heifetz 
538f6beaea3SAntoine Tenart static int safexcel_aead_handle_result(struct safexcel_crypto_priv *priv,
539f6beaea3SAntoine Tenart 				       int ring,
540f6beaea3SAntoine Tenart 				       struct crypto_async_request *async,
541f6beaea3SAntoine Tenart 				       bool *should_complete, int *ret)
542f6beaea3SAntoine Tenart {
543f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
544f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
545f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
546f6beaea3SAntoine Tenart 	int err;
547f6beaea3SAntoine Tenart 
548f6beaea3SAntoine Tenart 	if (sreq->needs_inv) {
549f6beaea3SAntoine Tenart 		sreq->needs_inv = false;
550f6beaea3SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async,
551f6beaea3SAntoine Tenart 						 should_complete, ret);
552f6beaea3SAntoine Tenart 	} else {
553f6beaea3SAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
554f6beaea3SAntoine Tenart 						 req->dst,
555f6beaea3SAntoine Tenart 						 req->cryptlen + crypto_aead_authsize(tfm),
556f6beaea3SAntoine Tenart 						 sreq, should_complete, ret);
557f6beaea3SAntoine Tenart 	}
558f6beaea3SAntoine Tenart 
559f6beaea3SAntoine Tenart 	return err;
560f6beaea3SAntoine Tenart }
561f6beaea3SAntoine Tenart 
5628ac1283eSAntoine Tenart static int safexcel_cipher_send_inv(struct crypto_async_request *base,
5631b44c5a6SAntoine Ténart 				    int ring, struct safexcel_request *request,
5641b44c5a6SAntoine Ténart 				    int *commands, int *results)
5651b44c5a6SAntoine Ténart {
5668ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
5671b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
5681b44c5a6SAntoine Ténart 	int ret;
5691b44c5a6SAntoine Ténart 
5708ac1283eSAntoine Tenart 	ret = safexcel_invalidate_cache(base, priv, ctx->base.ctxr_dma, ring,
5718ac1283eSAntoine Tenart 					request);
5721b44c5a6SAntoine Ténart 	if (unlikely(ret))
5731b44c5a6SAntoine Ténart 		return ret;
5741b44c5a6SAntoine Ténart 
5751b44c5a6SAntoine Ténart 	*commands = 1;
5761b44c5a6SAntoine Ténart 	*results = 1;
5771b44c5a6SAntoine Ténart 
5781b44c5a6SAntoine Ténart 	return 0;
5791b44c5a6SAntoine Ténart }
5801b44c5a6SAntoine Ténart 
5818ac1283eSAntoine Tenart static int safexcel_skcipher_send(struct crypto_async_request *async, int ring,
5828ac1283eSAntoine Tenart 				  struct safexcel_request *request,
5831eb7b403SOfer Heifetz 				  int *commands, int *results)
5841eb7b403SOfer Heifetz {
5851eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
586871df319SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
5871eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
588871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
5891eb7b403SOfer Heifetz 	int ret;
5901eb7b403SOfer Heifetz 
591871df319SAntoine Ténart 	BUG_ON(priv->version == EIP97 && sreq->needs_inv);
592871df319SAntoine Ténart 
5931eb7b403SOfer Heifetz 	if (sreq->needs_inv)
5948ac1283eSAntoine Tenart 		ret = safexcel_cipher_send_inv(async, ring, request, commands,
5958ac1283eSAntoine Tenart 					       results);
5961eb7b403SOfer Heifetz 	else
5978ac1283eSAntoine Tenart 		ret = safexcel_aes_send(async, ring, request, sreq, req->src,
598f6beaea3SAntoine Tenart 					req->dst, req->cryptlen, 0, 0, req->iv,
599f6beaea3SAntoine Tenart 					commands, results);
600f6beaea3SAntoine Tenart 	return ret;
601f6beaea3SAntoine Tenart }
602f6beaea3SAntoine Tenart 
603f6beaea3SAntoine Tenart static int safexcel_aead_send(struct crypto_async_request *async, int ring,
604f6beaea3SAntoine Tenart 			      struct safexcel_request *request, int *commands,
605f6beaea3SAntoine Tenart 			      int *results)
606f6beaea3SAntoine Tenart {
607f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
608f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
609f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
610f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
611f6beaea3SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
612f6beaea3SAntoine Tenart 	int ret;
613f6beaea3SAntoine Tenart 
614f6beaea3SAntoine Tenart 	BUG_ON(priv->version == EIP97 && sreq->needs_inv);
615f6beaea3SAntoine Tenart 
616f6beaea3SAntoine Tenart 	if (sreq->needs_inv)
617f6beaea3SAntoine Tenart 		ret = safexcel_cipher_send_inv(async, ring, request, commands,
618f6beaea3SAntoine Tenart 					       results);
619f6beaea3SAntoine Tenart 	else
620f6beaea3SAntoine Tenart 		ret = safexcel_aes_send(async, ring, request, sreq, req->src,
621f6beaea3SAntoine Tenart 					req->dst, req->cryptlen, req->assoclen,
622f6beaea3SAntoine Tenart 					crypto_aead_authsize(tfm), req->iv,
6231eb7b403SOfer Heifetz 					commands, results);
6241eb7b403SOfer Heifetz 	return ret;
6251eb7b403SOfer Heifetz }
6261eb7b403SOfer Heifetz 
6278ac1283eSAntoine Tenart static int safexcel_cipher_exit_inv(struct crypto_tfm *tfm,
6288ac1283eSAntoine Tenart 				    struct crypto_async_request *base,
6298ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
6308ac1283eSAntoine Tenart 				    struct safexcel_inv_result *result)
6311b44c5a6SAntoine Ténart {
6321b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
6331b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
63486671abbSAntoine Ténart 	int ring = ctx->base.ring;
6351b44c5a6SAntoine Ténart 
6368ac1283eSAntoine Tenart 	init_completion(&result->completion);
6371b44c5a6SAntoine Ténart 
6388ac1283eSAntoine Tenart 	ctx = crypto_tfm_ctx(base->tfm);
6391b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
6401eb7b403SOfer Heifetz 	sreq->needs_inv = true;
6411b44c5a6SAntoine Ténart 
64286671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
6438ac1283eSAntoine Tenart 	crypto_enqueue_request(&priv->ring[ring].queue, base);
64486671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
6451b44c5a6SAntoine Ténart 
6468472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
6478472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
6481b44c5a6SAntoine Ténart 
6498ac1283eSAntoine Tenart 	wait_for_completion(&result->completion);
6501b44c5a6SAntoine Ténart 
6518ac1283eSAntoine Tenart 	if (result->error) {
6521b44c5a6SAntoine Ténart 		dev_warn(priv->dev,
6531b44c5a6SAntoine Ténart 			"cipher: sync: invalidate: completion error %d\n",
6548ac1283eSAntoine Tenart 			 result->error);
6558ac1283eSAntoine Tenart 		return result->error;
6561b44c5a6SAntoine Ténart 	}
6571b44c5a6SAntoine Ténart 
6581b44c5a6SAntoine Ténart 	return 0;
6591b44c5a6SAntoine Ténart }
6601b44c5a6SAntoine Ténart 
6618ac1283eSAntoine Tenart static int safexcel_skcipher_exit_inv(struct crypto_tfm *tfm)
6628ac1283eSAntoine Tenart {
6638ac1283eSAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, skcipher, EIP197_SKCIPHER_REQ_SIZE);
6648ac1283eSAntoine Tenart 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
6658ac1283eSAntoine Tenart 	struct safexcel_inv_result result = {};
6668ac1283eSAntoine Tenart 
6678ac1283eSAntoine Tenart 	memset(req, 0, sizeof(struct skcipher_request));
6688ac1283eSAntoine Tenart 
6698ac1283eSAntoine Tenart 	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
6708ac1283eSAntoine Tenart 				      safexcel_inv_complete, &result);
6718ac1283eSAntoine Tenart 	skcipher_request_set_tfm(req, __crypto_skcipher_cast(tfm));
6728ac1283eSAntoine Tenart 
6738ac1283eSAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
6748ac1283eSAntoine Tenart }
6758ac1283eSAntoine Tenart 
676f6beaea3SAntoine Tenart static int safexcel_aead_exit_inv(struct crypto_tfm *tfm)
677f6beaea3SAntoine Tenart {
678f6beaea3SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, aead, EIP197_AEAD_REQ_SIZE);
679f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
680f6beaea3SAntoine Tenart 	struct safexcel_inv_result result = {};
681f6beaea3SAntoine Tenart 
682f6beaea3SAntoine Tenart 	memset(req, 0, sizeof(struct aead_request));
683f6beaea3SAntoine Tenart 
684f6beaea3SAntoine Tenart 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
685f6beaea3SAntoine Tenart 				  safexcel_inv_complete, &result);
686f6beaea3SAntoine Tenart 	aead_request_set_tfm(req, __crypto_aead_cast(tfm));
687f6beaea3SAntoine Tenart 
688f6beaea3SAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
689f6beaea3SAntoine Tenart }
690f6beaea3SAntoine Tenart 
6918ac1283eSAntoine Tenart static int safexcel_aes(struct crypto_async_request *base,
6928ac1283eSAntoine Tenart 			struct safexcel_cipher_req *sreq,
6931b44c5a6SAntoine Ténart 			enum safexcel_cipher_direction dir, u32 mode)
6941b44c5a6SAntoine Ténart {
6958ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
6961b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
69786671abbSAntoine Ténart 	int ret, ring;
6981b44c5a6SAntoine Ténart 
6991eb7b403SOfer Heifetz 	sreq->needs_inv = false;
700847ccfc5SOfer Heifetz 	sreq->direction = dir;
7011b44c5a6SAntoine Ténart 	ctx->mode = mode;
7021b44c5a6SAntoine Ténart 
7031b44c5a6SAntoine Ténart 	if (ctx->base.ctxr) {
704871df319SAntoine Ténart 		if (priv->version == EIP197 && ctx->base.needs_inv) {
7051eb7b403SOfer Heifetz 			sreq->needs_inv = true;
7061eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
7071eb7b403SOfer Heifetz 		}
7081b44c5a6SAntoine Ténart 	} else {
7091b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
7101b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
7118ac1283eSAntoine Tenart 						 EIP197_GFP_FLAGS(*base),
7121b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
7131b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
7141b44c5a6SAntoine Ténart 			return -ENOMEM;
7151b44c5a6SAntoine Ténart 	}
7161b44c5a6SAntoine Ténart 
71786671abbSAntoine Ténart 	ring = ctx->base.ring;
7181b44c5a6SAntoine Ténart 
71986671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
7208ac1283eSAntoine Tenart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
72186671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
72286671abbSAntoine Ténart 
7238472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
7248472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
7251b44c5a6SAntoine Ténart 
7261b44c5a6SAntoine Ténart 	return ret;
7271b44c5a6SAntoine Ténart }
7281b44c5a6SAntoine Ténart 
7291b44c5a6SAntoine Ténart static int safexcel_ecb_aes_encrypt(struct skcipher_request *req)
7301b44c5a6SAntoine Ténart {
7318ac1283eSAntoine Tenart 	return safexcel_aes(&req->base, skcipher_request_ctx(req),
7328ac1283eSAntoine Tenart 			    SAFEXCEL_ENCRYPT, CONTEXT_CONTROL_CRYPTO_MODE_ECB);
7331b44c5a6SAntoine Ténart }
7341b44c5a6SAntoine Ténart 
7351b44c5a6SAntoine Ténart static int safexcel_ecb_aes_decrypt(struct skcipher_request *req)
7361b44c5a6SAntoine Ténart {
7378ac1283eSAntoine Tenart 	return safexcel_aes(&req->base, skcipher_request_ctx(req),
7388ac1283eSAntoine Tenart 			    SAFEXCEL_DECRYPT, CONTEXT_CONTROL_CRYPTO_MODE_ECB);
7391b44c5a6SAntoine Ténart }
7401b44c5a6SAntoine Ténart 
7411b44c5a6SAntoine Ténart static int safexcel_skcipher_cra_init(struct crypto_tfm *tfm)
7421b44c5a6SAntoine Ténart {
7431b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
7441b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
7451b44c5a6SAntoine Ténart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
7461b44c5a6SAntoine Ténart 			     alg.skcipher.base);
7471b44c5a6SAntoine Ténart 
7481eb7b403SOfer Heifetz 	crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm),
7491eb7b403SOfer Heifetz 				    sizeof(struct safexcel_cipher_req));
7501b44c5a6SAntoine Ténart 
7518ac1283eSAntoine Tenart 	ctx->priv = tmpl->priv;
7528ac1283eSAntoine Tenart 
7538ac1283eSAntoine Tenart 	ctx->base.send = safexcel_skcipher_send;
7548ac1283eSAntoine Tenart 	ctx->base.handle_result = safexcel_skcipher_handle_result;
7558ac1283eSAntoine Tenart 	return 0;
7568ac1283eSAntoine Tenart }
7578ac1283eSAntoine Tenart 
7588ac1283eSAntoine Tenart static int safexcel_cipher_cra_exit(struct crypto_tfm *tfm)
7598ac1283eSAntoine Tenart {
7608ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
7618ac1283eSAntoine Tenart 
762ce679559SAntoine Tenart 	memzero_explicit(ctx->key, sizeof(ctx->key));
7638ac1283eSAntoine Tenart 
7648ac1283eSAntoine Tenart 	/* context not allocated, skip invalidation */
7658ac1283eSAntoine Tenart 	if (!ctx->base.ctxr)
7668ac1283eSAntoine Tenart 		return -ENOMEM;
7678ac1283eSAntoine Tenart 
768ce679559SAntoine Tenart 	memzero_explicit(ctx->base.ctxr->data, sizeof(ctx->base.ctxr->data));
7691b44c5a6SAntoine Ténart 	return 0;
7701b44c5a6SAntoine Ténart }
7711b44c5a6SAntoine Ténart 
7721b44c5a6SAntoine Ténart static void safexcel_skcipher_cra_exit(struct crypto_tfm *tfm)
7731b44c5a6SAntoine Ténart {
7741b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
7751b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
7761b44c5a6SAntoine Ténart 	int ret;
7771b44c5a6SAntoine Ténart 
7788ac1283eSAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
7791b44c5a6SAntoine Ténart 		return;
7801b44c5a6SAntoine Ténart 
781871df319SAntoine Ténart 	if (priv->version == EIP197) {
7828ac1283eSAntoine Tenart 		ret = safexcel_skcipher_exit_inv(tfm);
7831b44c5a6SAntoine Ténart 		if (ret)
7848ac1283eSAntoine Tenart 			dev_warn(priv->dev, "skcipher: invalidation error %d\n",
7858ac1283eSAntoine Tenart 				 ret);
786871df319SAntoine Ténart 	} else {
787871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
788871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
789871df319SAntoine Ténart 	}
7901b44c5a6SAntoine Ténart }
7911b44c5a6SAntoine Ténart 
792f6beaea3SAntoine Tenart static void safexcel_aead_cra_exit(struct crypto_tfm *tfm)
793f6beaea3SAntoine Tenart {
794f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
795f6beaea3SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
796f6beaea3SAntoine Tenart 	int ret;
797f6beaea3SAntoine Tenart 
798f6beaea3SAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
799f6beaea3SAntoine Tenart 		return;
800f6beaea3SAntoine Tenart 
801f6beaea3SAntoine Tenart 	if (priv->version == EIP197) {
802f6beaea3SAntoine Tenart 		ret = safexcel_aead_exit_inv(tfm);
803f6beaea3SAntoine Tenart 		if (ret)
804f6beaea3SAntoine Tenart 			dev_warn(priv->dev, "aead: invalidation error %d\n",
805f6beaea3SAntoine Tenart 				 ret);
806f6beaea3SAntoine Tenart 	} else {
807f6beaea3SAntoine Tenart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
808f6beaea3SAntoine Tenart 			      ctx->base.ctxr_dma);
809f6beaea3SAntoine Tenart 	}
810f6beaea3SAntoine Tenart }
811f6beaea3SAntoine Tenart 
8121b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_ecb_aes = {
8131b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
8141b44c5a6SAntoine Ténart 	.alg.skcipher = {
8158ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
8161b44c5a6SAntoine Ténart 		.encrypt = safexcel_ecb_aes_encrypt,
8171b44c5a6SAntoine Ténart 		.decrypt = safexcel_ecb_aes_decrypt,
8181b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
8191b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
8201b44c5a6SAntoine Ténart 		.base = {
8211b44c5a6SAntoine Ténart 			.cra_name = "ecb(aes)",
8221b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-ecb-aes",
8231b44c5a6SAntoine Ténart 			.cra_priority = 300,
8241b44c5a6SAntoine Ténart 			.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC |
8251b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
8261b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
8271b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
8281b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
8291b44c5a6SAntoine Ténart 			.cra_init = safexcel_skcipher_cra_init,
8301b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
8311b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
8321b44c5a6SAntoine Ténart 		},
8331b44c5a6SAntoine Ténart 	},
8341b44c5a6SAntoine Ténart };
8351b44c5a6SAntoine Ténart 
8361b44c5a6SAntoine Ténart static int safexcel_cbc_aes_encrypt(struct skcipher_request *req)
8371b44c5a6SAntoine Ténart {
8388ac1283eSAntoine Tenart 	return safexcel_aes(&req->base, skcipher_request_ctx(req),
8398ac1283eSAntoine Tenart 			    SAFEXCEL_ENCRYPT, CONTEXT_CONTROL_CRYPTO_MODE_CBC);
8401b44c5a6SAntoine Ténart }
8411b44c5a6SAntoine Ténart 
8421b44c5a6SAntoine Ténart static int safexcel_cbc_aes_decrypt(struct skcipher_request *req)
8431b44c5a6SAntoine Ténart {
8448ac1283eSAntoine Tenart 	return safexcel_aes(&req->base, skcipher_request_ctx(req),
8458ac1283eSAntoine Tenart 			    SAFEXCEL_DECRYPT, CONTEXT_CONTROL_CRYPTO_MODE_CBC);
8461b44c5a6SAntoine Ténart }
8471b44c5a6SAntoine Ténart 
8481b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_cbc_aes = {
8491b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
8501b44c5a6SAntoine Ténart 	.alg.skcipher = {
8518ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
8521b44c5a6SAntoine Ténart 		.encrypt = safexcel_cbc_aes_encrypt,
8531b44c5a6SAntoine Ténart 		.decrypt = safexcel_cbc_aes_decrypt,
8541b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
8551b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
8561b44c5a6SAntoine Ténart 		.ivsize = AES_BLOCK_SIZE,
8571b44c5a6SAntoine Ténart 		.base = {
8581b44c5a6SAntoine Ténart 			.cra_name = "cbc(aes)",
8591b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-cbc-aes",
8601b44c5a6SAntoine Ténart 			.cra_priority = 300,
8611b44c5a6SAntoine Ténart 			.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC |
8621b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
8631b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
8641b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
8651b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
8661b44c5a6SAntoine Ténart 			.cra_init = safexcel_skcipher_cra_init,
8671b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
8681b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
8691b44c5a6SAntoine Ténart 		},
8701b44c5a6SAntoine Ténart 	},
8711b44c5a6SAntoine Ténart };
872f6beaea3SAntoine Tenart 
873f6beaea3SAntoine Tenart static int safexcel_aead_encrypt(struct aead_request *req)
874f6beaea3SAntoine Tenart {
875f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
876f6beaea3SAntoine Tenart 
877f6beaea3SAntoine Tenart 	return safexcel_aes(&req->base, creq, SAFEXCEL_ENCRYPT,
878f6beaea3SAntoine Tenart 			    CONTEXT_CONTROL_CRYPTO_MODE_CBC);
879f6beaea3SAntoine Tenart }
880f6beaea3SAntoine Tenart 
881f6beaea3SAntoine Tenart static int safexcel_aead_decrypt(struct aead_request *req)
882f6beaea3SAntoine Tenart {
883f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
884f6beaea3SAntoine Tenart 
885f6beaea3SAntoine Tenart 	return safexcel_aes(&req->base, creq, SAFEXCEL_DECRYPT,
886f6beaea3SAntoine Tenart 			    CONTEXT_CONTROL_CRYPTO_MODE_CBC);
887f6beaea3SAntoine Tenart }
888f6beaea3SAntoine Tenart 
889f6beaea3SAntoine Tenart static int safexcel_aead_cra_init(struct crypto_tfm *tfm)
890f6beaea3SAntoine Tenart {
891f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
892f6beaea3SAntoine Tenart 	struct safexcel_alg_template *tmpl =
893f6beaea3SAntoine Tenart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
894f6beaea3SAntoine Tenart 			     alg.aead.base);
895f6beaea3SAntoine Tenart 
896f6beaea3SAntoine Tenart 	crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
897f6beaea3SAntoine Tenart 				sizeof(struct safexcel_cipher_req));
898f6beaea3SAntoine Tenart 
899f6beaea3SAntoine Tenart 	ctx->priv = tmpl->priv;
900f6beaea3SAntoine Tenart 
901f6beaea3SAntoine Tenart 	ctx->aead = true;
902f6beaea3SAntoine Tenart 	ctx->base.send = safexcel_aead_send;
903f6beaea3SAntoine Tenart 	ctx->base.handle_result = safexcel_aead_handle_result;
904f6beaea3SAntoine Tenart 	return 0;
905f6beaea3SAntoine Tenart }
906f6beaea3SAntoine Tenart 
907f6beaea3SAntoine Tenart static int safexcel_aead_sha256_cra_init(struct crypto_tfm *tfm)
908f6beaea3SAntoine Tenart {
909f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
910f6beaea3SAntoine Tenart 
911f6beaea3SAntoine Tenart 	safexcel_aead_cra_init(tfm);
912f6beaea3SAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
913f6beaea3SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
914f6beaea3SAntoine Tenart 	return 0;
915f6beaea3SAntoine Tenart }
916f6beaea3SAntoine Tenart 
917f6beaea3SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_aes = {
918f6beaea3SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
919f6beaea3SAntoine Tenart 	.alg.aead = {
920f6beaea3SAntoine Tenart 		.setkey = safexcel_aead_aes_setkey,
921f6beaea3SAntoine Tenart 		.encrypt = safexcel_aead_encrypt,
922f6beaea3SAntoine Tenart 		.decrypt = safexcel_aead_decrypt,
923f6beaea3SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
924f6beaea3SAntoine Tenart 		.maxauthsize = SHA256_DIGEST_SIZE,
925f6beaea3SAntoine Tenart 		.base = {
926f6beaea3SAntoine Tenart 			.cra_name = "authenc(hmac(sha256),cbc(aes))",
927f6beaea3SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-aes",
928f6beaea3SAntoine Tenart 			.cra_priority = 300,
929f6beaea3SAntoine Tenart 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC |
930f6beaea3SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
931f6beaea3SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
932f6beaea3SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
933f6beaea3SAntoine Tenart 			.cra_alignmask = 0,
934f6beaea3SAntoine Tenart 			.cra_init = safexcel_aead_sha256_cra_init,
935f6beaea3SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
936f6beaea3SAntoine Tenart 			.cra_module = THIS_MODULE,
937f6beaea3SAntoine Tenart 		},
938f6beaea3SAntoine Tenart 	},
939f6beaea3SAntoine Tenart };
940