1301422e3SAntoine Tenart // SPDX-License-Identifier: GPL-2.0
21b44c5a6SAntoine Ténart /*
31b44c5a6SAntoine Ténart  * Copyright (C) 2017 Marvell
41b44c5a6SAntoine Ténart  *
51b44c5a6SAntoine Ténart  * Antoine Tenart <antoine.tenart@free-electrons.com>
61b44c5a6SAntoine Ténart  */
71b44c5a6SAntoine Ténart 
8b98687bbSPascal van Leeuwen #include <crypto/aes.h>
9aed3731eSAntoine Ténart #include <crypto/hmac.h>
10293f89cfSOfer Heifetz #include <crypto/md5.h>
111b44c5a6SAntoine Ténart #include <crypto/sha.h>
12aaf5a383SPascal van Leeuwen #include <crypto/sha3.h>
1338f21b4bSPascal van Leeuwen #include <crypto/skcipher.h>
140f2bc131SPascal van Leeuwen #include <crypto/sm3.h>
151b44c5a6SAntoine Ténart #include <linux/device.h>
161b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
171b44c5a6SAntoine Ténart #include <linux/dmapool.h>
181b44c5a6SAntoine Ténart 
191b44c5a6SAntoine Ténart #include "safexcel.h"
201b44c5a6SAntoine Ténart 
211b44c5a6SAntoine Ténart struct safexcel_ahash_ctx {
221b44c5a6SAntoine Ténart 	struct safexcel_context base;
231b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
241b44c5a6SAntoine Ténart 
251b44c5a6SAntoine Ténart 	u32 alg;
26b98687bbSPascal van Leeuwen 	u8  key_sz;
2738f21b4bSPascal van Leeuwen 	bool cbcmac;
28aaf5a383SPascal van Leeuwen 	bool do_fallback;
29aaf5a383SPascal van Leeuwen 	bool fb_init_done;
306c1c09b3SPascal van Leeuwen 	bool fb_do_setkey;
311b44c5a6SAntoine Ténart 
3213a1bb93SPascal van Leeuwen 	__le32 ipad[SHA3_512_BLOCK_SIZE / sizeof(__le32)];
3313a1bb93SPascal van Leeuwen 	__le32 opad[SHA3_512_BLOCK_SIZE / sizeof(__le32)];
3438f21b4bSPascal van Leeuwen 
3538f21b4bSPascal van Leeuwen 	struct crypto_cipher *kaes;
36aaf5a383SPascal van Leeuwen 	struct crypto_ahash *fback;
376c1c09b3SPascal van Leeuwen 	struct crypto_shash *shpre;
386c1c09b3SPascal van Leeuwen 	struct shash_desc *shdesc;
391b44c5a6SAntoine Ténart };
401b44c5a6SAntoine Ténart 
411b44c5a6SAntoine Ténart struct safexcel_ahash_req {
421b44c5a6SAntoine Ténart 	bool last_req;
431b44c5a6SAntoine Ténart 	bool finish;
441b44c5a6SAntoine Ténart 	bool hmac;
451eb7b403SOfer Heifetz 	bool needs_inv;
4685b36ee8SPascal van Leeuwen 	bool hmac_zlen;
4785b36ee8SPascal van Leeuwen 	bool len_is_le;
48b98687bbSPascal van Leeuwen 	bool not_first;
49b98687bbSPascal van Leeuwen 	bool xcbcmac;
501b44c5a6SAntoine Ténart 
51c957f8b3SAntoine Ténart 	int nents;
52b8592027SOfer Heifetz 	dma_addr_t result_dma;
53c957f8b3SAntoine Ténart 
54b869648cSAntoine Tenart 	u32 digest;
55b869648cSAntoine Tenart 
5641abed7dSPascal van Leeuwen 	u8 state_sz;    /* expected state size, only set once */
5741abed7dSPascal van Leeuwen 	u8 block_sz;    /* block size, only set once */
586c1c09b3SPascal van Leeuwen 	u8 digest_sz;   /* output digest size, only set once */
5913a1bb93SPascal van Leeuwen 	__le32 state[SHA3_512_BLOCK_SIZE /
6013a1bb93SPascal van Leeuwen 		     sizeof(__le32)] __aligned(sizeof(__le32));
611b44c5a6SAntoine Ténart 
6231fb084cSPascal van Leeuwen 	u64 len;
6331fb084cSPascal van Leeuwen 	u64 processed;
641b44c5a6SAntoine Ténart 
6541abed7dSPascal van Leeuwen 	u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32));
66cff9a175SAntoine Tenart 	dma_addr_t cache_dma;
67cff9a175SAntoine Tenart 	unsigned int cache_sz;
68cff9a175SAntoine Tenart 
6941abed7dSPascal van Leeuwen 	u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32));
701b44c5a6SAntoine Ténart };
711b44c5a6SAntoine Ténart 
72b460edb6SAntoine Tenart static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req)
73b460edb6SAntoine Tenart {
7431fb084cSPascal van Leeuwen 	return req->len - req->processed;
75b460edb6SAntoine Tenart }
76b460edb6SAntoine Tenart 
771b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc,
78b98687bbSPascal van Leeuwen 				u32 input_length, u32 result_length,
7938f21b4bSPascal van Leeuwen 				bool cbcmac)
801b44c5a6SAntoine Ténart {
811b44c5a6SAntoine Ténart 	struct safexcel_token *token =
821b44c5a6SAntoine Ténart 		(struct safexcel_token *)cdesc->control_data.token;
831b44c5a6SAntoine Ténart 
841b44c5a6SAntoine Ténart 	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
851b44c5a6SAntoine Ténart 	token[0].packet_length = input_length;
861b44c5a6SAntoine Ténart 	token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH;
871b44c5a6SAntoine Ténart 
88b98687bbSPascal van Leeuwen 	input_length &= 15;
8938f21b4bSPascal van Leeuwen 	if (unlikely(cbcmac && input_length)) {
90098e51e5SPascal van Leeuwen 		token[0].stat =  0;
911b44c5a6SAntoine Ténart 		token[1].opcode = EIP197_TOKEN_OPCODE_INSERT;
92b98687bbSPascal van Leeuwen 		token[1].packet_length = 16 - input_length;
93b98687bbSPascal van Leeuwen 		token[1].stat = EIP197_TOKEN_STAT_LAST_HASH;
94b98687bbSPascal van Leeuwen 		token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH;
95b98687bbSPascal van Leeuwen 	} else {
96b98687bbSPascal van Leeuwen 		token[0].stat = EIP197_TOKEN_STAT_LAST_HASH;
97098e51e5SPascal van Leeuwen 		eip197_noop_token(&token[1]);
98b98687bbSPascal van Leeuwen 	}
99b98687bbSPascal van Leeuwen 
100b98687bbSPascal van Leeuwen 	token[2].opcode = EIP197_TOKEN_OPCODE_INSERT;
101b98687bbSPascal van Leeuwen 	token[2].stat = EIP197_TOKEN_STAT_LAST_HASH |
1021b44c5a6SAntoine Ténart 			EIP197_TOKEN_STAT_LAST_PACKET;
103b98687bbSPascal van Leeuwen 	token[2].packet_length = result_length;
104b98687bbSPascal van Leeuwen 	token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
1051b44c5a6SAntoine Ténart 				EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
106098e51e5SPascal van Leeuwen 
107098e51e5SPascal van Leeuwen 	eip197_noop_token(&token[3]);
1081b44c5a6SAntoine Ténart }
1091b44c5a6SAntoine Ténart 
1101b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx,
1111b44c5a6SAntoine Ténart 				     struct safexcel_ahash_req *req,
11241abed7dSPascal van Leeuwen 				     struct safexcel_command_desc *cdesc)
1131b44c5a6SAntoine Ténart {
114b460edb6SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
11541abed7dSPascal van Leeuwen 	u64 count = 0;
1161b44c5a6SAntoine Ténart 
117a7cf8658SPascal van Leeuwen 	cdesc->control_data.control0 = ctx->alg;
118098e51e5SPascal van Leeuwen 	cdesc->control_data.control1 = 0;
119dc5268b6SPascal van Leeuwen 
1201b44c5a6SAntoine Ténart 	/*
1211b44c5a6SAntoine Ténart 	 * Copy the input digest if needed, and setup the context
1221b44c5a6SAntoine Ténart 	 * fields. Do this now as we need it to setup the first command
1231b44c5a6SAntoine Ténart 	 * descriptor.
1241b44c5a6SAntoine Ténart 	 */
125a7cf8658SPascal van Leeuwen 	if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) {
126b98687bbSPascal van Leeuwen 		if (req->xcbcmac)
127b98687bbSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data, ctx->ipad, ctx->key_sz);
128b98687bbSPascal van Leeuwen 		else
129b98687bbSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
130a7cf8658SPascal van Leeuwen 
131b98687bbSPascal van Leeuwen 		if (!req->finish && req->xcbcmac)
132b98687bbSPascal van Leeuwen 			cdesc->control_data.control0 |=
133b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
134a7cf8658SPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
135b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_NO_FINISH_HASH |
136b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz /
137b98687bbSPascal van Leeuwen 						     sizeof(u32));
138b98687bbSPascal van Leeuwen 		else
139b98687bbSPascal van Leeuwen 			cdesc->control_data.control0 |=
140b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
141b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
142b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz /
143b98687bbSPascal van Leeuwen 						     sizeof(u32));
144a7cf8658SPascal van Leeuwen 		return;
145a7cf8658SPascal van Leeuwen 	} else if (!req->processed) {
14641abed7dSPascal van Leeuwen 		/* First - and possibly only - block of basic hash only */
147b98687bbSPascal van Leeuwen 		if (req->finish)
148a7cf8658SPascal van Leeuwen 			cdesc->control_data.control0 |= req->digest |
14941abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
15041abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH  |
15141abed7dSPascal van Leeuwen 				/* ensure its not 0! */
15241abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
153b98687bbSPascal van Leeuwen 		else
154a7cf8658SPascal van Leeuwen 			cdesc->control_data.control0 |= req->digest |
15541abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
15641abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH   |
15741abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_NO_FINISH_HASH |
15841abed7dSPascal van Leeuwen 				/* ensure its not 0! */
15941abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
16041abed7dSPascal van Leeuwen 		return;
16141abed7dSPascal van Leeuwen 	}
16241abed7dSPascal van Leeuwen 
16341abed7dSPascal van Leeuwen 	/* Hash continuation or HMAC, setup (inner) digest from state */
16441abed7dSPascal van Leeuwen 	memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
1651b44c5a6SAntoine Ténart 
166b460edb6SAntoine Tenart 	if (req->finish) {
16741abed7dSPascal van Leeuwen 		/* Compute digest count for hash/HMAC finish operations */
16841abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
16931fb084cSPascal van Leeuwen 		    req->hmac_zlen || (req->processed != req->block_sz)) {
17031fb084cSPascal van Leeuwen 			count = req->processed / EIP197_COUNTER_BLOCK_SIZE;
171b460edb6SAntoine Tenart 
17241abed7dSPascal van Leeuwen 			/* This is a hardware limitation, as the
173b460edb6SAntoine Tenart 			 * counter must fit into an u32. This represents
17441abed7dSPascal van Leeuwen 			 * a fairly big amount of input data, so we
175b460edb6SAntoine Tenart 			 * shouldn't see this.
176b460edb6SAntoine Tenart 			 */
17741abed7dSPascal van Leeuwen 			if (unlikely(count & 0xffffffff00000000ULL)) {
178b460edb6SAntoine Tenart 				dev_warn(priv->dev,
179b460edb6SAntoine Tenart 					 "Input data is too big\n");
180b460edb6SAntoine Tenart 				return;
181b460edb6SAntoine Tenart 			}
182b460edb6SAntoine Tenart 		}
1831b44c5a6SAntoine Ténart 
18441abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
18585b36ee8SPascal van Leeuwen 		    /* Special case: zero length HMAC */
18685b36ee8SPascal van Leeuwen 		    req->hmac_zlen ||
18741abed7dSPascal van Leeuwen 		    /* PE HW < 4.4 cannot do HMAC continue, fake using hash */
18831fb084cSPascal van Leeuwen 		    (req->processed != req->block_sz)) {
18941abed7dSPascal van Leeuwen 			/* Basic hash continue operation, need digest + cnt */
19041abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
19141abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) |
19241abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
19341abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
19485b36ee8SPascal van Leeuwen 			/* For zero-len HMAC, don't finalize, already padded! */
19585b36ee8SPascal van Leeuwen 			if (req->hmac_zlen)
19685b36ee8SPascal van Leeuwen 				cdesc->control_data.control0 |=
19785b36ee8SPascal van Leeuwen 					CONTEXT_CONTROL_NO_FINISH_HASH;
19841abed7dSPascal van Leeuwen 			cdesc->control_data.control1 |=
19941abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_CNT;
20041abed7dSPascal van Leeuwen 			ctx->base.ctxr->data[req->state_sz >> 2] =
20141abed7dSPascal van Leeuwen 				cpu_to_le32(count);
20241abed7dSPascal van Leeuwen 			req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
20385b36ee8SPascal van Leeuwen 
20485b36ee8SPascal van Leeuwen 			/* Clear zero-length HMAC flag for next operation! */
20585b36ee8SPascal van Leeuwen 			req->hmac_zlen = false;
20641abed7dSPascal van Leeuwen 		} else { /* HMAC */
20741abed7dSPascal van Leeuwen 			/* Need outer digest for HMAC finalization */
20841abed7dSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (req->state_sz >> 2),
2094505bb02SAntoine Tenart 			       ctx->opad, req->state_sz);
21041abed7dSPascal van Leeuwen 
21141abed7dSPascal van Leeuwen 			/* Single pass HMAC - no digest count */
21241abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
21341abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz >> 1) |
21441abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
21541abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_HMAC;
21641abed7dSPascal van Leeuwen 		}
21741abed7dSPascal van Leeuwen 	} else { /* Hash continuation, do not finish yet */
21841abed7dSPascal van Leeuwen 		cdesc->control_data.control0 |=
21941abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_SIZE(req->state_sz >> 2) |
22041abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_DIGEST_PRECOMPUTED |
22141abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_TYPE_HASH_OUT |
22241abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_NO_FINISH_HASH;
2231b44c5a6SAntoine Ténart 	}
2241b44c5a6SAntoine Ténart }
2251b44c5a6SAntoine Ténart 
22641abed7dSPascal van Leeuwen static int safexcel_ahash_enqueue(struct ahash_request *areq);
22741abed7dSPascal van Leeuwen 
22841abed7dSPascal van Leeuwen static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv,
22941abed7dSPascal van Leeuwen 				      int ring,
2301b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
2311b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
2321b44c5a6SAntoine Ténart {
2331b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
2341b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
2351b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2361b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *sreq = ahash_request_ctx(areq);
23741abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
238b460edb6SAntoine Tenart 	u64 cache_len;
2391b44c5a6SAntoine Ténart 
2401b44c5a6SAntoine Ténart 	*ret = 0;
2411b44c5a6SAntoine Ténart 
2421b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
2431b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
2441b44c5a6SAntoine Ténart 		dev_err(priv->dev,
2451b44c5a6SAntoine Ténart 			"hash: result: could not retrieve the result descriptor\n");
2461b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
247bdfd1909SAntoine Tenart 	} else {
248bdfd1909SAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
2491b44c5a6SAntoine Ténart 	}
2501b44c5a6SAntoine Ténart 
2511b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
2521b44c5a6SAntoine Ténart 
253c957f8b3SAntoine Ténart 	if (sreq->nents) {
254c957f8b3SAntoine Ténart 		dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE);
255c957f8b3SAntoine Ténart 		sreq->nents = 0;
256c957f8b3SAntoine Ténart 	}
2571b44c5a6SAntoine Ténart 
258b8592027SOfer Heifetz 	if (sreq->result_dma) {
2596c1c09b3SPascal van Leeuwen 		dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz,
260b8592027SOfer Heifetz 				 DMA_FROM_DEVICE);
261b8592027SOfer Heifetz 		sreq->result_dma = 0;
262b8592027SOfer Heifetz 	}
263b8592027SOfer Heifetz 
264cff9a175SAntoine Tenart 	if (sreq->cache_dma) {
265cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz,
266cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
267cff9a175SAntoine Tenart 		sreq->cache_dma = 0;
268aa524286SAntoine Tenart 		sreq->cache_sz = 0;
269cff9a175SAntoine Tenart 	}
2701b44c5a6SAntoine Ténart 
27141abed7dSPascal van Leeuwen 	if (sreq->finish) {
27241abed7dSPascal van Leeuwen 		if (sreq->hmac &&
27341abed7dSPascal van Leeuwen 		    (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) {
27441abed7dSPascal van Leeuwen 			/* Faking HMAC using hash - need to do outer hash */
27541abed7dSPascal van Leeuwen 			memcpy(sreq->cache, sreq->state,
27641abed7dSPascal van Leeuwen 			       crypto_ahash_digestsize(ahash));
27741abed7dSPascal van Leeuwen 
2786c1c09b3SPascal van Leeuwen 			memcpy(sreq->state, ctx->opad, sreq->digest_sz);
27941abed7dSPascal van Leeuwen 
28031fb084cSPascal van Leeuwen 			sreq->len = sreq->block_sz +
28141abed7dSPascal van Leeuwen 				    crypto_ahash_digestsize(ahash);
28231fb084cSPascal van Leeuwen 			sreq->processed = sreq->block_sz;
28341abed7dSPascal van Leeuwen 			sreq->hmac = 0;
28441abed7dSPascal van Leeuwen 
285177e358cSPascal van Leeuwen 			if (priv->flags & EIP197_TRC_CACHE)
28641abed7dSPascal van Leeuwen 				ctx->base.needs_inv = true;
28741abed7dSPascal van Leeuwen 			areq->nbytes = 0;
28841abed7dSPascal van Leeuwen 			safexcel_ahash_enqueue(areq);
28941abed7dSPascal van Leeuwen 
29041abed7dSPascal van Leeuwen 			*should_complete = false; /* Not done yet */
29141abed7dSPascal van Leeuwen 			return 1;
29241abed7dSPascal van Leeuwen 		}
29341abed7dSPascal van Leeuwen 
294b98687bbSPascal van Leeuwen 		if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM &&
295b98687bbSPascal van Leeuwen 			     ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) {
296a7cf8658SPascal van Leeuwen 			/* Undo final XOR with 0xffffffff ...*/
29713a1bb93SPascal van Leeuwen 			*(__le32 *)areq->result = ~sreq->state[0];
298a7cf8658SPascal van Leeuwen 		} else {
299b89a8159SAntoine Tenart 			memcpy(areq->result, sreq->state,
300b89a8159SAntoine Tenart 			       crypto_ahash_digestsize(ahash));
30141abed7dSPascal van Leeuwen 		}
302a7cf8658SPascal van Leeuwen 	}
303b89a8159SAntoine Tenart 
304b460edb6SAntoine Tenart 	cache_len = safexcel_queued_len(sreq);
3051b44c5a6SAntoine Ténart 	if (cache_len)
3061b44c5a6SAntoine Ténart 		memcpy(sreq->cache, sreq->cache_next, cache_len);
3071b44c5a6SAntoine Ténart 
3081b44c5a6SAntoine Ténart 	*should_complete = true;
3091b44c5a6SAntoine Ténart 
3101b44c5a6SAntoine Ténart 	return 1;
3111b44c5a6SAntoine Ténart }
3121b44c5a6SAntoine Ténart 
3131eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring,
3141eb7b403SOfer Heifetz 				   int *commands, int *results)
3151b44c5a6SAntoine Ténart {
3161b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
3171b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
3181b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
3191b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
3201b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc, *first_cdesc = NULL;
3211b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
3221b44c5a6SAntoine Ténart 	struct scatterlist *sg;
323098e51e5SPascal van Leeuwen 	struct safexcel_token *dmmy;
3246c1c09b3SPascal van Leeuwen 	int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0;
325b98687bbSPascal van Leeuwen 	u64 queued, len;
3261b44c5a6SAntoine Ténart 
327b98687bbSPascal van Leeuwen 	queued = safexcel_queued_len(req);
32841abed7dSPascal van Leeuwen 	if (queued <= HASH_CACHE_SIZE)
3291b44c5a6SAntoine Ténart 		cache_len = queued;
3301b44c5a6SAntoine Ténart 	else
3311b44c5a6SAntoine Ténart 		cache_len = queued - areq->nbytes;
3321b44c5a6SAntoine Ténart 
33341abed7dSPascal van Leeuwen 	if (!req->finish && !req->last_req) {
334809778e0SAntoine Ténart 		/* If this is not the last request and the queued data does not
33541abed7dSPascal van Leeuwen 		 * fit into full cache blocks, cache it for the next send call.
3361b44c5a6SAntoine Ténart 		 */
33741abed7dSPascal van Leeuwen 		extra = queued & (HASH_CACHE_SIZE - 1);
338082ec2d4SAntoine Tenart 
339809778e0SAntoine Ténart 		/* If this is not the last request and the queued data
340809778e0SAntoine Ténart 		 * is a multiple of a block, cache the last one for now.
341809778e0SAntoine Ténart 		 */
342dd4306a6SAntoine Tenart 		if (!extra)
34341abed7dSPascal van Leeuwen 			extra = HASH_CACHE_SIZE;
344809778e0SAntoine Ténart 
3451b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
346809778e0SAntoine Ténart 				   req->cache_next, extra,
347809778e0SAntoine Ténart 				   areq->nbytes - extra);
3481b44c5a6SAntoine Ténart 
3491b44c5a6SAntoine Ténart 		queued -= extra;
350dc5268b6SPascal van Leeuwen 
351dc5268b6SPascal van Leeuwen 		if (!queued) {
352dc5268b6SPascal van Leeuwen 			*commands = 0;
353dc5268b6SPascal van Leeuwen 			*results = 0;
354dc5268b6SPascal van Leeuwen 			return 0;
355dc5268b6SPascal van Leeuwen 		}
356b98687bbSPascal van Leeuwen 
357b98687bbSPascal van Leeuwen 		extra = 0;
358809778e0SAntoine Ténart 	}
3591b44c5a6SAntoine Ténart 
360b98687bbSPascal van Leeuwen 	if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) {
361b98687bbSPascal van Leeuwen 		if (unlikely(cache_len < AES_BLOCK_SIZE)) {
362b98687bbSPascal van Leeuwen 			/*
363b98687bbSPascal van Leeuwen 			 * Cache contains less than 1 full block, complete.
364b98687bbSPascal van Leeuwen 			 */
365b98687bbSPascal van Leeuwen 			extra = AES_BLOCK_SIZE - cache_len;
366b98687bbSPascal van Leeuwen 			if (queued > cache_len) {
367b98687bbSPascal van Leeuwen 				/* More data follows: borrow bytes */
368b98687bbSPascal van Leeuwen 				u64 tmp = queued - cache_len;
369b98687bbSPascal van Leeuwen 
370b98687bbSPascal van Leeuwen 				skip = min_t(u64, tmp, extra);
371b98687bbSPascal van Leeuwen 				sg_pcopy_to_buffer(areq->src,
372b98687bbSPascal van Leeuwen 					sg_nents(areq->src),
373b98687bbSPascal van Leeuwen 					req->cache + cache_len,
374b98687bbSPascal van Leeuwen 					skip, 0);
375b98687bbSPascal van Leeuwen 			}
376b98687bbSPascal van Leeuwen 			extra -= skip;
377b98687bbSPascal van Leeuwen 			memset(req->cache + cache_len + skip, 0, extra);
37838f21b4bSPascal van Leeuwen 			if (!ctx->cbcmac && extra) {
37938f21b4bSPascal van Leeuwen 				// 10- padding for XCBCMAC & CMAC
38038f21b4bSPascal van Leeuwen 				req->cache[cache_len + skip] = 0x80;
38138f21b4bSPascal van Leeuwen 				// HW will use K2 iso K3 - compensate!
38238f21b4bSPascal van Leeuwen 				for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
38313a1bb93SPascal van Leeuwen 					((__be32 *)req->cache)[i] ^=
38413a1bb93SPascal van Leeuwen 					  cpu_to_be32(le32_to_cpu(
38513a1bb93SPascal van Leeuwen 					    ctx->ipad[i] ^ ctx->ipad[i + 4]));
38638f21b4bSPascal van Leeuwen 			}
387b98687bbSPascal van Leeuwen 			cache_len = AES_BLOCK_SIZE;
388b98687bbSPascal van Leeuwen 			queued = queued + extra;
389b98687bbSPascal van Leeuwen 		}
390b98687bbSPascal van Leeuwen 
391b98687bbSPascal van Leeuwen 		/* XCBC continue: XOR previous result into 1st word */
392b98687bbSPascal van Leeuwen 		crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE);
393b98687bbSPascal van Leeuwen 	}
394b98687bbSPascal van Leeuwen 
395b98687bbSPascal van Leeuwen 	len = queued;
3961b44c5a6SAntoine Ténart 	/* Add a command descriptor for the cached data, if any */
3971b44c5a6SAntoine Ténart 	if (cache_len) {
398cff9a175SAntoine Tenart 		req->cache_dma = dma_map_single(priv->dev, req->cache,
3991b44c5a6SAntoine Ténart 						cache_len, DMA_TO_DEVICE);
4009744fec9SOfer Heifetz 		if (dma_mapping_error(priv->dev, req->cache_dma))
401cff9a175SAntoine Tenart 			return -EINVAL;
4021b44c5a6SAntoine Ténart 
403cff9a175SAntoine Tenart 		req->cache_sz = cache_len;
4041b44c5a6SAntoine Ténart 		first_cdesc = safexcel_add_cdesc(priv, ring, 1,
4051b44c5a6SAntoine Ténart 						 (cache_len == len),
406b98687bbSPascal van Leeuwen 						 req->cache_dma, cache_len,
407098e51e5SPascal van Leeuwen 						 len, ctx->base.ctxr_dma,
408098e51e5SPascal van Leeuwen 						 &dmmy);
4091b44c5a6SAntoine Ténart 		if (IS_ERR(first_cdesc)) {
4101b44c5a6SAntoine Ténart 			ret = PTR_ERR(first_cdesc);
4111b44c5a6SAntoine Ténart 			goto unmap_cache;
4121b44c5a6SAntoine Ténart 		}
4131b44c5a6SAntoine Ténart 		n_cdesc++;
4141b44c5a6SAntoine Ténart 
4151b44c5a6SAntoine Ténart 		queued -= cache_len;
4161b44c5a6SAntoine Ténart 		if (!queued)
4171b44c5a6SAntoine Ténart 			goto send_command;
4181b44c5a6SAntoine Ténart 	}
4191b44c5a6SAntoine Ténart 
4201b44c5a6SAntoine Ténart 	/* Now handle the current ahash request buffer(s) */
42141abed7dSPascal van Leeuwen 	req->nents = dma_map_sg(priv->dev, areq->src,
42241abed7dSPascal van Leeuwen 				sg_nents_for_len(areq->src,
42341abed7dSPascal van Leeuwen 						 areq->nbytes),
4241b44c5a6SAntoine Ténart 				DMA_TO_DEVICE);
425c957f8b3SAntoine Ténart 	if (!req->nents) {
4261b44c5a6SAntoine Ténart 		ret = -ENOMEM;
4271b44c5a6SAntoine Ténart 		goto cdesc_rollback;
4281b44c5a6SAntoine Ténart 	}
4291b44c5a6SAntoine Ténart 
430c957f8b3SAntoine Ténart 	for_each_sg(areq->src, sg, req->nents, i) {
4311b44c5a6SAntoine Ténart 		int sglen = sg_dma_len(sg);
4321b44c5a6SAntoine Ténart 
433b98687bbSPascal van Leeuwen 		if (unlikely(sglen <= skip)) {
434b98687bbSPascal van Leeuwen 			skip -= sglen;
435b98687bbSPascal van Leeuwen 			continue;
436b98687bbSPascal van Leeuwen 		}
437b98687bbSPascal van Leeuwen 
4381b44c5a6SAntoine Ténart 		/* Do not overflow the request */
439b98687bbSPascal van Leeuwen 		if ((queued + skip) <= sglen)
4401b44c5a6SAntoine Ténart 			sglen = queued;
441b98687bbSPascal van Leeuwen 		else
442b98687bbSPascal van Leeuwen 			sglen -= skip;
4431b44c5a6SAntoine Ténart 
4441b44c5a6SAntoine Ténart 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
44541abed7dSPascal van Leeuwen 					   !(queued - sglen),
446b98687bbSPascal van Leeuwen 					   sg_dma_address(sg) + skip, sglen,
447098e51e5SPascal van Leeuwen 					   len, ctx->base.ctxr_dma, &dmmy);
4481b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
4491b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
45057433b58SAntoine Tenart 			goto unmap_sg;
4511b44c5a6SAntoine Ténart 		}
4521b44c5a6SAntoine Ténart 
453b98687bbSPascal van Leeuwen 		if (!n_cdesc)
4541b44c5a6SAntoine Ténart 			first_cdesc = cdesc;
455b98687bbSPascal van Leeuwen 		n_cdesc++;
4561b44c5a6SAntoine Ténart 
4571b44c5a6SAntoine Ténart 		queued -= sglen;
4581b44c5a6SAntoine Ténart 		if (!queued)
4591b44c5a6SAntoine Ténart 			break;
460b98687bbSPascal van Leeuwen 		skip = 0;
4611b44c5a6SAntoine Ténart 	}
4621b44c5a6SAntoine Ténart 
4631b44c5a6SAntoine Ténart send_command:
4641b44c5a6SAntoine Ténart 	/* Setup the context options */
46541abed7dSPascal van Leeuwen 	safexcel_context_control(ctx, req, first_cdesc);
4661b44c5a6SAntoine Ténart 
4676c1c09b3SPascal van Leeuwen 	/* Add the token */
4686c1c09b3SPascal van Leeuwen 	safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac);
4691b44c5a6SAntoine Ténart 
4706c1c09b3SPascal van Leeuwen 	req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz,
471b8592027SOfer Heifetz 					 DMA_FROM_DEVICE);
472b8592027SOfer Heifetz 	if (dma_mapping_error(priv->dev, req->result_dma)) {
4731b44c5a6SAntoine Ténart 		ret = -EINVAL;
47457433b58SAntoine Tenart 		goto unmap_sg;
4751b44c5a6SAntoine Ténart 	}
4761b44c5a6SAntoine Ténart 
4771b44c5a6SAntoine Ténart 	/* Add a result descriptor */
478b8592027SOfer Heifetz 	rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma,
4796c1c09b3SPascal van Leeuwen 				   req->digest_sz);
4801b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
4811b44c5a6SAntoine Ténart 		ret = PTR_ERR(rdesc);
48257240a78SAntoine Tenart 		goto unmap_result;
4831b44c5a6SAntoine Ténart 	}
4841b44c5a6SAntoine Ténart 
4859744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, rdesc, &areq->base);
4861b44c5a6SAntoine Ténart 
487b98687bbSPascal van Leeuwen 	req->processed += len - extra;
488b460edb6SAntoine Tenart 
4891b44c5a6SAntoine Ténart 	*commands = n_cdesc;
4901b44c5a6SAntoine Ténart 	*results = 1;
4911b44c5a6SAntoine Ténart 	return 0;
4921b44c5a6SAntoine Ténart 
49357240a78SAntoine Tenart unmap_result:
4946c1c09b3SPascal van Leeuwen 	dma_unmap_single(priv->dev, req->result_dma, req->digest_sz,
49557433b58SAntoine Tenart 			 DMA_FROM_DEVICE);
49657433b58SAntoine Tenart unmap_sg:
497b98687bbSPascal van Leeuwen 	if (req->nents) {
49857240a78SAntoine Tenart 		dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE);
499b98687bbSPascal van Leeuwen 		req->nents = 0;
500b98687bbSPascal van Leeuwen 	}
5011b44c5a6SAntoine Ténart cdesc_rollback:
5021b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
5031b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
5041b44c5a6SAntoine Ténart unmap_cache:
505cff9a175SAntoine Tenart 	if (req->cache_dma) {
506cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz,
507cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
508aa524286SAntoine Tenart 		req->cache_dma = 0;
509cff9a175SAntoine Tenart 		req->cache_sz = 0;
5101b44c5a6SAntoine Ténart 	}
5111b44c5a6SAntoine Ténart 
5121b44c5a6SAntoine Ténart 	return ret;
5131b44c5a6SAntoine Ténart }
5141b44c5a6SAntoine Ténart 
5151b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
5161b44c5a6SAntoine Ténart 				      int ring,
5171b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
5181b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
5191b44c5a6SAntoine Ténart {
5201b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
5211b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
5221b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
5231b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
5241b44c5a6SAntoine Ténart 	int enq_ret;
5251b44c5a6SAntoine Ténart 
5261b44c5a6SAntoine Ténart 	*ret = 0;
5271b44c5a6SAntoine Ténart 
5281b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
5291b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
5301b44c5a6SAntoine Ténart 		dev_err(priv->dev,
5311b44c5a6SAntoine Ténart 			"hash: invalidate: could not retrieve the result descriptor\n");
5321b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
533cda3e73aSAntoine Tenart 	} else {
534cda3e73aSAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
5351b44c5a6SAntoine Ténart 	}
5361b44c5a6SAntoine Ténart 
5371b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
5381b44c5a6SAntoine Ténart 
5391b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
5401b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
5411b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
5421b44c5a6SAntoine Ténart 
5431b44c5a6SAntoine Ténart 		*should_complete = true;
5441b44c5a6SAntoine Ténart 		return 1;
5451b44c5a6SAntoine Ténart 	}
5461b44c5a6SAntoine Ténart 
54786671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
54886671abbSAntoine Ténart 	ctx->base.ring = ring;
5491b44c5a6SAntoine Ténart 
55086671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
55186671abbSAntoine Ténart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async);
55286671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
5531b44c5a6SAntoine Ténart 
5541b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
5551b44c5a6SAntoine Ténart 		*ret = enq_ret;
5561b44c5a6SAntoine Ténart 
5578472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
5588472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
55986671abbSAntoine Ténart 
5601b44c5a6SAntoine Ténart 	*should_complete = false;
5611b44c5a6SAntoine Ténart 
5621b44c5a6SAntoine Ténart 	return 1;
5631b44c5a6SAntoine Ténart }
5641b44c5a6SAntoine Ténart 
5651eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring,
5661eb7b403SOfer Heifetz 				  struct crypto_async_request *async,
5671eb7b403SOfer Heifetz 				  bool *should_complete, int *ret)
5681eb7b403SOfer Heifetz {
5691eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
5701eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5711eb7b403SOfer Heifetz 	int err;
5721eb7b403SOfer Heifetz 
57353c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv);
574871df319SAntoine Ténart 
5751eb7b403SOfer Heifetz 	if (req->needs_inv) {
5761eb7b403SOfer Heifetz 		req->needs_inv = false;
5771eb7b403SOfer Heifetz 		err = safexcel_handle_inv_result(priv, ring, async,
5781eb7b403SOfer Heifetz 						 should_complete, ret);
5791eb7b403SOfer Heifetz 	} else {
5801eb7b403SOfer Heifetz 		err = safexcel_handle_req_result(priv, ring, async,
5811eb7b403SOfer Heifetz 						 should_complete, ret);
5821eb7b403SOfer Heifetz 	}
5831eb7b403SOfer Heifetz 
5841eb7b403SOfer Heifetz 	return err;
5851eb7b403SOfer Heifetz }
5861eb7b403SOfer Heifetz 
5871b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async,
5889744fec9SOfer Heifetz 				   int ring, int *commands, int *results)
5891b44c5a6SAntoine Ténart {
5901b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
5911b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
5921b44c5a6SAntoine Ténart 	int ret;
5931b44c5a6SAntoine Ténart 
5945290ad6eSOfer Heifetz 	ret = safexcel_invalidate_cache(async, ctx->priv,
5959744fec9SOfer Heifetz 					ctx->base.ctxr_dma, ring);
5961b44c5a6SAntoine Ténart 	if (unlikely(ret))
5971b44c5a6SAntoine Ténart 		return ret;
5981b44c5a6SAntoine Ténart 
5991b44c5a6SAntoine Ténart 	*commands = 1;
6001b44c5a6SAntoine Ténart 	*results = 1;
6011b44c5a6SAntoine Ténart 
6021b44c5a6SAntoine Ténart 	return 0;
6031b44c5a6SAntoine Ténart }
6041b44c5a6SAntoine Ténart 
6051eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async,
6069744fec9SOfer Heifetz 			       int ring, int *commands, int *results)
6071eb7b403SOfer Heifetz {
6081eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
6091eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6101eb7b403SOfer Heifetz 	int ret;
6111eb7b403SOfer Heifetz 
6121eb7b403SOfer Heifetz 	if (req->needs_inv)
6139744fec9SOfer Heifetz 		ret = safexcel_ahash_send_inv(async, ring, commands, results);
6141eb7b403SOfer Heifetz 	else
6159744fec9SOfer Heifetz 		ret = safexcel_ahash_send_req(async, ring, commands, results);
6169744fec9SOfer Heifetz 
6171eb7b403SOfer Heifetz 	return ret;
6181eb7b403SOfer Heifetz }
6191eb7b403SOfer Heifetz 
6201b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm)
6211b44c5a6SAntoine Ténart {
6221b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
6231b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
62461824806SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE);
6257cad2fabSAntoine Ténart 	struct safexcel_ahash_req *rctx = ahash_request_ctx(req);
6263e1166b9SArnd Bergmann 	struct safexcel_inv_result result = {};
62786671abbSAntoine Ténart 	int ring = ctx->base.ring;
6281b44c5a6SAntoine Ténart 
629b926213dSAntoine Tenart 	memset(req, 0, EIP197_AHASH_REQ_SIZE);
6301b44c5a6SAntoine Ténart 
6311b44c5a6SAntoine Ténart 	/* create invalidation request */
6321b44c5a6SAntoine Ténart 	init_completion(&result.completion);
6337cad2fabSAntoine Ténart 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
6341b44c5a6SAntoine Ténart 				   safexcel_inv_complete, &result);
6351b44c5a6SAntoine Ténart 
6367cad2fabSAntoine Ténart 	ahash_request_set_tfm(req, __crypto_ahash_cast(tfm));
6377cad2fabSAntoine Ténart 	ctx = crypto_tfm_ctx(req->base.tfm);
6381b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
6391eb7b403SOfer Heifetz 	rctx->needs_inv = true;
6401b44c5a6SAntoine Ténart 
64186671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
6427cad2fabSAntoine Ténart 	crypto_enqueue_request(&priv->ring[ring].queue, &req->base);
64386671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
6441b44c5a6SAntoine Ténart 
6458472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
6468472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
6471b44c5a6SAntoine Ténart 
648b7007dbcSAntoine Tenart 	wait_for_completion(&result.completion);
6491b44c5a6SAntoine Ténart 
6501b44c5a6SAntoine Ténart 	if (result.error) {
6511b44c5a6SAntoine Ténart 		dev_warn(priv->dev, "hash: completion error (%d)\n",
6521b44c5a6SAntoine Ténart 			 result.error);
6531b44c5a6SAntoine Ténart 		return result.error;
6541b44c5a6SAntoine Ténart 	}
6551b44c5a6SAntoine Ténart 
6561b44c5a6SAntoine Ténart 	return 0;
6571b44c5a6SAntoine Ténart }
6581b44c5a6SAntoine Ténart 
659cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to
660cc75f5ceSAntoine Ténart  * the engine, aka. when there is at least 1 block size in the pipe.
661cc75f5ceSAntoine Ténart  */
66241abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq)
6631b44c5a6SAntoine Ténart {
6641b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
66541abed7dSPascal van Leeuwen 	u64 cache_len;
6661b44c5a6SAntoine Ténart 
667b460edb6SAntoine Tenart 	/* cache_len: everything accepted by the driver but not sent yet,
668b460edb6SAntoine Tenart 	 * tot sz handled by update() - last req sz - tot sz handled by send()
669b460edb6SAntoine Tenart 	 */
67041abed7dSPascal van Leeuwen 	cache_len = safexcel_queued_len(req);
6711b44c5a6SAntoine Ténart 
6721b44c5a6SAntoine Ténart 	/*
6731b44c5a6SAntoine Ténart 	 * In case there isn't enough bytes to proceed (less than a
6741b44c5a6SAntoine Ténart 	 * block size), cache the data until we have enough.
6751b44c5a6SAntoine Ténart 	 */
67641abed7dSPascal van Leeuwen 	if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) {
6771b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
6781b44c5a6SAntoine Ténart 				   req->cache + cache_len,
6791b44c5a6SAntoine Ténart 				   areq->nbytes, 0);
68041abed7dSPascal van Leeuwen 		return 0;
6811b44c5a6SAntoine Ténart 	}
6821b44c5a6SAntoine Ténart 
683dfbcc08fSAntoine Ténart 	/* We couldn't cache all the data */
6841b44c5a6SAntoine Ténart 	return -E2BIG;
6851b44c5a6SAntoine Ténart }
6861b44c5a6SAntoine Ténart 
6871b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq)
6881b44c5a6SAntoine Ténart {
6891b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
6901b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6911b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
69286671abbSAntoine Ténart 	int ret, ring;
6931b44c5a6SAntoine Ténart 
6941eb7b403SOfer Heifetz 	req->needs_inv = false;
6951b44c5a6SAntoine Ténart 
696c4daf4ccSOfer Heifetz 	if (ctx->base.ctxr) {
69753c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv &&
698b98687bbSPascal van Leeuwen 		     /* invalidate for *any* non-XCBC continuation */
699b98687bbSPascal van Leeuwen 		   ((req->not_first && !req->xcbcmac) ||
70041abed7dSPascal van Leeuwen 		     /* invalidate if (i)digest changed */
70141abed7dSPascal van Leeuwen 		     memcmp(ctx->base.ctxr->data, req->state, req->state_sz) ||
70241abed7dSPascal van Leeuwen 		     /* invalidate for HMAC finish with odigest changed */
703a7cf8658SPascal van Leeuwen 		     (req->finish && req->hmac &&
70441abed7dSPascal van Leeuwen 		      memcmp(ctx->base.ctxr->data + (req->state_sz>>2),
70541abed7dSPascal van Leeuwen 			     ctx->opad, req->state_sz))))
70641abed7dSPascal van Leeuwen 			/*
70741abed7dSPascal van Leeuwen 			 * We're still setting needs_inv here, even though it is
708c4daf4ccSOfer Heifetz 			 * cleared right away, because the needs_inv flag can be
709c4daf4ccSOfer Heifetz 			 * set in other functions and we want to keep the same
710c4daf4ccSOfer Heifetz 			 * logic.
711c4daf4ccSOfer Heifetz 			 */
71241abed7dSPascal van Leeuwen 			ctx->base.needs_inv = true;
7131b44c5a6SAntoine Ténart 
7141eb7b403SOfer Heifetz 		if (ctx->base.needs_inv) {
7151eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
7161eb7b403SOfer Heifetz 			req->needs_inv = true;
7171eb7b403SOfer Heifetz 		}
7181b44c5a6SAntoine Ténart 	} else {
7191b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
7201b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
7211b44c5a6SAntoine Ténart 						 EIP197_GFP_FLAGS(areq->base),
7221b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
7231b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
7241b44c5a6SAntoine Ténart 			return -ENOMEM;
7251b44c5a6SAntoine Ténart 	}
726b98687bbSPascal van Leeuwen 	req->not_first = true;
7271b44c5a6SAntoine Ténart 
72886671abbSAntoine Ténart 	ring = ctx->base.ring;
7291b44c5a6SAntoine Ténart 
73086671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
73186671abbSAntoine Ténart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base);
73286671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
73386671abbSAntoine Ténart 
7348472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
7358472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
7361b44c5a6SAntoine Ténart 
7371b44c5a6SAntoine Ténart 	return ret;
7381b44c5a6SAntoine Ténart }
7391b44c5a6SAntoine Ténart 
7401b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq)
7411b44c5a6SAntoine Ténart {
7421b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
74341abed7dSPascal van Leeuwen 	int ret;
7441b44c5a6SAntoine Ténart 
7451b44c5a6SAntoine Ténart 	/* If the request is 0 length, do nothing */
7461b44c5a6SAntoine Ténart 	if (!areq->nbytes)
7471b44c5a6SAntoine Ténart 		return 0;
7481b44c5a6SAntoine Ténart 
74941abed7dSPascal van Leeuwen 	/* Add request to the cache if it fits */
75041abed7dSPascal van Leeuwen 	ret = safexcel_ahash_cache(areq);
75141abed7dSPascal van Leeuwen 
75241abed7dSPascal van Leeuwen 	/* Update total request length */
75331fb084cSPascal van Leeuwen 	req->len += areq->nbytes;
7541b44c5a6SAntoine Ténart 
75541abed7dSPascal van Leeuwen 	/* If not all data could fit into the cache, go process the excess.
75641abed7dSPascal van Leeuwen 	 * Also go process immediately for an HMAC IV precompute, which
75741abed7dSPascal van Leeuwen 	 * will never be finished at all, but needs to be processed anyway.
7581b44c5a6SAntoine Ténart 	 */
75941abed7dSPascal van Leeuwen 	if ((ret && !req->finish) || req->last_req)
7601b44c5a6SAntoine Ténart 		return safexcel_ahash_enqueue(areq);
7611b44c5a6SAntoine Ténart 
7621b44c5a6SAntoine Ténart 	return 0;
7631b44c5a6SAntoine Ténart }
7641b44c5a6SAntoine Ténart 
7651b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq)
7661b44c5a6SAntoine Ténart {
7671b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
7681b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
7691b44c5a6SAntoine Ténart 
7701b44c5a6SAntoine Ténart 	req->finish = true;
7711b44c5a6SAntoine Ténart 
77231fb084cSPascal van Leeuwen 	if (unlikely(!req->len && !areq->nbytes)) {
77385695b09SPascal van Leeuwen 		/*
77485695b09SPascal van Leeuwen 		 * If we have an overall 0 length *hash* request:
77585695b09SPascal van Leeuwen 		 * The HW cannot do 0 length hash, so we provide the correct
77685695b09SPascal van Leeuwen 		 * result directly here.
77785695b09SPascal van Leeuwen 		 */
778293f89cfSOfer Heifetz 		if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5)
779293f89cfSOfer Heifetz 			memcpy(areq->result, md5_zero_message_hash,
780293f89cfSOfer Heifetz 			       MD5_DIGEST_SIZE);
781293f89cfSOfer Heifetz 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1)
7821b44c5a6SAntoine Ténart 			memcpy(areq->result, sha1_zero_message_hash,
7831b44c5a6SAntoine Ténart 			       SHA1_DIGEST_SIZE);
7841b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224)
7851b44c5a6SAntoine Ténart 			memcpy(areq->result, sha224_zero_message_hash,
7861b44c5a6SAntoine Ténart 			       SHA224_DIGEST_SIZE);
7871b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256)
7881b44c5a6SAntoine Ténart 			memcpy(areq->result, sha256_zero_message_hash,
7891b44c5a6SAntoine Ténart 			       SHA256_DIGEST_SIZE);
7909e46eafdSAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384)
7919e46eafdSAntoine Tenart 			memcpy(areq->result, sha384_zero_message_hash,
7929e46eafdSAntoine Tenart 			       SHA384_DIGEST_SIZE);
793b460edb6SAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512)
794b460edb6SAntoine Tenart 			memcpy(areq->result, sha512_zero_message_hash,
795b460edb6SAntoine Tenart 			       SHA512_DIGEST_SIZE);
7960f2bc131SPascal van Leeuwen 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) {
7970f2bc131SPascal van Leeuwen 			memcpy(areq->result,
7980f2bc131SPascal van Leeuwen 			       EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE);
7990f2bc131SPascal van Leeuwen 		}
8001b44c5a6SAntoine Ténart 
8011b44c5a6SAntoine Ténart 		return 0;
802a7cf8658SPascal van Leeuwen 	} else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM &&
803a7cf8658SPascal van Leeuwen 			    ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 &&
804a7cf8658SPascal van Leeuwen 			    req->len == sizeof(u32) && !areq->nbytes)) {
805a7cf8658SPascal van Leeuwen 		/* Zero length CRC32 */
806a7cf8658SPascal van Leeuwen 		memcpy(areq->result, ctx->ipad, sizeof(u32));
807a7cf8658SPascal van Leeuwen 		return 0;
80838f21b4bSPascal van Leeuwen 	} else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE &&
809b98687bbSPascal van Leeuwen 			    !areq->nbytes)) {
810b98687bbSPascal van Leeuwen 		/* Zero length CBC MAC */
811b98687bbSPascal van Leeuwen 		memset(areq->result, 0, AES_BLOCK_SIZE);
812b98687bbSPascal van Leeuwen 		return 0;
81338f21b4bSPascal van Leeuwen 	} else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE &&
81438f21b4bSPascal van Leeuwen 			    !areq->nbytes)) {
81538f21b4bSPascal van Leeuwen 		/* Zero length (X)CBC/CMAC */
81638f21b4bSPascal van Leeuwen 		int i;
81738f21b4bSPascal van Leeuwen 
81838f21b4bSPascal van Leeuwen 		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
81913a1bb93SPascal van Leeuwen 			((__be32 *)areq->result)[i] =
82013a1bb93SPascal van Leeuwen 				cpu_to_be32(le32_to_cpu(ctx->ipad[i + 4]));//K3
82138f21b4bSPascal van Leeuwen 		areq->result[0] ^= 0x80;			// 10- padding
82238f21b4bSPascal van Leeuwen 		crypto_cipher_encrypt_one(ctx->kaes, areq->result, areq->result);
82338f21b4bSPascal van Leeuwen 		return 0;
82431fb084cSPascal van Leeuwen 	} else if (unlikely(req->hmac &&
82531fb084cSPascal van Leeuwen 			    (req->len == req->block_sz) &&
82641abed7dSPascal van Leeuwen 			    !areq->nbytes)) {
82785b36ee8SPascal van Leeuwen 		/*
82885b36ee8SPascal van Leeuwen 		 * If we have an overall 0 length *HMAC* request:
82985b36ee8SPascal van Leeuwen 		 * For HMAC, we need to finalize the inner digest
83085b36ee8SPascal van Leeuwen 		 * and then perform the outer hash.
83185b36ee8SPascal van Leeuwen 		 */
83285b36ee8SPascal van Leeuwen 
83385b36ee8SPascal van Leeuwen 		/* generate pad block in the cache */
83485b36ee8SPascal van Leeuwen 		/* start with a hash block of all zeroes */
83585b36ee8SPascal van Leeuwen 		memset(req->cache, 0, req->block_sz);
83685b36ee8SPascal van Leeuwen 		/* set the first byte to 0x80 to 'append a 1 bit' */
83785b36ee8SPascal van Leeuwen 		req->cache[0] = 0x80;
83885b36ee8SPascal van Leeuwen 		/* add the length in bits in the last 2 bytes */
83985b36ee8SPascal van Leeuwen 		if (req->len_is_le) {
84085b36ee8SPascal van Leeuwen 			/* Little endian length word (e.g. MD5) */
84185b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-8] = (req->block_sz << 3) &
84285b36ee8SPascal van Leeuwen 						      255;
84385b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-7] = (req->block_sz >> 5);
84485b36ee8SPascal van Leeuwen 		} else {
84585b36ee8SPascal van Leeuwen 			/* Big endian length word (e.g. any SHA) */
84685b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-2] = (req->block_sz >> 5);
84785b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-1] = (req->block_sz << 3) &
84885b36ee8SPascal van Leeuwen 						      255;
84985b36ee8SPascal van Leeuwen 		}
85085b36ee8SPascal van Leeuwen 
85131fb084cSPascal van Leeuwen 		req->len += req->block_sz; /* plus 1 hash block */
85285b36ee8SPascal van Leeuwen 
85385b36ee8SPascal van Leeuwen 		/* Set special zero-length HMAC flag */
85485b36ee8SPascal van Leeuwen 		req->hmac_zlen = true;
85585b36ee8SPascal van Leeuwen 
85685b36ee8SPascal van Leeuwen 		/* Finalize HMAC */
85785b36ee8SPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
85841abed7dSPascal van Leeuwen 	} else if (req->hmac) {
85941abed7dSPascal van Leeuwen 		/* Finalize HMAC */
86041abed7dSPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
8611b44c5a6SAntoine Ténart 	}
8621b44c5a6SAntoine Ténart 
8631b44c5a6SAntoine Ténart 	return safexcel_ahash_enqueue(areq);
8641b44c5a6SAntoine Ténart }
8651b44c5a6SAntoine Ténart 
8661b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq)
8671b44c5a6SAntoine Ténart {
8681b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8691b44c5a6SAntoine Ténart 
8701b44c5a6SAntoine Ténart 	req->finish = true;
8711b44c5a6SAntoine Ténart 
8721b44c5a6SAntoine Ténart 	safexcel_ahash_update(areq);
8731b44c5a6SAntoine Ténart 	return safexcel_ahash_final(areq);
8741b44c5a6SAntoine Ténart }
8751b44c5a6SAntoine Ténart 
8761b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out)
8771b44c5a6SAntoine Ténart {
8781b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8791b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state *export = out;
8801b44c5a6SAntoine Ténart 
88131fb084cSPascal van Leeuwen 	export->len = req->len;
88231fb084cSPascal van Leeuwen 	export->processed = req->processed;
8831b44c5a6SAntoine Ténart 
884b869648cSAntoine Tenart 	export->digest = req->digest;
885b869648cSAntoine Tenart 
8861b44c5a6SAntoine Ténart 	memcpy(export->state, req->state, req->state_sz);
88741abed7dSPascal van Leeuwen 	memcpy(export->cache, req->cache, HASH_CACHE_SIZE);
8881b44c5a6SAntoine Ténart 
8891b44c5a6SAntoine Ténart 	return 0;
8901b44c5a6SAntoine Ténart }
8911b44c5a6SAntoine Ténart 
8921b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in)
8931b44c5a6SAntoine Ténart {
8941b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8951b44c5a6SAntoine Ténart 	const struct safexcel_ahash_export_state *export = in;
8961b44c5a6SAntoine Ténart 	int ret;
8971b44c5a6SAntoine Ténart 
8981b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
8991b44c5a6SAntoine Ténart 	if (ret)
9001b44c5a6SAntoine Ténart 		return ret;
9011b44c5a6SAntoine Ténart 
90231fb084cSPascal van Leeuwen 	req->len = export->len;
90331fb084cSPascal van Leeuwen 	req->processed = export->processed;
9041b44c5a6SAntoine Ténart 
905b869648cSAntoine Tenart 	req->digest = export->digest;
906b869648cSAntoine Tenart 
90741abed7dSPascal van Leeuwen 	memcpy(req->cache, export->cache, HASH_CACHE_SIZE);
9081b44c5a6SAntoine Ténart 	memcpy(req->state, export->state, req->state_sz);
9091b44c5a6SAntoine Ténart 
9101b44c5a6SAntoine Ténart 	return 0;
9111b44c5a6SAntoine Ténart }
9121b44c5a6SAntoine Ténart 
9131b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm)
9141b44c5a6SAntoine Ténart {
9151b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
9161b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
9171b44c5a6SAntoine Ténart 		container_of(__crypto_ahash_alg(tfm->__crt_alg),
9181b44c5a6SAntoine Ténart 			     struct safexcel_alg_template, alg.ahash);
9191b44c5a6SAntoine Ténart 
9201b44c5a6SAntoine Ténart 	ctx->priv = tmpl->priv;
9211eb7b403SOfer Heifetz 	ctx->base.send = safexcel_ahash_send;
9221eb7b403SOfer Heifetz 	ctx->base.handle_result = safexcel_handle_result;
9236c1c09b3SPascal van Leeuwen 	ctx->fb_do_setkey = false;
9241b44c5a6SAntoine Ténart 
9251b44c5a6SAntoine Ténart 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
9261b44c5a6SAntoine Ténart 				 sizeof(struct safexcel_ahash_req));
9271b44c5a6SAntoine Ténart 	return 0;
9281b44c5a6SAntoine Ténart }
9291b44c5a6SAntoine Ténart 
9301b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq)
9311b44c5a6SAntoine Ténart {
9321b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
9331b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
9341b44c5a6SAntoine Ténart 
9351b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
9361b44c5a6SAntoine Ténart 
9371b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
938b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
9391b44c5a6SAntoine Ténart 	req->state_sz = SHA1_DIGEST_SIZE;
9406c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA1_DIGEST_SIZE;
94141abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
9421b44c5a6SAntoine Ténart 
9431b44c5a6SAntoine Ténart 	return 0;
9441b44c5a6SAntoine Ténart }
9451b44c5a6SAntoine Ténart 
9461b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq)
9471b44c5a6SAntoine Ténart {
9481b44c5a6SAntoine Ténart 	int ret = safexcel_sha1_init(areq);
9491b44c5a6SAntoine Ténart 
9501b44c5a6SAntoine Ténart 	if (ret)
9511b44c5a6SAntoine Ténart 		return ret;
9521b44c5a6SAntoine Ténart 
9531b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
9541b44c5a6SAntoine Ténart }
9551b44c5a6SAntoine Ténart 
9561b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm)
9571b44c5a6SAntoine Ténart {
9581b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
9591b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
9601b44c5a6SAntoine Ténart 	int ret;
9611b44c5a6SAntoine Ténart 
9621b44c5a6SAntoine Ténart 	/* context not allocated, skip invalidation */
9631b44c5a6SAntoine Ténart 	if (!ctx->base.ctxr)
9641b44c5a6SAntoine Ténart 		return;
9651b44c5a6SAntoine Ténart 
96653c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
9671b44c5a6SAntoine Ténart 		ret = safexcel_ahash_exit_inv(tfm);
9681b44c5a6SAntoine Ténart 		if (ret)
9691b44c5a6SAntoine Ténart 			dev_warn(priv->dev, "hash: invalidation error %d\n", ret);
970871df319SAntoine Ténart 	} else {
971871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
972871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
973871df319SAntoine Ténart 	}
9741b44c5a6SAntoine Ténart }
9751b44c5a6SAntoine Ténart 
9761b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = {
9771b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
978062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
9791b44c5a6SAntoine Ténart 	.alg.ahash = {
9801b44c5a6SAntoine Ténart 		.init = safexcel_sha1_init,
9811b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
9821b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
9831b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
9841b44c5a6SAntoine Ténart 		.digest = safexcel_sha1_digest,
9851b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
9861b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
9871b44c5a6SAntoine Ténart 		.halg = {
9881b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
9891b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
9901b44c5a6SAntoine Ténart 			.base = {
9911b44c5a6SAntoine Ténart 				.cra_name = "sha1",
9921b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha1",
993aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
9941b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
995b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
9961b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
9971b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
9981b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
9991b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
10001b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
10011b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
10021b44c5a6SAntoine Ténart 			},
10031b44c5a6SAntoine Ténart 		},
10041b44c5a6SAntoine Ténart 	},
10051b44c5a6SAntoine Ténart };
10061b44c5a6SAntoine Ténart 
10071b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq)
10081b44c5a6SAntoine Ténart {
100941abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1010b869648cSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
10111b44c5a6SAntoine Ténart 
101241abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
101341abed7dSPascal van Leeuwen 
101441abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
101541abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA1_DIGEST_SIZE);
101641abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
101731fb084cSPascal van Leeuwen 	req->len	= SHA1_BLOCK_SIZE;
101831fb084cSPascal van Leeuwen 	req->processed	= SHA1_BLOCK_SIZE;
101941abed7dSPascal van Leeuwen 
102041abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
102141abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
102241abed7dSPascal van Leeuwen 	req->state_sz = SHA1_DIGEST_SIZE;
10236c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA1_DIGEST_SIZE;
102441abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
102541abed7dSPascal van Leeuwen 	req->hmac = true;
102641abed7dSPascal van Leeuwen 
10271b44c5a6SAntoine Ténart 	return 0;
10281b44c5a6SAntoine Ténart }
10291b44c5a6SAntoine Ténart 
10301b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq)
10311b44c5a6SAntoine Ténart {
10321b44c5a6SAntoine Ténart 	int ret = safexcel_hmac_sha1_init(areq);
10331b44c5a6SAntoine Ténart 
10341b44c5a6SAntoine Ténart 	if (ret)
10351b44c5a6SAntoine Ténart 		return ret;
10361b44c5a6SAntoine Ténart 
10371b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
10381b44c5a6SAntoine Ténart }
10391b44c5a6SAntoine Ténart 
10401b44c5a6SAntoine Ténart struct safexcel_ahash_result {
10411b44c5a6SAntoine Ténart 	struct completion completion;
10421b44c5a6SAntoine Ténart 	int error;
10431b44c5a6SAntoine Ténart };
10441b44c5a6SAntoine Ténart 
10451b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error)
10461b44c5a6SAntoine Ténart {
10471b44c5a6SAntoine Ténart 	struct safexcel_ahash_result *result = req->data;
10481b44c5a6SAntoine Ténart 
10491b44c5a6SAntoine Ténart 	if (error == -EINPROGRESS)
10501b44c5a6SAntoine Ténart 		return;
10511b44c5a6SAntoine Ténart 
10521b44c5a6SAntoine Ténart 	result->error = error;
10531b44c5a6SAntoine Ténart 	complete(&result->completion);
10541b44c5a6SAntoine Ténart }
10551b44c5a6SAntoine Ténart 
10561b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq,
10571b44c5a6SAntoine Ténart 				  unsigned int blocksize, const u8 *key,
10581b44c5a6SAntoine Ténart 				  unsigned int keylen, u8 *ipad, u8 *opad)
10591b44c5a6SAntoine Ténart {
10601b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
10611b44c5a6SAntoine Ténart 	struct scatterlist sg;
10621b44c5a6SAntoine Ténart 	int ret, i;
10631b44c5a6SAntoine Ténart 	u8 *keydup;
10641b44c5a6SAntoine Ténart 
10651b44c5a6SAntoine Ténart 	if (keylen <= blocksize) {
10661b44c5a6SAntoine Ténart 		memcpy(ipad, key, keylen);
10671b44c5a6SAntoine Ténart 	} else {
10681b44c5a6SAntoine Ténart 		keydup = kmemdup(key, keylen, GFP_KERNEL);
10691b44c5a6SAntoine Ténart 		if (!keydup)
10701b44c5a6SAntoine Ténart 			return -ENOMEM;
10711b44c5a6SAntoine Ténart 
10721b44c5a6SAntoine Ténart 		ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
10731b44c5a6SAntoine Ténart 					   safexcel_ahash_complete, &result);
10741b44c5a6SAntoine Ténart 		sg_init_one(&sg, keydup, keylen);
10751b44c5a6SAntoine Ténart 		ahash_request_set_crypt(areq, &sg, ipad, keylen);
10761b44c5a6SAntoine Ténart 		init_completion(&result.completion);
10771b44c5a6SAntoine Ténart 
10781b44c5a6SAntoine Ténart 		ret = crypto_ahash_digest(areq);
10794dc5475aSAntoine Tenart 		if (ret == -EINPROGRESS || ret == -EBUSY) {
10801b44c5a6SAntoine Ténart 			wait_for_completion_interruptible(&result.completion);
10811b44c5a6SAntoine Ténart 			ret = result.error;
10821b44c5a6SAntoine Ténart 		}
10831b44c5a6SAntoine Ténart 
10841b44c5a6SAntoine Ténart 		/* Avoid leaking */
108557059185SDenis Efremov 		kfree_sensitive(keydup);
10861b44c5a6SAntoine Ténart 
10871b44c5a6SAntoine Ténart 		if (ret)
10881b44c5a6SAntoine Ténart 			return ret;
10891b44c5a6SAntoine Ténart 
10901b44c5a6SAntoine Ténart 		keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq));
10911b44c5a6SAntoine Ténart 	}
10921b44c5a6SAntoine Ténart 
10931b44c5a6SAntoine Ténart 	memset(ipad + keylen, 0, blocksize - keylen);
10941b44c5a6SAntoine Ténart 	memcpy(opad, ipad, blocksize);
10951b44c5a6SAntoine Ténart 
10961b44c5a6SAntoine Ténart 	for (i = 0; i < blocksize; i++) {
1097aed3731eSAntoine Ténart 		ipad[i] ^= HMAC_IPAD_VALUE;
1098aed3731eSAntoine Ténart 		opad[i] ^= HMAC_OPAD_VALUE;
10991b44c5a6SAntoine Ténart 	}
11001b44c5a6SAntoine Ténart 
11011b44c5a6SAntoine Ténart 	return 0;
11021b44c5a6SAntoine Ténart }
11031b44c5a6SAntoine Ténart 
11041b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq,
11051b44c5a6SAntoine Ténart 				 unsigned int blocksize, u8 *pad, void *state)
11061b44c5a6SAntoine Ténart {
11071b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
11081b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req;
11091b44c5a6SAntoine Ténart 	struct scatterlist sg;
11101b44c5a6SAntoine Ténart 	int ret;
11111b44c5a6SAntoine Ténart 
11121b44c5a6SAntoine Ténart 	ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
11131b44c5a6SAntoine Ténart 				   safexcel_ahash_complete, &result);
11141b44c5a6SAntoine Ténart 	sg_init_one(&sg, pad, blocksize);
11151b44c5a6SAntoine Ténart 	ahash_request_set_crypt(areq, &sg, pad, blocksize);
11161b44c5a6SAntoine Ténart 	init_completion(&result.completion);
11171b44c5a6SAntoine Ténart 
11181b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
11191b44c5a6SAntoine Ténart 	if (ret)
11201b44c5a6SAntoine Ténart 		return ret;
11211b44c5a6SAntoine Ténart 
11221b44c5a6SAntoine Ténart 	req = ahash_request_ctx(areq);
11231b44c5a6SAntoine Ténart 	req->hmac = true;
11241b44c5a6SAntoine Ténart 	req->last_req = true;
11251b44c5a6SAntoine Ténart 
11261b44c5a6SAntoine Ténart 	ret = crypto_ahash_update(areq);
112712bf4142SOfer Heifetz 	if (ret && ret != -EINPROGRESS && ret != -EBUSY)
11281b44c5a6SAntoine Ténart 		return ret;
11291b44c5a6SAntoine Ténart 
11301b44c5a6SAntoine Ténart 	wait_for_completion_interruptible(&result.completion);
11311b44c5a6SAntoine Ténart 	if (result.error)
11321b44c5a6SAntoine Ténart 		return result.error;
11331b44c5a6SAntoine Ténart 
11341b44c5a6SAntoine Ténart 	return crypto_ahash_export(areq, state);
11351b44c5a6SAntoine Ténart }
11361b44c5a6SAntoine Ténart 
1137f6beaea3SAntoine Tenart int safexcel_hmac_setkey(const char *alg, const u8 *key, unsigned int keylen,
1138f6beaea3SAntoine Tenart 			 void *istate, void *ostate)
11391b44c5a6SAntoine Ténart {
11401b44c5a6SAntoine Ténart 	struct ahash_request *areq;
11411b44c5a6SAntoine Ténart 	struct crypto_ahash *tfm;
11421b44c5a6SAntoine Ténart 	unsigned int blocksize;
11431b44c5a6SAntoine Ténart 	u8 *ipad, *opad;
11441b44c5a6SAntoine Ténart 	int ret;
11451b44c5a6SAntoine Ténart 
114685d7311fSEric Biggers 	tfm = crypto_alloc_ahash(alg, 0, 0);
11471b44c5a6SAntoine Ténart 	if (IS_ERR(tfm))
11481b44c5a6SAntoine Ténart 		return PTR_ERR(tfm);
11491b44c5a6SAntoine Ténart 
11501b44c5a6SAntoine Ténart 	areq = ahash_request_alloc(tfm, GFP_KERNEL);
11511b44c5a6SAntoine Ténart 	if (!areq) {
11521b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11531b44c5a6SAntoine Ténart 		goto free_ahash;
11541b44c5a6SAntoine Ténart 	}
11551b44c5a6SAntoine Ténart 
11561b44c5a6SAntoine Ténart 	crypto_ahash_clear_flags(tfm, ~0);
11571b44c5a6SAntoine Ténart 	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
11581b44c5a6SAntoine Ténart 
11596396bb22SKees Cook 	ipad = kcalloc(2, blocksize, GFP_KERNEL);
11601b44c5a6SAntoine Ténart 	if (!ipad) {
11611b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11621b44c5a6SAntoine Ténart 		goto free_request;
11631b44c5a6SAntoine Ténart 	}
11641b44c5a6SAntoine Ténart 
11651b44c5a6SAntoine Ténart 	opad = ipad + blocksize;
11661b44c5a6SAntoine Ténart 
11671b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad);
11681b44c5a6SAntoine Ténart 	if (ret)
11691b44c5a6SAntoine Ténart 		goto free_ipad;
11701b44c5a6SAntoine Ténart 
11711b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate);
11721b44c5a6SAntoine Ténart 	if (ret)
11731b44c5a6SAntoine Ténart 		goto free_ipad;
11741b44c5a6SAntoine Ténart 
11751b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate);
11761b44c5a6SAntoine Ténart 
11771b44c5a6SAntoine Ténart free_ipad:
11781b44c5a6SAntoine Ténart 	kfree(ipad);
11791b44c5a6SAntoine Ténart free_request:
11801b44c5a6SAntoine Ténart 	ahash_request_free(areq);
11811b44c5a6SAntoine Ténart free_ahash:
11821b44c5a6SAntoine Ténart 	crypto_free_ahash(tfm);
11831b44c5a6SAntoine Ténart 
11841b44c5a6SAntoine Ténart 	return ret;
11851b44c5a6SAntoine Ténart }
11861b44c5a6SAntoine Ténart 
118773f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key,
118873f36ea7SAntoine Tenart 				    unsigned int keylen, const char *alg,
118973f36ea7SAntoine Tenart 				    unsigned int state_sz)
11901b44c5a6SAntoine Ténart {
11911b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1192871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
11931b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state istate, ostate;
119441abed7dSPascal van Leeuwen 	int ret;
11951b44c5a6SAntoine Ténart 
119673f36ea7SAntoine Tenart 	ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate);
11971b44c5a6SAntoine Ténart 	if (ret)
11981b44c5a6SAntoine Ténart 		return ret;
11991b44c5a6SAntoine Ténart 
120041abed7dSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr &&
120141abed7dSPascal van Leeuwen 	    (memcmp(ctx->ipad, istate.state, state_sz) ||
120241abed7dSPascal van Leeuwen 	     memcmp(ctx->opad, ostate.state, state_sz)))
12031b44c5a6SAntoine Ténart 		ctx->base.needs_inv = true;
12041b44c5a6SAntoine Ténart 
120573f36ea7SAntoine Tenart 	memcpy(ctx->ipad, &istate.state, state_sz);
120673f36ea7SAntoine Tenart 	memcpy(ctx->opad, &ostate.state, state_sz);
120742ef3bedSAntoine Ténart 
12081b44c5a6SAntoine Ténart 	return 0;
12091b44c5a6SAntoine Ténart }
12101b44c5a6SAntoine Ténart 
121173f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
121273f36ea7SAntoine Tenart 				     unsigned int keylen)
121373f36ea7SAntoine Tenart {
121473f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1",
121573f36ea7SAntoine Tenart 					SHA1_DIGEST_SIZE);
121673f36ea7SAntoine Tenart }
121773f36ea7SAntoine Tenart 
12181b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = {
12191b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1220062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
12211b44c5a6SAntoine Ténart 	.alg.ahash = {
12221b44c5a6SAntoine Ténart 		.init = safexcel_hmac_sha1_init,
12231b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12241b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12251b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12261b44c5a6SAntoine Ténart 		.digest = safexcel_hmac_sha1_digest,
12271b44c5a6SAntoine Ténart 		.setkey = safexcel_hmac_sha1_setkey,
12281b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12291b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12301b44c5a6SAntoine Ténart 		.halg = {
12311b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
12321b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12331b44c5a6SAntoine Ténart 			.base = {
12341b44c5a6SAntoine Ténart 				.cra_name = "hmac(sha1)",
12351b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-hmac-sha1",
1236aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12371b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1238b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
12391b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12401b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
12411b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12421b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
12431b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
12441b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
12451b44c5a6SAntoine Ténart 			},
12461b44c5a6SAntoine Ténart 		},
12471b44c5a6SAntoine Ténart 	},
12481b44c5a6SAntoine Ténart };
12491b44c5a6SAntoine Ténart 
12501b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq)
12511b44c5a6SAntoine Ténart {
12521b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
12531b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
12541b44c5a6SAntoine Ténart 
12551b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
12561b44c5a6SAntoine Ténart 
12571b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1258b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
12591b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
12606c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
126141abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
12621b44c5a6SAntoine Ténart 
12631b44c5a6SAntoine Ténart 	return 0;
12641b44c5a6SAntoine Ténart }
12651b44c5a6SAntoine Ténart 
12661b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq)
12671b44c5a6SAntoine Ténart {
12681b44c5a6SAntoine Ténart 	int ret = safexcel_sha256_init(areq);
12691b44c5a6SAntoine Ténart 
12701b44c5a6SAntoine Ténart 	if (ret)
12711b44c5a6SAntoine Ténart 		return ret;
12721b44c5a6SAntoine Ténart 
12731b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
12741b44c5a6SAntoine Ténart }
12751b44c5a6SAntoine Ténart 
12761b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = {
12771b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1278062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
12791b44c5a6SAntoine Ténart 	.alg.ahash = {
12801b44c5a6SAntoine Ténart 		.init = safexcel_sha256_init,
12811b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12821b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12831b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12841b44c5a6SAntoine Ténart 		.digest = safexcel_sha256_digest,
12851b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12861b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12871b44c5a6SAntoine Ténart 		.halg = {
12881b44c5a6SAntoine Ténart 			.digestsize = SHA256_DIGEST_SIZE,
12891b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12901b44c5a6SAntoine Ténart 			.base = {
12911b44c5a6SAntoine Ténart 				.cra_name = "sha256",
12921b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha256",
1293aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12941b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1295b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
12961b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12971b44c5a6SAntoine Ténart 				.cra_blocksize = SHA256_BLOCK_SIZE,
12981b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12991b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
13001b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
13011b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
13021b44c5a6SAntoine Ténart 			},
13031b44c5a6SAntoine Ténart 		},
13041b44c5a6SAntoine Ténart 	},
13051b44c5a6SAntoine Ténart };
13061b44c5a6SAntoine Ténart 
13071b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq)
13081b44c5a6SAntoine Ténart {
13091b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
13101b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
13111b44c5a6SAntoine Ténart 
13121b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
13131b44c5a6SAntoine Ténart 
13141b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1315b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
13161b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
13176c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
131841abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
13191b44c5a6SAntoine Ténart 
13201b44c5a6SAntoine Ténart 	return 0;
13211b44c5a6SAntoine Ténart }
13221b44c5a6SAntoine Ténart 
13231b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq)
13241b44c5a6SAntoine Ténart {
13251b44c5a6SAntoine Ténart 	int ret = safexcel_sha224_init(areq);
13261b44c5a6SAntoine Ténart 
13271b44c5a6SAntoine Ténart 	if (ret)
13281b44c5a6SAntoine Ténart 		return ret;
13291b44c5a6SAntoine Ténart 
13301b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
13311b44c5a6SAntoine Ténart }
13321b44c5a6SAntoine Ténart 
13331b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = {
13341b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1335062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
13361b44c5a6SAntoine Ténart 	.alg.ahash = {
13371b44c5a6SAntoine Ténart 		.init = safexcel_sha224_init,
13381b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
13391b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
13401b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
13411b44c5a6SAntoine Ténart 		.digest = safexcel_sha224_digest,
13421b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
13431b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
13441b44c5a6SAntoine Ténart 		.halg = {
13451b44c5a6SAntoine Ténart 			.digestsize = SHA224_DIGEST_SIZE,
13461b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
13471b44c5a6SAntoine Ténart 			.base = {
13481b44c5a6SAntoine Ténart 				.cra_name = "sha224",
13491b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha224",
1350aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
13511b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1352b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
13531b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
13541b44c5a6SAntoine Ténart 				.cra_blocksize = SHA224_BLOCK_SIZE,
13551b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
13561b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
13571b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
13581b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
13591b44c5a6SAntoine Ténart 			},
13601b44c5a6SAntoine Ténart 		},
13611b44c5a6SAntoine Ténart 	},
13621b44c5a6SAntoine Ténart };
136373f36ea7SAntoine Tenart 
13643ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key,
13653ad618d8SAntoine Tenart 				       unsigned int keylen)
13663ad618d8SAntoine Tenart {
13673ad618d8SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224",
13683ad618d8SAntoine Tenart 					SHA256_DIGEST_SIZE);
13693ad618d8SAntoine Tenart }
13703ad618d8SAntoine Tenart 
13713ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq)
13723ad618d8SAntoine Tenart {
137341abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
13743ad618d8SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
13753ad618d8SAntoine Tenart 
137641abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
137741abed7dSPascal van Leeuwen 
137841abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
137941abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE);
138041abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
138131fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
138231fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
138341abed7dSPascal van Leeuwen 
138441abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
138541abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
138641abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
13876c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
138841abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
138941abed7dSPascal van Leeuwen 	req->hmac = true;
139041abed7dSPascal van Leeuwen 
13913ad618d8SAntoine Tenart 	return 0;
13923ad618d8SAntoine Tenart }
13933ad618d8SAntoine Tenart 
13943ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq)
13953ad618d8SAntoine Tenart {
13963ad618d8SAntoine Tenart 	int ret = safexcel_hmac_sha224_init(areq);
13973ad618d8SAntoine Tenart 
13983ad618d8SAntoine Tenart 	if (ret)
13993ad618d8SAntoine Tenart 		return ret;
14003ad618d8SAntoine Tenart 
14013ad618d8SAntoine Tenart 	return safexcel_ahash_finup(areq);
14023ad618d8SAntoine Tenart }
14033ad618d8SAntoine Tenart 
14043ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = {
14053ad618d8SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1406062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
14073ad618d8SAntoine Tenart 	.alg.ahash = {
14083ad618d8SAntoine Tenart 		.init = safexcel_hmac_sha224_init,
14093ad618d8SAntoine Tenart 		.update = safexcel_ahash_update,
14103ad618d8SAntoine Tenart 		.final = safexcel_ahash_final,
14113ad618d8SAntoine Tenart 		.finup = safexcel_ahash_finup,
14123ad618d8SAntoine Tenart 		.digest = safexcel_hmac_sha224_digest,
14133ad618d8SAntoine Tenart 		.setkey = safexcel_hmac_sha224_setkey,
14143ad618d8SAntoine Tenart 		.export = safexcel_ahash_export,
14153ad618d8SAntoine Tenart 		.import = safexcel_ahash_import,
14163ad618d8SAntoine Tenart 		.halg = {
14173ad618d8SAntoine Tenart 			.digestsize = SHA224_DIGEST_SIZE,
14183ad618d8SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
14193ad618d8SAntoine Tenart 			.base = {
14203ad618d8SAntoine Tenart 				.cra_name = "hmac(sha224)",
14213ad618d8SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha224",
1422aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
14233ad618d8SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1424b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
14253ad618d8SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
14263ad618d8SAntoine Tenart 				.cra_blocksize = SHA224_BLOCK_SIZE,
14273ad618d8SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
14283ad618d8SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
14293ad618d8SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
14303ad618d8SAntoine Tenart 				.cra_module = THIS_MODULE,
14313ad618d8SAntoine Tenart 			},
14323ad618d8SAntoine Tenart 		},
14333ad618d8SAntoine Tenart 	},
14343ad618d8SAntoine Tenart };
14353ad618d8SAntoine Tenart 
143673f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
143773f36ea7SAntoine Tenart 				     unsigned int keylen)
143873f36ea7SAntoine Tenart {
143973f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256",
144073f36ea7SAntoine Tenart 					SHA256_DIGEST_SIZE);
144173f36ea7SAntoine Tenart }
144273f36ea7SAntoine Tenart 
144373f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq)
144473f36ea7SAntoine Tenart {
144541abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
144673f36ea7SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
144773f36ea7SAntoine Tenart 
144841abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
144941abed7dSPascal van Leeuwen 
145041abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
145141abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE);
145241abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
145331fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
145431fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
145541abed7dSPascal van Leeuwen 
145641abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
145741abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
145841abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
14596c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
146041abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
146141abed7dSPascal van Leeuwen 	req->hmac = true;
146241abed7dSPascal van Leeuwen 
146373f36ea7SAntoine Tenart 	return 0;
146473f36ea7SAntoine Tenart }
146573f36ea7SAntoine Tenart 
146673f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq)
146773f36ea7SAntoine Tenart {
146873f36ea7SAntoine Tenart 	int ret = safexcel_hmac_sha256_init(areq);
146973f36ea7SAntoine Tenart 
147073f36ea7SAntoine Tenart 	if (ret)
147173f36ea7SAntoine Tenart 		return ret;
147273f36ea7SAntoine Tenart 
147373f36ea7SAntoine Tenart 	return safexcel_ahash_finup(areq);
147473f36ea7SAntoine Tenart }
147573f36ea7SAntoine Tenart 
147673f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = {
147773f36ea7SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1478062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
147973f36ea7SAntoine Tenart 	.alg.ahash = {
148073f36ea7SAntoine Tenart 		.init = safexcel_hmac_sha256_init,
148173f36ea7SAntoine Tenart 		.update = safexcel_ahash_update,
148273f36ea7SAntoine Tenart 		.final = safexcel_ahash_final,
148373f36ea7SAntoine Tenart 		.finup = safexcel_ahash_finup,
148473f36ea7SAntoine Tenart 		.digest = safexcel_hmac_sha256_digest,
148573f36ea7SAntoine Tenart 		.setkey = safexcel_hmac_sha256_setkey,
148673f36ea7SAntoine Tenart 		.export = safexcel_ahash_export,
148773f36ea7SAntoine Tenart 		.import = safexcel_ahash_import,
148873f36ea7SAntoine Tenart 		.halg = {
148973f36ea7SAntoine Tenart 			.digestsize = SHA256_DIGEST_SIZE,
149073f36ea7SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
149173f36ea7SAntoine Tenart 			.base = {
149273f36ea7SAntoine Tenart 				.cra_name = "hmac(sha256)",
149373f36ea7SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha256",
1494aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
149573f36ea7SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1496b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
149773f36ea7SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
149873f36ea7SAntoine Tenart 				.cra_blocksize = SHA256_BLOCK_SIZE,
149973f36ea7SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
150073f36ea7SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
150173f36ea7SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
150273f36ea7SAntoine Tenart 				.cra_module = THIS_MODULE,
150373f36ea7SAntoine Tenart 			},
150473f36ea7SAntoine Tenart 		},
150573f36ea7SAntoine Tenart 	},
150673f36ea7SAntoine Tenart };
1507b460edb6SAntoine Tenart 
1508b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq)
1509b460edb6SAntoine Tenart {
1510b460edb6SAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1511b460edb6SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1512b460edb6SAntoine Tenart 
1513b460edb6SAntoine Tenart 	memset(req, 0, sizeof(*req));
1514b460edb6SAntoine Tenart 
1515b460edb6SAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
1516b460edb6SAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1517b460edb6SAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
15186c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
151941abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
1520b460edb6SAntoine Tenart 
1521b460edb6SAntoine Tenart 	return 0;
1522b460edb6SAntoine Tenart }
1523b460edb6SAntoine Tenart 
1524b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq)
1525b460edb6SAntoine Tenart {
1526b460edb6SAntoine Tenart 	int ret = safexcel_sha512_init(areq);
1527b460edb6SAntoine Tenart 
1528b460edb6SAntoine Tenart 	if (ret)
1529b460edb6SAntoine Tenart 		return ret;
1530b460edb6SAntoine Tenart 
1531b460edb6SAntoine Tenart 	return safexcel_ahash_finup(areq);
1532b460edb6SAntoine Tenart }
1533b460edb6SAntoine Tenart 
1534b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = {
1535b460edb6SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1536062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
1537b460edb6SAntoine Tenart 	.alg.ahash = {
1538b460edb6SAntoine Tenart 		.init = safexcel_sha512_init,
1539b460edb6SAntoine Tenart 		.update = safexcel_ahash_update,
1540b460edb6SAntoine Tenart 		.final = safexcel_ahash_final,
1541b460edb6SAntoine Tenart 		.finup = safexcel_ahash_finup,
1542b460edb6SAntoine Tenart 		.digest = safexcel_sha512_digest,
1543b460edb6SAntoine Tenart 		.export = safexcel_ahash_export,
1544b460edb6SAntoine Tenart 		.import = safexcel_ahash_import,
1545b460edb6SAntoine Tenart 		.halg = {
1546b460edb6SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
1547b460edb6SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
1548b460edb6SAntoine Tenart 			.base = {
1549b460edb6SAntoine Tenart 				.cra_name = "sha512",
1550b460edb6SAntoine Tenart 				.cra_driver_name = "safexcel-sha512",
1551aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1552b460edb6SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1553b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1554b460edb6SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1555b460edb6SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
1556b460edb6SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1557b460edb6SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
1558b460edb6SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
1559b460edb6SAntoine Tenart 				.cra_module = THIS_MODULE,
1560b460edb6SAntoine Tenart 			},
1561b460edb6SAntoine Tenart 		},
1562b460edb6SAntoine Tenart 	},
1563b460edb6SAntoine Tenart };
15640de54fb1SAntoine Tenart 
15659e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq)
15669e46eafdSAntoine Tenart {
15679e46eafdSAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
15689e46eafdSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
15699e46eafdSAntoine Tenart 
15709e46eafdSAntoine Tenart 	memset(req, 0, sizeof(*req));
15719e46eafdSAntoine Tenart 
15729e46eafdSAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
15739e46eafdSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
15749e46eafdSAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
15756c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
157641abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
15779e46eafdSAntoine Tenart 
15789e46eafdSAntoine Tenart 	return 0;
15799e46eafdSAntoine Tenart }
15809e46eafdSAntoine Tenart 
15819e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq)
15829e46eafdSAntoine Tenart {
15839e46eafdSAntoine Tenart 	int ret = safexcel_sha384_init(areq);
15849e46eafdSAntoine Tenart 
15859e46eafdSAntoine Tenart 	if (ret)
15869e46eafdSAntoine Tenart 		return ret;
15879e46eafdSAntoine Tenart 
15889e46eafdSAntoine Tenart 	return safexcel_ahash_finup(areq);
15899e46eafdSAntoine Tenart }
15909e46eafdSAntoine Tenart 
15919e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = {
15929e46eafdSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1593062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
15949e46eafdSAntoine Tenart 	.alg.ahash = {
15959e46eafdSAntoine Tenart 		.init = safexcel_sha384_init,
15969e46eafdSAntoine Tenart 		.update = safexcel_ahash_update,
15979e46eafdSAntoine Tenart 		.final = safexcel_ahash_final,
15989e46eafdSAntoine Tenart 		.finup = safexcel_ahash_finup,
15999e46eafdSAntoine Tenart 		.digest = safexcel_sha384_digest,
16009e46eafdSAntoine Tenart 		.export = safexcel_ahash_export,
16019e46eafdSAntoine Tenart 		.import = safexcel_ahash_import,
16029e46eafdSAntoine Tenart 		.halg = {
16039e46eafdSAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
16049e46eafdSAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
16059e46eafdSAntoine Tenart 			.base = {
16069e46eafdSAntoine Tenart 				.cra_name = "sha384",
16079e46eafdSAntoine Tenart 				.cra_driver_name = "safexcel-sha384",
1608aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
16099e46eafdSAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1610b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
16119e46eafdSAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16129e46eafdSAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
16139e46eafdSAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
16149e46eafdSAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
16159e46eafdSAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
16169e46eafdSAntoine Tenart 				.cra_module = THIS_MODULE,
16179e46eafdSAntoine Tenart 			},
16189e46eafdSAntoine Tenart 		},
16199e46eafdSAntoine Tenart 	},
16209e46eafdSAntoine Tenart };
16219e46eafdSAntoine Tenart 
16220de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key,
16230de54fb1SAntoine Tenart 				       unsigned int keylen)
16240de54fb1SAntoine Tenart {
16250de54fb1SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512",
16260de54fb1SAntoine Tenart 					SHA512_DIGEST_SIZE);
16270de54fb1SAntoine Tenart }
16280de54fb1SAntoine Tenart 
16290de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq)
16300de54fb1SAntoine Tenart {
163141abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
16320de54fb1SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
16330de54fb1SAntoine Tenart 
163441abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
163541abed7dSPascal van Leeuwen 
163641abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
163741abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE);
163841abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
163931fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
164031fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
164141abed7dSPascal van Leeuwen 
164241abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
164341abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
164441abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
16456c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
164641abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
164741abed7dSPascal van Leeuwen 	req->hmac = true;
164841abed7dSPascal van Leeuwen 
16490de54fb1SAntoine Tenart 	return 0;
16500de54fb1SAntoine Tenart }
16510de54fb1SAntoine Tenart 
16520de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq)
16530de54fb1SAntoine Tenart {
16540de54fb1SAntoine Tenart 	int ret = safexcel_hmac_sha512_init(areq);
16550de54fb1SAntoine Tenart 
16560de54fb1SAntoine Tenart 	if (ret)
16570de54fb1SAntoine Tenart 		return ret;
16580de54fb1SAntoine Tenart 
16590de54fb1SAntoine Tenart 	return safexcel_ahash_finup(areq);
16600de54fb1SAntoine Tenart }
16610de54fb1SAntoine Tenart 
16620de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = {
16630de54fb1SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1664062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
16650de54fb1SAntoine Tenart 	.alg.ahash = {
16660de54fb1SAntoine Tenart 		.init = safexcel_hmac_sha512_init,
16670de54fb1SAntoine Tenart 		.update = safexcel_ahash_update,
16680de54fb1SAntoine Tenart 		.final = safexcel_ahash_final,
16690de54fb1SAntoine Tenart 		.finup = safexcel_ahash_finup,
16700de54fb1SAntoine Tenart 		.digest = safexcel_hmac_sha512_digest,
16710de54fb1SAntoine Tenart 		.setkey = safexcel_hmac_sha512_setkey,
16720de54fb1SAntoine Tenart 		.export = safexcel_ahash_export,
16730de54fb1SAntoine Tenart 		.import = safexcel_ahash_import,
16740de54fb1SAntoine Tenart 		.halg = {
16750de54fb1SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
16760de54fb1SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
16770de54fb1SAntoine Tenart 			.base = {
16780de54fb1SAntoine Tenart 				.cra_name = "hmac(sha512)",
16790de54fb1SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha512",
1680aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
16810de54fb1SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1682b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
16830de54fb1SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16840de54fb1SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
16850de54fb1SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
16860de54fb1SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
16870de54fb1SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
16880de54fb1SAntoine Tenart 				.cra_module = THIS_MODULE,
16890de54fb1SAntoine Tenart 			},
16900de54fb1SAntoine Tenart 		},
16910de54fb1SAntoine Tenart 	},
16920de54fb1SAntoine Tenart };
16931f5d5d98SAntoine Tenart 
16941f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key,
16951f5d5d98SAntoine Tenart 				       unsigned int keylen)
16961f5d5d98SAntoine Tenart {
16971f5d5d98SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384",
16981f5d5d98SAntoine Tenart 					SHA512_DIGEST_SIZE);
16991f5d5d98SAntoine Tenart }
17001f5d5d98SAntoine Tenart 
17011f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq)
17021f5d5d98SAntoine Tenart {
170341abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
17041f5d5d98SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
17051f5d5d98SAntoine Tenart 
170641abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
170741abed7dSPascal van Leeuwen 
170841abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
170941abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE);
171041abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
171131fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
171231fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
171341abed7dSPascal van Leeuwen 
171441abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
171541abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
171641abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
17176c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
171841abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
171941abed7dSPascal van Leeuwen 	req->hmac = true;
172041abed7dSPascal van Leeuwen 
17211f5d5d98SAntoine Tenart 	return 0;
17221f5d5d98SAntoine Tenart }
17231f5d5d98SAntoine Tenart 
17241f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq)
17251f5d5d98SAntoine Tenart {
17261f5d5d98SAntoine Tenart 	int ret = safexcel_hmac_sha384_init(areq);
17271f5d5d98SAntoine Tenart 
17281f5d5d98SAntoine Tenart 	if (ret)
17291f5d5d98SAntoine Tenart 		return ret;
17301f5d5d98SAntoine Tenart 
17311f5d5d98SAntoine Tenart 	return safexcel_ahash_finup(areq);
17321f5d5d98SAntoine Tenart }
17331f5d5d98SAntoine Tenart 
17341f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = {
17351f5d5d98SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1736062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
17371f5d5d98SAntoine Tenart 	.alg.ahash = {
17381f5d5d98SAntoine Tenart 		.init = safexcel_hmac_sha384_init,
17391f5d5d98SAntoine Tenart 		.update = safexcel_ahash_update,
17401f5d5d98SAntoine Tenart 		.final = safexcel_ahash_final,
17411f5d5d98SAntoine Tenart 		.finup = safexcel_ahash_finup,
17421f5d5d98SAntoine Tenart 		.digest = safexcel_hmac_sha384_digest,
17431f5d5d98SAntoine Tenart 		.setkey = safexcel_hmac_sha384_setkey,
17441f5d5d98SAntoine Tenart 		.export = safexcel_ahash_export,
17451f5d5d98SAntoine Tenart 		.import = safexcel_ahash_import,
17461f5d5d98SAntoine Tenart 		.halg = {
17471f5d5d98SAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
17481f5d5d98SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
17491f5d5d98SAntoine Tenart 			.base = {
17501f5d5d98SAntoine Tenart 				.cra_name = "hmac(sha384)",
17511f5d5d98SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha384",
1752aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
17531f5d5d98SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1754b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
17551f5d5d98SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
17561f5d5d98SAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
17571f5d5d98SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
17581f5d5d98SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
17591f5d5d98SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
17601f5d5d98SAntoine Tenart 				.cra_module = THIS_MODULE,
17611f5d5d98SAntoine Tenart 			},
17621f5d5d98SAntoine Tenart 		},
17631f5d5d98SAntoine Tenart 	},
17641f5d5d98SAntoine Tenart };
1765293f89cfSOfer Heifetz 
1766293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq)
1767293f89cfSOfer Heifetz {
1768293f89cfSOfer Heifetz 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1769293f89cfSOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1770293f89cfSOfer Heifetz 
1771293f89cfSOfer Heifetz 	memset(req, 0, sizeof(*req));
1772293f89cfSOfer Heifetz 
1773293f89cfSOfer Heifetz 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
1774293f89cfSOfer Heifetz 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1775293f89cfSOfer Heifetz 	req->state_sz = MD5_DIGEST_SIZE;
17766c1c09b3SPascal van Leeuwen 	req->digest_sz = MD5_DIGEST_SIZE;
177741abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
1778293f89cfSOfer Heifetz 
1779293f89cfSOfer Heifetz 	return 0;
1780293f89cfSOfer Heifetz }
1781293f89cfSOfer Heifetz 
1782293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq)
1783293f89cfSOfer Heifetz {
1784293f89cfSOfer Heifetz 	int ret = safexcel_md5_init(areq);
1785293f89cfSOfer Heifetz 
1786293f89cfSOfer Heifetz 	if (ret)
1787293f89cfSOfer Heifetz 		return ret;
1788293f89cfSOfer Heifetz 
1789293f89cfSOfer Heifetz 	return safexcel_ahash_finup(areq);
1790293f89cfSOfer Heifetz }
1791293f89cfSOfer Heifetz 
1792293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = {
1793293f89cfSOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1794062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1795293f89cfSOfer Heifetz 	.alg.ahash = {
1796293f89cfSOfer Heifetz 		.init = safexcel_md5_init,
1797293f89cfSOfer Heifetz 		.update = safexcel_ahash_update,
1798293f89cfSOfer Heifetz 		.final = safexcel_ahash_final,
1799293f89cfSOfer Heifetz 		.finup = safexcel_ahash_finup,
1800293f89cfSOfer Heifetz 		.digest = safexcel_md5_digest,
1801293f89cfSOfer Heifetz 		.export = safexcel_ahash_export,
1802293f89cfSOfer Heifetz 		.import = safexcel_ahash_import,
1803293f89cfSOfer Heifetz 		.halg = {
1804293f89cfSOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1805293f89cfSOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1806293f89cfSOfer Heifetz 			.base = {
1807293f89cfSOfer Heifetz 				.cra_name = "md5",
1808293f89cfSOfer Heifetz 				.cra_driver_name = "safexcel-md5",
1809aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1810293f89cfSOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1811b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1812293f89cfSOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1813293f89cfSOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1814293f89cfSOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1815293f89cfSOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1816293f89cfSOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1817293f89cfSOfer Heifetz 				.cra_module = THIS_MODULE,
1818293f89cfSOfer Heifetz 			},
1819293f89cfSOfer Heifetz 		},
1820293f89cfSOfer Heifetz 	},
1821293f89cfSOfer Heifetz };
1822b471e4b9SOfer Heifetz 
1823b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq)
1824b471e4b9SOfer Heifetz {
182541abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1826b471e4b9SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1827b471e4b9SOfer Heifetz 
182841abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
182941abed7dSPascal van Leeuwen 
183041abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
183141abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, MD5_DIGEST_SIZE);
183241abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
183331fb084cSPascal van Leeuwen 	req->len	= MD5_HMAC_BLOCK_SIZE;
183431fb084cSPascal van Leeuwen 	req->processed	= MD5_HMAC_BLOCK_SIZE;
183541abed7dSPascal van Leeuwen 
183641abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
183741abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
183841abed7dSPascal van Leeuwen 	req->state_sz = MD5_DIGEST_SIZE;
18396c1c09b3SPascal van Leeuwen 	req->digest_sz = MD5_DIGEST_SIZE;
184041abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
184185b36ee8SPascal van Leeuwen 	req->len_is_le = true; /* MD5 is little endian! ... */
184241abed7dSPascal van Leeuwen 	req->hmac = true;
184341abed7dSPascal van Leeuwen 
1844b471e4b9SOfer Heifetz 	return 0;
1845b471e4b9SOfer Heifetz }
1846b471e4b9SOfer Heifetz 
1847b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key,
1848b471e4b9SOfer Heifetz 				     unsigned int keylen)
1849b471e4b9SOfer Heifetz {
1850b471e4b9SOfer Heifetz 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5",
1851b471e4b9SOfer Heifetz 					MD5_DIGEST_SIZE);
1852b471e4b9SOfer Heifetz }
1853b471e4b9SOfer Heifetz 
1854b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq)
1855b471e4b9SOfer Heifetz {
1856b471e4b9SOfer Heifetz 	int ret = safexcel_hmac_md5_init(areq);
1857b471e4b9SOfer Heifetz 
1858b471e4b9SOfer Heifetz 	if (ret)
1859b471e4b9SOfer Heifetz 		return ret;
1860b471e4b9SOfer Heifetz 
1861b471e4b9SOfer Heifetz 	return safexcel_ahash_finup(areq);
1862b471e4b9SOfer Heifetz }
1863b471e4b9SOfer Heifetz 
1864b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = {
1865b471e4b9SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1866062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1867b471e4b9SOfer Heifetz 	.alg.ahash = {
1868b471e4b9SOfer Heifetz 		.init = safexcel_hmac_md5_init,
1869b471e4b9SOfer Heifetz 		.update = safexcel_ahash_update,
1870b471e4b9SOfer Heifetz 		.final = safexcel_ahash_final,
1871b471e4b9SOfer Heifetz 		.finup = safexcel_ahash_finup,
1872b471e4b9SOfer Heifetz 		.digest = safexcel_hmac_md5_digest,
1873b471e4b9SOfer Heifetz 		.setkey = safexcel_hmac_md5_setkey,
1874b471e4b9SOfer Heifetz 		.export = safexcel_ahash_export,
1875b471e4b9SOfer Heifetz 		.import = safexcel_ahash_import,
1876b471e4b9SOfer Heifetz 		.halg = {
1877b471e4b9SOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1878b471e4b9SOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1879b471e4b9SOfer Heifetz 			.base = {
1880b471e4b9SOfer Heifetz 				.cra_name = "hmac(md5)",
1881b471e4b9SOfer Heifetz 				.cra_driver_name = "safexcel-hmac-md5",
1882aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1883b471e4b9SOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1884b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1885b471e4b9SOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1886b471e4b9SOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1887b471e4b9SOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1888b471e4b9SOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1889b471e4b9SOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1890b471e4b9SOfer Heifetz 				.cra_module = THIS_MODULE,
1891b471e4b9SOfer Heifetz 			},
1892b471e4b9SOfer Heifetz 		},
1893b471e4b9SOfer Heifetz 	},
1894b471e4b9SOfer Heifetz };
1895a7cf8658SPascal van Leeuwen 
1896a7cf8658SPascal van Leeuwen static int safexcel_crc32_cra_init(struct crypto_tfm *tfm)
1897a7cf8658SPascal van Leeuwen {
1898a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
1899a7cf8658SPascal van Leeuwen 	int ret = safexcel_ahash_cra_init(tfm);
1900a7cf8658SPascal van Leeuwen 
1901a7cf8658SPascal van Leeuwen 	/* Default 'key' is all zeroes */
1902a7cf8658SPascal van Leeuwen 	memset(ctx->ipad, 0, sizeof(u32));
1903a7cf8658SPascal van Leeuwen 	return ret;
1904a7cf8658SPascal van Leeuwen }
1905a7cf8658SPascal van Leeuwen 
1906a7cf8658SPascal van Leeuwen static int safexcel_crc32_init(struct ahash_request *areq)
1907a7cf8658SPascal van Leeuwen {
1908a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1909a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1910a7cf8658SPascal van Leeuwen 
1911a7cf8658SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1912a7cf8658SPascal van Leeuwen 
1913a7cf8658SPascal van Leeuwen 	/* Start from loaded key */
191413a1bb93SPascal van Leeuwen 	req->state[0]	= (__force __le32)le32_to_cpu(~ctx->ipad[0]);
1915a7cf8658SPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
1916a7cf8658SPascal van Leeuwen 	req->len	= sizeof(u32);
1917a7cf8658SPascal van Leeuwen 	req->processed	= sizeof(u32);
1918a7cf8658SPascal van Leeuwen 
1919a7cf8658SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32;
1920a7cf8658SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_XCM;
1921a7cf8658SPascal van Leeuwen 	req->state_sz = sizeof(u32);
19226c1c09b3SPascal van Leeuwen 	req->digest_sz = sizeof(u32);
1923a7cf8658SPascal van Leeuwen 	req->block_sz = sizeof(u32);
1924a7cf8658SPascal van Leeuwen 
1925a7cf8658SPascal van Leeuwen 	return 0;
1926a7cf8658SPascal van Leeuwen }
1927a7cf8658SPascal van Leeuwen 
1928a7cf8658SPascal van Leeuwen static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key,
1929a7cf8658SPascal van Leeuwen 				 unsigned int keylen)
1930a7cf8658SPascal van Leeuwen {
1931a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1932a7cf8658SPascal van Leeuwen 
1933674f368aSEric Biggers 	if (keylen != sizeof(u32))
1934a7cf8658SPascal van Leeuwen 		return -EINVAL;
1935a7cf8658SPascal van Leeuwen 
1936a7cf8658SPascal van Leeuwen 	memcpy(ctx->ipad, key, sizeof(u32));
1937a7cf8658SPascal van Leeuwen 	return 0;
1938a7cf8658SPascal van Leeuwen }
1939a7cf8658SPascal van Leeuwen 
1940a7cf8658SPascal van Leeuwen static int safexcel_crc32_digest(struct ahash_request *areq)
1941a7cf8658SPascal van Leeuwen {
1942a7cf8658SPascal van Leeuwen 	return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq);
1943a7cf8658SPascal van Leeuwen }
1944a7cf8658SPascal van Leeuwen 
1945a7cf8658SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_crc32 = {
1946a7cf8658SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1947a7cf8658SPascal van Leeuwen 	.algo_mask = 0,
1948a7cf8658SPascal van Leeuwen 	.alg.ahash = {
1949a7cf8658SPascal van Leeuwen 		.init = safexcel_crc32_init,
1950a7cf8658SPascal van Leeuwen 		.update = safexcel_ahash_update,
1951a7cf8658SPascal van Leeuwen 		.final = safexcel_ahash_final,
1952a7cf8658SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
1953a7cf8658SPascal van Leeuwen 		.digest = safexcel_crc32_digest,
1954a7cf8658SPascal van Leeuwen 		.setkey = safexcel_crc32_setkey,
1955a7cf8658SPascal van Leeuwen 		.export = safexcel_ahash_export,
1956a7cf8658SPascal van Leeuwen 		.import = safexcel_ahash_import,
1957a7cf8658SPascal van Leeuwen 		.halg = {
1958a7cf8658SPascal van Leeuwen 			.digestsize = sizeof(u32),
1959a7cf8658SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
1960a7cf8658SPascal van Leeuwen 			.base = {
1961a7cf8658SPascal van Leeuwen 				.cra_name = "crc32",
1962a7cf8658SPascal van Leeuwen 				.cra_driver_name = "safexcel-crc32",
1963a7cf8658SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1964a7cf8658SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_OPTIONAL_KEY |
1965a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_ASYNC |
1966b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1967a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1968a7cf8658SPascal van Leeuwen 				.cra_blocksize = 1,
1969a7cf8658SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1970a7cf8658SPascal van Leeuwen 				.cra_init = safexcel_crc32_cra_init,
1971a7cf8658SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
1972a7cf8658SPascal van Leeuwen 				.cra_module = THIS_MODULE,
1973a7cf8658SPascal van Leeuwen 			},
1974a7cf8658SPascal van Leeuwen 		},
1975a7cf8658SPascal van Leeuwen 	},
1976a7cf8658SPascal van Leeuwen };
1977b98687bbSPascal van Leeuwen 
1978b98687bbSPascal van Leeuwen static int safexcel_cbcmac_init(struct ahash_request *areq)
1979b98687bbSPascal van Leeuwen {
1980b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1981b98687bbSPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1982b98687bbSPascal van Leeuwen 
1983b98687bbSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1984b98687bbSPascal van Leeuwen 
1985b98687bbSPascal van Leeuwen 	/* Start from loaded keys */
1986b98687bbSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, ctx->key_sz);
1987b98687bbSPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
1988b98687bbSPascal van Leeuwen 	req->len	= AES_BLOCK_SIZE;
1989b98687bbSPascal van Leeuwen 	req->processed	= AES_BLOCK_SIZE;
1990b98687bbSPascal van Leeuwen 
1991b98687bbSPascal van Leeuwen 	req->digest   = CONTEXT_CONTROL_DIGEST_XCM;
1992b98687bbSPascal van Leeuwen 	req->state_sz = ctx->key_sz;
19936c1c09b3SPascal van Leeuwen 	req->digest_sz = AES_BLOCK_SIZE;
1994b98687bbSPascal van Leeuwen 	req->block_sz = AES_BLOCK_SIZE;
1995b98687bbSPascal van Leeuwen 	req->xcbcmac  = true;
1996b98687bbSPascal van Leeuwen 
1997b98687bbSPascal van Leeuwen 	return 0;
1998b98687bbSPascal van Leeuwen }
1999b98687bbSPascal van Leeuwen 
2000b98687bbSPascal van Leeuwen static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
2001b98687bbSPascal van Leeuwen 				 unsigned int len)
2002b98687bbSPascal van Leeuwen {
2003b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
2004b98687bbSPascal van Leeuwen 	struct crypto_aes_ctx aes;
2005b98687bbSPascal van Leeuwen 	int ret, i;
2006b98687bbSPascal van Leeuwen 
2007b98687bbSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
2008674f368aSEric Biggers 	if (ret)
2009b98687bbSPascal van Leeuwen 		return ret;
2010b98687bbSPascal van Leeuwen 
2011b98687bbSPascal van Leeuwen 	memset(ctx->ipad, 0, 2 * AES_BLOCK_SIZE);
2012b98687bbSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
201313a1bb93SPascal van Leeuwen 		ctx->ipad[i + 8] = (__force __le32)cpu_to_be32(aes.key_enc[i]);
2014b98687bbSPascal van Leeuwen 
2015b98687bbSPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
2016b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
2017b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2018b98687bbSPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
2019b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
2020b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2021b98687bbSPascal van Leeuwen 	} else {
2022b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
2023b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2024b98687bbSPascal van Leeuwen 	}
202538f21b4bSPascal van Leeuwen 	ctx->cbcmac  = true;
2026b98687bbSPascal van Leeuwen 
2027b98687bbSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
2028b98687bbSPascal van Leeuwen 	return 0;
2029b98687bbSPascal van Leeuwen }
2030b98687bbSPascal van Leeuwen 
2031b98687bbSPascal van Leeuwen static int safexcel_cbcmac_digest(struct ahash_request *areq)
2032b98687bbSPascal van Leeuwen {
2033b98687bbSPascal van Leeuwen 	return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq);
2034b98687bbSPascal van Leeuwen }
2035b98687bbSPascal van Leeuwen 
2036b98687bbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbcmac = {
2037b98687bbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2038b98687bbSPascal van Leeuwen 	.algo_mask = 0,
2039b98687bbSPascal van Leeuwen 	.alg.ahash = {
2040b98687bbSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
2041b98687bbSPascal van Leeuwen 		.update = safexcel_ahash_update,
2042b98687bbSPascal van Leeuwen 		.final = safexcel_ahash_final,
2043b98687bbSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
2044b98687bbSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
2045b98687bbSPascal van Leeuwen 		.setkey = safexcel_cbcmac_setkey,
2046b98687bbSPascal van Leeuwen 		.export = safexcel_ahash_export,
2047b98687bbSPascal van Leeuwen 		.import = safexcel_ahash_import,
2048b98687bbSPascal van Leeuwen 		.halg = {
2049b98687bbSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
2050b98687bbSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2051b98687bbSPascal van Leeuwen 			.base = {
2052b98687bbSPascal van Leeuwen 				.cra_name = "cbcmac(aes)",
2053b98687bbSPascal van Leeuwen 				.cra_driver_name = "safexcel-cbcmac-aes",
2054b98687bbSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2055b98687bbSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2056b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
2057b98687bbSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
2058b98687bbSPascal van Leeuwen 				.cra_blocksize = 1,
2059b98687bbSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2060b98687bbSPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
2061b98687bbSPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
2062b98687bbSPascal van Leeuwen 				.cra_module = THIS_MODULE,
2063b98687bbSPascal van Leeuwen 			},
2064b98687bbSPascal van Leeuwen 		},
2065b98687bbSPascal van Leeuwen 	},
2066b98687bbSPascal van Leeuwen };
206738f21b4bSPascal van Leeuwen 
206838f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
206938f21b4bSPascal van Leeuwen 				 unsigned int len)
207038f21b4bSPascal van Leeuwen {
207138f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
207238f21b4bSPascal van Leeuwen 	struct crypto_aes_ctx aes;
207338f21b4bSPascal van Leeuwen 	u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)];
207438f21b4bSPascal van Leeuwen 	int ret, i;
207538f21b4bSPascal van Leeuwen 
207638f21b4bSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
2077674f368aSEric Biggers 	if (ret)
207838f21b4bSPascal van Leeuwen 		return ret;
207938f21b4bSPascal van Leeuwen 
208038f21b4bSPascal van Leeuwen 	/* precompute the XCBC key material */
208138f21b4bSPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK);
208238f21b4bSPascal van Leeuwen 	crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) &
208338f21b4bSPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
208438f21b4bSPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->kaes, key, len);
208538f21b4bSPascal van Leeuwen 	if (ret)
208638f21b4bSPascal van Leeuwen 		return ret;
208738f21b4bSPascal van Leeuwen 
208838f21b4bSPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
208938f21b4bSPascal van Leeuwen 		"\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1");
209038f21b4bSPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp,
209138f21b4bSPascal van Leeuwen 		"\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2");
209238f21b4bSPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + AES_BLOCK_SIZE,
209338f21b4bSPascal van Leeuwen 		"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3");
209438f21b4bSPascal van Leeuwen 	for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++)
209513a1bb93SPascal van Leeuwen 		ctx->ipad[i] =
209613a1bb93SPascal van Leeuwen 			cpu_to_le32((__force u32)cpu_to_be32(key_tmp[i]));
209738f21b4bSPascal van Leeuwen 
209838f21b4bSPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK);
209938f21b4bSPascal van Leeuwen 	crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) &
210038f21b4bSPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
210138f21b4bSPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->kaes,
210238f21b4bSPascal van Leeuwen 				   (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
210338f21b4bSPascal van Leeuwen 				   AES_MIN_KEY_SIZE);
210438f21b4bSPascal van Leeuwen 	if (ret)
210538f21b4bSPascal van Leeuwen 		return ret;
210638f21b4bSPascal van Leeuwen 
210738f21b4bSPascal van Leeuwen 	ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
210838f21b4bSPascal van Leeuwen 	ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
210938f21b4bSPascal van Leeuwen 	ctx->cbcmac = false;
211038f21b4bSPascal van Leeuwen 
211138f21b4bSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
211238f21b4bSPascal van Leeuwen 	return 0;
211338f21b4bSPascal van Leeuwen }
211438f21b4bSPascal van Leeuwen 
211538f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm)
211638f21b4bSPascal van Leeuwen {
211738f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
211838f21b4bSPascal van Leeuwen 
211938f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_init(tfm);
212038f21b4bSPascal van Leeuwen 	ctx->kaes = crypto_alloc_cipher("aes", 0, 0);
212127018ab1SYueHaibing 	return PTR_ERR_OR_ZERO(ctx->kaes);
212238f21b4bSPascal van Leeuwen }
212338f21b4bSPascal van Leeuwen 
212438f21b4bSPascal van Leeuwen static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm)
212538f21b4bSPascal van Leeuwen {
212638f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
212738f21b4bSPascal van Leeuwen 
212838f21b4bSPascal van Leeuwen 	crypto_free_cipher(ctx->kaes);
212938f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
213038f21b4bSPascal van Leeuwen }
213138f21b4bSPascal van Leeuwen 
213238f21b4bSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xcbcmac = {
213338f21b4bSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
213438f21b4bSPascal van Leeuwen 	.algo_mask = 0,
213538f21b4bSPascal van Leeuwen 	.alg.ahash = {
213638f21b4bSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
213738f21b4bSPascal van Leeuwen 		.update = safexcel_ahash_update,
213838f21b4bSPascal van Leeuwen 		.final = safexcel_ahash_final,
213938f21b4bSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
214038f21b4bSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
214138f21b4bSPascal van Leeuwen 		.setkey = safexcel_xcbcmac_setkey,
214238f21b4bSPascal van Leeuwen 		.export = safexcel_ahash_export,
214338f21b4bSPascal van Leeuwen 		.import = safexcel_ahash_import,
214438f21b4bSPascal van Leeuwen 		.halg = {
214538f21b4bSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
214638f21b4bSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
214738f21b4bSPascal van Leeuwen 			.base = {
214838f21b4bSPascal van Leeuwen 				.cra_name = "xcbc(aes)",
214938f21b4bSPascal van Leeuwen 				.cra_driver_name = "safexcel-xcbc-aes",
215038f21b4bSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
215138f21b4bSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2152b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
215338f21b4bSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
215438f21b4bSPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
215538f21b4bSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
215638f21b4bSPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
215738f21b4bSPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
215838f21b4bSPascal van Leeuwen 				.cra_module = THIS_MODULE,
215938f21b4bSPascal van Leeuwen 			},
216038f21b4bSPascal van Leeuwen 		},
216138f21b4bSPascal van Leeuwen 	},
216238f21b4bSPascal van Leeuwen };
21637a627db9SPascal van Leeuwen 
21647a627db9SPascal van Leeuwen static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
21657a627db9SPascal van Leeuwen 				unsigned int len)
21667a627db9SPascal van Leeuwen {
21677a627db9SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
21687a627db9SPascal van Leeuwen 	struct crypto_aes_ctx aes;
21697a627db9SPascal van Leeuwen 	__be64 consts[4];
21707a627db9SPascal van Leeuwen 	u64 _const[2];
21717a627db9SPascal van Leeuwen 	u8 msb_mask, gfmask;
21727a627db9SPascal van Leeuwen 	int ret, i;
21737a627db9SPascal van Leeuwen 
21747a627db9SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
2175674f368aSEric Biggers 	if (ret)
21767a627db9SPascal van Leeuwen 		return ret;
21777a627db9SPascal van Leeuwen 
21787a627db9SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
217913a1bb93SPascal van Leeuwen 		ctx->ipad[i + 8] =
218013a1bb93SPascal van Leeuwen 			cpu_to_le32((__force u32)cpu_to_be32(aes.key_enc[i]));
21817a627db9SPascal van Leeuwen 
21827a627db9SPascal van Leeuwen 	/* precompute the CMAC key material */
21837a627db9SPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK);
21847a627db9SPascal van Leeuwen 	crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) &
21857a627db9SPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
21867a627db9SPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->kaes, key, len);
21877a627db9SPascal van Leeuwen 	if (ret)
21887a627db9SPascal van Leeuwen 		return ret;
21897a627db9SPascal van Leeuwen 
21907a627db9SPascal van Leeuwen 	/* code below borrowed from crypto/cmac.c */
21917a627db9SPascal van Leeuwen 	/* encrypt the zero block */
21927a627db9SPascal van Leeuwen 	memset(consts, 0, AES_BLOCK_SIZE);
21937a627db9SPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)consts, (u8 *)consts);
21947a627db9SPascal van Leeuwen 
21957a627db9SPascal van Leeuwen 	gfmask = 0x87;
21967a627db9SPascal van Leeuwen 	_const[0] = be64_to_cpu(consts[1]);
21977a627db9SPascal van Leeuwen 	_const[1] = be64_to_cpu(consts[0]);
21987a627db9SPascal van Leeuwen 
21997a627db9SPascal van Leeuwen 	/* gf(2^128) multiply zero-ciphertext with u and u^2 */
22007a627db9SPascal van Leeuwen 	for (i = 0; i < 4; i += 2) {
22017a627db9SPascal van Leeuwen 		msb_mask = ((s64)_const[1] >> 63) & gfmask;
22027a627db9SPascal van Leeuwen 		_const[1] = (_const[1] << 1) | (_const[0] >> 63);
22037a627db9SPascal van Leeuwen 		_const[0] = (_const[0] << 1) ^ msb_mask;
22047a627db9SPascal van Leeuwen 
22057a627db9SPascal van Leeuwen 		consts[i + 0] = cpu_to_be64(_const[1]);
22067a627db9SPascal van Leeuwen 		consts[i + 1] = cpu_to_be64(_const[0]);
22077a627db9SPascal van Leeuwen 	}
22087a627db9SPascal van Leeuwen 	/* end of code borrowed from crypto/cmac.c */
22097a627db9SPascal van Leeuwen 
22107a627db9SPascal van Leeuwen 	for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++)
221113a1bb93SPascal van Leeuwen 		ctx->ipad[i] = (__force __le32)cpu_to_be32(((u32 *)consts)[i]);
22127a627db9SPascal van Leeuwen 
22137a627db9SPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
22147a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
22157a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
22167a627db9SPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
22177a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
22187a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
22197a627db9SPascal van Leeuwen 	} else {
22207a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
22217a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
22227a627db9SPascal van Leeuwen 	}
22237a627db9SPascal van Leeuwen 	ctx->cbcmac = false;
22247a627db9SPascal van Leeuwen 
22257a627db9SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
22267a627db9SPascal van Leeuwen 	return 0;
22277a627db9SPascal van Leeuwen }
22287a627db9SPascal van Leeuwen 
22297a627db9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cmac = {
22307a627db9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
22317a627db9SPascal van Leeuwen 	.algo_mask = 0,
22327a627db9SPascal van Leeuwen 	.alg.ahash = {
22337a627db9SPascal van Leeuwen 		.init = safexcel_cbcmac_init,
22347a627db9SPascal van Leeuwen 		.update = safexcel_ahash_update,
22357a627db9SPascal van Leeuwen 		.final = safexcel_ahash_final,
22367a627db9SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22377a627db9SPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
22387a627db9SPascal van Leeuwen 		.setkey = safexcel_cmac_setkey,
22397a627db9SPascal van Leeuwen 		.export = safexcel_ahash_export,
22407a627db9SPascal van Leeuwen 		.import = safexcel_ahash_import,
22417a627db9SPascal van Leeuwen 		.halg = {
22427a627db9SPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
22437a627db9SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
22447a627db9SPascal van Leeuwen 			.base = {
22457a627db9SPascal van Leeuwen 				.cra_name = "cmac(aes)",
22467a627db9SPascal van Leeuwen 				.cra_driver_name = "safexcel-cmac-aes",
22477a627db9SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
22487a627db9SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2249b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
22507a627db9SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
22517a627db9SPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
22527a627db9SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
22537a627db9SPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
22547a627db9SPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
22557a627db9SPascal van Leeuwen 				.cra_module = THIS_MODULE,
22567a627db9SPascal van Leeuwen 			},
22577a627db9SPascal van Leeuwen 		},
22587a627db9SPascal van Leeuwen 	},
22597a627db9SPascal van Leeuwen };
22600f2bc131SPascal van Leeuwen 
22610f2bc131SPascal van Leeuwen static int safexcel_sm3_init(struct ahash_request *areq)
22620f2bc131SPascal van Leeuwen {
22630f2bc131SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
22640f2bc131SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
22650f2bc131SPascal van Leeuwen 
22660f2bc131SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
22670f2bc131SPascal van Leeuwen 
22680f2bc131SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
22690f2bc131SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
22700f2bc131SPascal van Leeuwen 	req->state_sz = SM3_DIGEST_SIZE;
22716c1c09b3SPascal van Leeuwen 	req->digest_sz = SM3_DIGEST_SIZE;
22720f2bc131SPascal van Leeuwen 	req->block_sz = SM3_BLOCK_SIZE;
22730f2bc131SPascal van Leeuwen 
22740f2bc131SPascal van Leeuwen 	return 0;
22750f2bc131SPascal van Leeuwen }
22760f2bc131SPascal van Leeuwen 
22770f2bc131SPascal van Leeuwen static int safexcel_sm3_digest(struct ahash_request *areq)
22780f2bc131SPascal van Leeuwen {
22790f2bc131SPascal van Leeuwen 	int ret = safexcel_sm3_init(areq);
22800f2bc131SPascal van Leeuwen 
22810f2bc131SPascal van Leeuwen 	if (ret)
22820f2bc131SPascal van Leeuwen 		return ret;
22830f2bc131SPascal van Leeuwen 
22840f2bc131SPascal van Leeuwen 	return safexcel_ahash_finup(areq);
22850f2bc131SPascal van Leeuwen }
22860f2bc131SPascal van Leeuwen 
22870f2bc131SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sm3 = {
22880f2bc131SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
22890f2bc131SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM3,
22900f2bc131SPascal van Leeuwen 	.alg.ahash = {
22910f2bc131SPascal van Leeuwen 		.init = safexcel_sm3_init,
22920f2bc131SPascal van Leeuwen 		.update = safexcel_ahash_update,
22930f2bc131SPascal van Leeuwen 		.final = safexcel_ahash_final,
22940f2bc131SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22950f2bc131SPascal van Leeuwen 		.digest = safexcel_sm3_digest,
22960f2bc131SPascal van Leeuwen 		.export = safexcel_ahash_export,
22970f2bc131SPascal van Leeuwen 		.import = safexcel_ahash_import,
22980f2bc131SPascal van Leeuwen 		.halg = {
22990f2bc131SPascal van Leeuwen 			.digestsize = SM3_DIGEST_SIZE,
23000f2bc131SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
23010f2bc131SPascal van Leeuwen 			.base = {
23020f2bc131SPascal van Leeuwen 				.cra_name = "sm3",
23030f2bc131SPascal van Leeuwen 				.cra_driver_name = "safexcel-sm3",
23040f2bc131SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
23050f2bc131SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2306b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
23070f2bc131SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
23080f2bc131SPascal van Leeuwen 				.cra_blocksize = SM3_BLOCK_SIZE,
23090f2bc131SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
23100f2bc131SPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
23110f2bc131SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
23120f2bc131SPascal van Leeuwen 				.cra_module = THIS_MODULE,
23130f2bc131SPascal van Leeuwen 			},
23140f2bc131SPascal van Leeuwen 		},
23150f2bc131SPascal van Leeuwen 	},
23160f2bc131SPascal van Leeuwen };
2317aa3a43e6SPascal van Leeuwen 
2318aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key,
2319aa3a43e6SPascal van Leeuwen 				    unsigned int keylen)
2320aa3a43e6SPascal van Leeuwen {
2321aa3a43e6SPascal van Leeuwen 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3",
2322aa3a43e6SPascal van Leeuwen 					SM3_DIGEST_SIZE);
2323aa3a43e6SPascal van Leeuwen }
2324aa3a43e6SPascal van Leeuwen 
2325aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_init(struct ahash_request *areq)
2326aa3a43e6SPascal van Leeuwen {
2327aa3a43e6SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
2328aa3a43e6SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2329aa3a43e6SPascal van Leeuwen 
2330aa3a43e6SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2331aa3a43e6SPascal van Leeuwen 
2332aa3a43e6SPascal van Leeuwen 	/* Start from ipad precompute */
2333aa3a43e6SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SM3_DIGEST_SIZE);
2334aa3a43e6SPascal van Leeuwen 	/* Already processed the key^ipad part now! */
2335aa3a43e6SPascal van Leeuwen 	req->len	= SM3_BLOCK_SIZE;
2336aa3a43e6SPascal van Leeuwen 	req->processed	= SM3_BLOCK_SIZE;
2337aa3a43e6SPascal van Leeuwen 
2338aa3a43e6SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
2339aa3a43e6SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
2340aa3a43e6SPascal van Leeuwen 	req->state_sz = SM3_DIGEST_SIZE;
23416c1c09b3SPascal van Leeuwen 	req->digest_sz = SM3_DIGEST_SIZE;
2342aa3a43e6SPascal van Leeuwen 	req->block_sz = SM3_BLOCK_SIZE;
2343aa3a43e6SPascal van Leeuwen 	req->hmac = true;
2344aa3a43e6SPascal van Leeuwen 
2345aa3a43e6SPascal van Leeuwen 	return 0;
2346aa3a43e6SPascal van Leeuwen }
2347aa3a43e6SPascal van Leeuwen 
2348aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_digest(struct ahash_request *areq)
2349aa3a43e6SPascal van Leeuwen {
2350aa3a43e6SPascal van Leeuwen 	int ret = safexcel_hmac_sm3_init(areq);
2351aa3a43e6SPascal van Leeuwen 
2352aa3a43e6SPascal van Leeuwen 	if (ret)
2353aa3a43e6SPascal van Leeuwen 		return ret;
2354aa3a43e6SPascal van Leeuwen 
2355aa3a43e6SPascal van Leeuwen 	return safexcel_ahash_finup(areq);
2356aa3a43e6SPascal van Leeuwen }
2357aa3a43e6SPascal van Leeuwen 
2358aa3a43e6SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sm3 = {
2359aa3a43e6SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2360aa3a43e6SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM3,
2361aa3a43e6SPascal van Leeuwen 	.alg.ahash = {
2362aa3a43e6SPascal van Leeuwen 		.init = safexcel_hmac_sm3_init,
2363aa3a43e6SPascal van Leeuwen 		.update = safexcel_ahash_update,
2364aa3a43e6SPascal van Leeuwen 		.final = safexcel_ahash_final,
2365aa3a43e6SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
2366aa3a43e6SPascal van Leeuwen 		.digest = safexcel_hmac_sm3_digest,
2367aa3a43e6SPascal van Leeuwen 		.setkey = safexcel_hmac_sm3_setkey,
2368aa3a43e6SPascal van Leeuwen 		.export = safexcel_ahash_export,
2369aa3a43e6SPascal van Leeuwen 		.import = safexcel_ahash_import,
2370aa3a43e6SPascal van Leeuwen 		.halg = {
2371aa3a43e6SPascal van Leeuwen 			.digestsize = SM3_DIGEST_SIZE,
2372aa3a43e6SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2373aa3a43e6SPascal van Leeuwen 			.base = {
2374aa3a43e6SPascal van Leeuwen 				.cra_name = "hmac(sm3)",
2375aa3a43e6SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sm3",
2376aa3a43e6SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2377aa3a43e6SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2378b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
2379aa3a43e6SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
2380aa3a43e6SPascal van Leeuwen 				.cra_blocksize = SM3_BLOCK_SIZE,
2381aa3a43e6SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2382aa3a43e6SPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
2383aa3a43e6SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
2384aa3a43e6SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2385aa3a43e6SPascal van Leeuwen 			},
2386aa3a43e6SPascal van Leeuwen 		},
2387aa3a43e6SPascal van Leeuwen 	},
2388aa3a43e6SPascal van Leeuwen };
2389aaf5a383SPascal van Leeuwen 
2390aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_init(struct ahash_request *areq)
2391aaf5a383SPascal van Leeuwen {
2392aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2393aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2394aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2395aaf5a383SPascal van Leeuwen 
2396aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2397aaf5a383SPascal van Leeuwen 
2398aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
2399aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2400aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_224_DIGEST_SIZE;
24016c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_224_DIGEST_SIZE;
2402aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_224_BLOCK_SIZE;
2403aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2404aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2405aaf5a383SPascal van Leeuwen 	return 0;
2406aaf5a383SPascal van Leeuwen }
2407aaf5a383SPascal van Leeuwen 
2408aaf5a383SPascal van Leeuwen static int safexcel_sha3_fbcheck(struct ahash_request *req)
2409aaf5a383SPascal van Leeuwen {
2410aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2411aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2412aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2413aaf5a383SPascal van Leeuwen 	int ret = 0;
2414aaf5a383SPascal van Leeuwen 
2415aaf5a383SPascal van Leeuwen 	if (ctx->do_fallback) {
2416aaf5a383SPascal van Leeuwen 		ahash_request_set_tfm(subreq, ctx->fback);
2417aaf5a383SPascal van Leeuwen 		ahash_request_set_callback(subreq, req->base.flags,
2418aaf5a383SPascal van Leeuwen 					   req->base.complete, req->base.data);
2419aaf5a383SPascal van Leeuwen 		ahash_request_set_crypt(subreq, req->src, req->result,
2420aaf5a383SPascal van Leeuwen 					req->nbytes);
2421aaf5a383SPascal van Leeuwen 		if (!ctx->fb_init_done) {
24226c1c09b3SPascal van Leeuwen 			if (ctx->fb_do_setkey) {
24236c1c09b3SPascal van Leeuwen 				/* Set fallback cipher HMAC key */
24246c1c09b3SPascal van Leeuwen 				u8 key[SHA3_224_BLOCK_SIZE];
24256c1c09b3SPascal van Leeuwen 
24266c1c09b3SPascal van Leeuwen 				memcpy(key, ctx->ipad,
24276c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2);
24286c1c09b3SPascal van Leeuwen 				memcpy(key +
24296c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2,
24306c1c09b3SPascal van Leeuwen 				       ctx->opad,
24316c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2);
24326c1c09b3SPascal van Leeuwen 				ret = crypto_ahash_setkey(ctx->fback, key,
24336c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(ctx->fback));
24346c1c09b3SPascal van Leeuwen 				memzero_explicit(key,
24356c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(ctx->fback));
24366c1c09b3SPascal van Leeuwen 				ctx->fb_do_setkey = false;
24376c1c09b3SPascal van Leeuwen 			}
24386c1c09b3SPascal van Leeuwen 			ret = ret ?: crypto_ahash_init(subreq);
2439aaf5a383SPascal van Leeuwen 			ctx->fb_init_done = true;
2440aaf5a383SPascal van Leeuwen 		}
2441aaf5a383SPascal van Leeuwen 	}
2442aaf5a383SPascal van Leeuwen 	return ret;
2443aaf5a383SPascal van Leeuwen }
2444aaf5a383SPascal van Leeuwen 
2445aaf5a383SPascal van Leeuwen static int safexcel_sha3_update(struct ahash_request *req)
2446aaf5a383SPascal van Leeuwen {
2447aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2448aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2449aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2450aaf5a383SPascal van Leeuwen 
2451aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2452aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq);
2453aaf5a383SPascal van Leeuwen }
2454aaf5a383SPascal van Leeuwen 
2455aaf5a383SPascal van Leeuwen static int safexcel_sha3_final(struct ahash_request *req)
2456aaf5a383SPascal van Leeuwen {
2457aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2458aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2459aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2460aaf5a383SPascal van Leeuwen 
2461aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2462aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq);
2463aaf5a383SPascal van Leeuwen }
2464aaf5a383SPascal van Leeuwen 
2465aaf5a383SPascal van Leeuwen static int safexcel_sha3_finup(struct ahash_request *req)
2466aaf5a383SPascal van Leeuwen {
2467aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2468aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2469aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2470aaf5a383SPascal van Leeuwen 
2471aaf5a383SPascal van Leeuwen 	ctx->do_fallback |= !req->nbytes;
2472aaf5a383SPascal van Leeuwen 	if (ctx->do_fallback)
2473aaf5a383SPascal van Leeuwen 		/* Update or ex/import happened or len 0, cannot use the HW */
2474aaf5a383SPascal van Leeuwen 		return safexcel_sha3_fbcheck(req) ?:
2475aaf5a383SPascal van Leeuwen 		       crypto_ahash_finup(subreq);
2476aaf5a383SPascal van Leeuwen 	else
2477aaf5a383SPascal van Leeuwen 		return safexcel_ahash_finup(req);
2478aaf5a383SPascal van Leeuwen }
2479aaf5a383SPascal van Leeuwen 
2480aaf5a383SPascal van Leeuwen static int safexcel_sha3_digest_fallback(struct ahash_request *req)
2481aaf5a383SPascal van Leeuwen {
2482aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2483aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2484aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2485aaf5a383SPascal van Leeuwen 
2486aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2487aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2488aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq);
2489aaf5a383SPascal van Leeuwen }
2490aaf5a383SPascal van Leeuwen 
2491aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_digest(struct ahash_request *req)
2492aaf5a383SPascal van Leeuwen {
2493aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2494aaf5a383SPascal van Leeuwen 		return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req);
2495aaf5a383SPascal van Leeuwen 
2496aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2497aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2498aaf5a383SPascal van Leeuwen }
2499aaf5a383SPascal van Leeuwen 
2500aaf5a383SPascal van Leeuwen static int safexcel_sha3_export(struct ahash_request *req, void *out)
2501aaf5a383SPascal van Leeuwen {
2502aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2503aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2504aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2505aaf5a383SPascal van Leeuwen 
2506aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2507aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out);
2508aaf5a383SPascal van Leeuwen }
2509aaf5a383SPascal van Leeuwen 
2510aaf5a383SPascal van Leeuwen static int safexcel_sha3_import(struct ahash_request *req, const void *in)
2511aaf5a383SPascal van Leeuwen {
2512aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2513aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2514aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2515aaf5a383SPascal van Leeuwen 
2516aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2517aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in);
2518aaf5a383SPascal van Leeuwen 	// return safexcel_ahash_import(req, in);
2519aaf5a383SPascal van Leeuwen }
2520aaf5a383SPascal van Leeuwen 
2521aaf5a383SPascal van Leeuwen static int safexcel_sha3_cra_init(struct crypto_tfm *tfm)
2522aaf5a383SPascal van Leeuwen {
2523aaf5a383SPascal van Leeuwen 	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
2524aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
2525aaf5a383SPascal van Leeuwen 
2526aaf5a383SPascal van Leeuwen 	safexcel_ahash_cra_init(tfm);
2527aaf5a383SPascal van Leeuwen 
2528aaf5a383SPascal van Leeuwen 	/* Allocate fallback implementation */
2529aaf5a383SPascal van Leeuwen 	ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0,
2530aaf5a383SPascal van Leeuwen 					CRYPTO_ALG_ASYNC |
2531aaf5a383SPascal van Leeuwen 					CRYPTO_ALG_NEED_FALLBACK);
2532aaf5a383SPascal van Leeuwen 	if (IS_ERR(ctx->fback))
2533aaf5a383SPascal van Leeuwen 		return PTR_ERR(ctx->fback);
2534aaf5a383SPascal van Leeuwen 
2535aaf5a383SPascal van Leeuwen 	/* Update statesize from fallback algorithm! */
2536aaf5a383SPascal van Leeuwen 	crypto_hash_alg_common(ahash)->statesize =
2537aaf5a383SPascal van Leeuwen 		crypto_ahash_statesize(ctx->fback);
2538aaf5a383SPascal van Leeuwen 	crypto_ahash_set_reqsize(ahash, max(sizeof(struct safexcel_ahash_req),
2539aaf5a383SPascal van Leeuwen 					    sizeof(struct ahash_request) +
2540aaf5a383SPascal van Leeuwen 					    crypto_ahash_reqsize(ctx->fback)));
2541aaf5a383SPascal van Leeuwen 	return 0;
2542aaf5a383SPascal van Leeuwen }
2543aaf5a383SPascal van Leeuwen 
2544aaf5a383SPascal van Leeuwen static void safexcel_sha3_cra_exit(struct crypto_tfm *tfm)
2545aaf5a383SPascal van Leeuwen {
2546aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
2547aaf5a383SPascal van Leeuwen 
2548aaf5a383SPascal van Leeuwen 	crypto_free_ahash(ctx->fback);
2549aaf5a383SPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
2550aaf5a383SPascal van Leeuwen }
2551aaf5a383SPascal van Leeuwen 
2552aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_224 = {
2553aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2554aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2555aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2556aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_224_init,
2557aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2558aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2559aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2560aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_224_digest,
2561aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2562aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2563aaf5a383SPascal van Leeuwen 		.halg = {
2564aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_224_DIGEST_SIZE,
2565aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2566aaf5a383SPascal van Leeuwen 			.base = {
2567aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-224",
2568aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-224",
2569aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2570aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2571aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2572aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2573aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_224_BLOCK_SIZE,
2574aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2575aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2576aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2577aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2578aaf5a383SPascal van Leeuwen 			},
2579aaf5a383SPascal van Leeuwen 		},
2580aaf5a383SPascal van Leeuwen 	},
2581aaf5a383SPascal van Leeuwen };
2582aaf5a383SPascal van Leeuwen 
2583aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_init(struct ahash_request *areq)
2584aaf5a383SPascal van Leeuwen {
2585aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2586aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2587aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2588aaf5a383SPascal van Leeuwen 
2589aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2590aaf5a383SPascal van Leeuwen 
2591aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
2592aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2593aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_256_DIGEST_SIZE;
25946c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_256_DIGEST_SIZE;
2595aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_256_BLOCK_SIZE;
2596aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2597aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2598aaf5a383SPascal van Leeuwen 	return 0;
2599aaf5a383SPascal van Leeuwen }
2600aaf5a383SPascal van Leeuwen 
2601aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_digest(struct ahash_request *req)
2602aaf5a383SPascal van Leeuwen {
2603aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2604aaf5a383SPascal van Leeuwen 		return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req);
2605aaf5a383SPascal van Leeuwen 
2606aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2607aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2608aaf5a383SPascal van Leeuwen }
2609aaf5a383SPascal van Leeuwen 
2610aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_256 = {
2611aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2612aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2613aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2614aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_256_init,
2615aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2616aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2617aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2618aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_256_digest,
2619aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2620aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2621aaf5a383SPascal van Leeuwen 		.halg = {
2622aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_256_DIGEST_SIZE,
2623aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2624aaf5a383SPascal van Leeuwen 			.base = {
2625aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-256",
2626aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-256",
2627aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2628aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2629aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2630aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2631aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_256_BLOCK_SIZE,
2632aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2633aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2634aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2635aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2636aaf5a383SPascal van Leeuwen 			},
2637aaf5a383SPascal van Leeuwen 		},
2638aaf5a383SPascal van Leeuwen 	},
2639aaf5a383SPascal van Leeuwen };
2640aaf5a383SPascal van Leeuwen 
2641aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_init(struct ahash_request *areq)
2642aaf5a383SPascal van Leeuwen {
2643aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2644aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2645aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2646aaf5a383SPascal van Leeuwen 
2647aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2648aaf5a383SPascal van Leeuwen 
2649aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
2650aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2651aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_384_DIGEST_SIZE;
26526c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_384_DIGEST_SIZE;
2653aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_384_BLOCK_SIZE;
2654aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2655aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2656aaf5a383SPascal van Leeuwen 	return 0;
2657aaf5a383SPascal van Leeuwen }
2658aaf5a383SPascal van Leeuwen 
2659aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_digest(struct ahash_request *req)
2660aaf5a383SPascal van Leeuwen {
2661aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2662aaf5a383SPascal van Leeuwen 		return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req);
2663aaf5a383SPascal van Leeuwen 
2664aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2665aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2666aaf5a383SPascal van Leeuwen }
2667aaf5a383SPascal van Leeuwen 
2668aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_384 = {
2669aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2670aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2671aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2672aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_384_init,
2673aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2674aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2675aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2676aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_384_digest,
2677aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2678aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2679aaf5a383SPascal van Leeuwen 		.halg = {
2680aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_384_DIGEST_SIZE,
2681aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2682aaf5a383SPascal van Leeuwen 			.base = {
2683aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-384",
2684aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-384",
2685aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2686aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2687aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2688aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2689aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_384_BLOCK_SIZE,
2690aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2691aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2692aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2693aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2694aaf5a383SPascal van Leeuwen 			},
2695aaf5a383SPascal van Leeuwen 		},
2696aaf5a383SPascal van Leeuwen 	},
2697aaf5a383SPascal van Leeuwen };
2698aaf5a383SPascal van Leeuwen 
2699aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_init(struct ahash_request *areq)
2700aaf5a383SPascal van Leeuwen {
2701aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2702aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2703aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2704aaf5a383SPascal van Leeuwen 
2705aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2706aaf5a383SPascal van Leeuwen 
2707aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
2708aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2709aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_512_DIGEST_SIZE;
27106c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_512_DIGEST_SIZE;
2711aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_512_BLOCK_SIZE;
2712aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2713aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2714aaf5a383SPascal van Leeuwen 	return 0;
2715aaf5a383SPascal van Leeuwen }
2716aaf5a383SPascal van Leeuwen 
2717aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_digest(struct ahash_request *req)
2718aaf5a383SPascal van Leeuwen {
2719aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2720aaf5a383SPascal van Leeuwen 		return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req);
2721aaf5a383SPascal van Leeuwen 
2722aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2723aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2724aaf5a383SPascal van Leeuwen }
2725aaf5a383SPascal van Leeuwen 
2726aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_512 = {
2727aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2728aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2729aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2730aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_512_init,
2731aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2732aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2733aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2734aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_512_digest,
2735aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2736aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2737aaf5a383SPascal van Leeuwen 		.halg = {
2738aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_512_DIGEST_SIZE,
2739aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2740aaf5a383SPascal van Leeuwen 			.base = {
2741aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-512",
2742aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-512",
2743aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2744aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2745aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2746aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2747aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_512_BLOCK_SIZE,
2748aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2749aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2750aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2751aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2752aaf5a383SPascal van Leeuwen 			},
2753aaf5a383SPascal van Leeuwen 		},
2754aaf5a383SPascal van Leeuwen 	},
2755aaf5a383SPascal van Leeuwen };
27566c1c09b3SPascal van Leeuwen 
27576c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg)
27586c1c09b3SPascal van Leeuwen {
27596c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
27606c1c09b3SPascal van Leeuwen 	int ret;
27616c1c09b3SPascal van Leeuwen 
27626c1c09b3SPascal van Leeuwen 	ret = safexcel_sha3_cra_init(tfm);
27636c1c09b3SPascal van Leeuwen 	if (ret)
27646c1c09b3SPascal van Leeuwen 		return ret;
27656c1c09b3SPascal van Leeuwen 
27666c1c09b3SPascal van Leeuwen 	/* Allocate precalc basic digest implementation */
27676c1c09b3SPascal van Leeuwen 	ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
27686c1c09b3SPascal van Leeuwen 	if (IS_ERR(ctx->shpre))
27696c1c09b3SPascal van Leeuwen 		return PTR_ERR(ctx->shpre);
27706c1c09b3SPascal van Leeuwen 
27716c1c09b3SPascal van Leeuwen 	ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) +
27726c1c09b3SPascal van Leeuwen 			      crypto_shash_descsize(ctx->shpre), GFP_KERNEL);
27736c1c09b3SPascal van Leeuwen 	if (!ctx->shdesc) {
27746c1c09b3SPascal van Leeuwen 		crypto_free_shash(ctx->shpre);
27756c1c09b3SPascal van Leeuwen 		return -ENOMEM;
27766c1c09b3SPascal van Leeuwen 	}
27776c1c09b3SPascal van Leeuwen 	ctx->shdesc->tfm = ctx->shpre;
27786c1c09b3SPascal van Leeuwen 	return 0;
27796c1c09b3SPascal van Leeuwen }
27806c1c09b3SPascal van Leeuwen 
27816c1c09b3SPascal van Leeuwen static void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm)
27826c1c09b3SPascal van Leeuwen {
27836c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
27846c1c09b3SPascal van Leeuwen 
27856c1c09b3SPascal van Leeuwen 	crypto_free_ahash(ctx->fback);
27866c1c09b3SPascal van Leeuwen 	crypto_free_shash(ctx->shpre);
27876c1c09b3SPascal van Leeuwen 	kfree(ctx->shdesc);
27886c1c09b3SPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
27896c1c09b3SPascal van Leeuwen }
27906c1c09b3SPascal van Leeuwen 
27916c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key,
27926c1c09b3SPascal van Leeuwen 				     unsigned int keylen)
27936c1c09b3SPascal van Leeuwen {
27946c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
27956c1c09b3SPascal van Leeuwen 	int ret = 0;
27966c1c09b3SPascal van Leeuwen 
27976c1c09b3SPascal van Leeuwen 	if (keylen > crypto_ahash_blocksize(tfm)) {
27986c1c09b3SPascal van Leeuwen 		/*
27996c1c09b3SPascal van Leeuwen 		 * If the key is larger than the blocksize, then hash it
28006c1c09b3SPascal van Leeuwen 		 * first using our fallback cipher
28016c1c09b3SPascal van Leeuwen 		 */
28026c1c09b3SPascal van Leeuwen 		ret = crypto_shash_digest(ctx->shdesc, key, keylen,
28036c1c09b3SPascal van Leeuwen 					  (u8 *)ctx->ipad);
28046c1c09b3SPascal van Leeuwen 		keylen = crypto_shash_digestsize(ctx->shpre);
28056c1c09b3SPascal van Leeuwen 
28066c1c09b3SPascal van Leeuwen 		/*
28076c1c09b3SPascal van Leeuwen 		 * If the digest is larger than half the blocksize, we need to
28086c1c09b3SPascal van Leeuwen 		 * move the rest to opad due to the way our HMAC infra works.
28096c1c09b3SPascal van Leeuwen 		 */
28106c1c09b3SPascal van Leeuwen 		if (keylen > crypto_ahash_blocksize(tfm) / 2)
28116c1c09b3SPascal van Leeuwen 			/* Buffers overlap, need to use memmove iso memcpy! */
28126c1c09b3SPascal van Leeuwen 			memmove(ctx->opad,
28136c1c09b3SPascal van Leeuwen 				(u8 *)ctx->ipad +
28146c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(tfm) / 2,
28156c1c09b3SPascal van Leeuwen 				keylen - crypto_ahash_blocksize(tfm) / 2);
28166c1c09b3SPascal van Leeuwen 	} else {
28176c1c09b3SPascal van Leeuwen 		/*
28186c1c09b3SPascal van Leeuwen 		 * Copy the key to our ipad & opad buffers
28196c1c09b3SPascal van Leeuwen 		 * Note that ipad and opad each contain one half of the key,
28206c1c09b3SPascal van Leeuwen 		 * to match the existing HMAC driver infrastructure.
28216c1c09b3SPascal van Leeuwen 		 */
28226c1c09b3SPascal van Leeuwen 		if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
28236c1c09b3SPascal van Leeuwen 			memcpy(ctx->ipad, key, keylen);
28246c1c09b3SPascal van Leeuwen 		} else {
28256c1c09b3SPascal van Leeuwen 			memcpy(ctx->ipad, key,
28266c1c09b3SPascal van Leeuwen 			       crypto_ahash_blocksize(tfm) / 2);
28276c1c09b3SPascal van Leeuwen 			memcpy(ctx->opad,
28286c1c09b3SPascal van Leeuwen 			       key + crypto_ahash_blocksize(tfm) / 2,
28296c1c09b3SPascal van Leeuwen 			       keylen - crypto_ahash_blocksize(tfm) / 2);
28306c1c09b3SPascal van Leeuwen 		}
28316c1c09b3SPascal van Leeuwen 	}
28326c1c09b3SPascal van Leeuwen 
28336c1c09b3SPascal van Leeuwen 	/* Pad key with zeroes */
28346c1c09b3SPascal van Leeuwen 	if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
28356c1c09b3SPascal van Leeuwen 		memset((u8 *)ctx->ipad + keylen, 0,
28366c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) / 2 - keylen);
28376c1c09b3SPascal van Leeuwen 		memset(ctx->opad, 0, crypto_ahash_blocksize(tfm) / 2);
28386c1c09b3SPascal van Leeuwen 	} else {
28396c1c09b3SPascal van Leeuwen 		memset((u8 *)ctx->opad + keylen -
28406c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) / 2, 0,
28416c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) - keylen);
28426c1c09b3SPascal van Leeuwen 	}
28436c1c09b3SPascal van Leeuwen 
28446c1c09b3SPascal van Leeuwen 	/* If doing fallback, still need to set the new key! */
28456c1c09b3SPascal van Leeuwen 	ctx->fb_do_setkey = true;
28466c1c09b3SPascal van Leeuwen 	return ret;
28476c1c09b3SPascal van Leeuwen }
28486c1c09b3SPascal van Leeuwen 
28496c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_init(struct ahash_request *areq)
28506c1c09b3SPascal van Leeuwen {
28516c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
28526c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
28536c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
28546c1c09b3SPascal van Leeuwen 
28556c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
28566c1c09b3SPascal van Leeuwen 
28576c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
28586c1c09b3SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA3_224_BLOCK_SIZE / 2);
28596c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
28606c1c09b3SPascal van Leeuwen 	req->len	= SHA3_224_BLOCK_SIZE;
28616c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_224_BLOCK_SIZE;
28626c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
28636c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
28646c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_224_BLOCK_SIZE / 2;
28656c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_224_DIGEST_SIZE;
28666c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_224_BLOCK_SIZE;
28676c1c09b3SPascal van Leeuwen 	req->hmac = true;
28686c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
28696c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
28706c1c09b3SPascal van Leeuwen 	return 0;
28716c1c09b3SPascal van Leeuwen }
28726c1c09b3SPascal van Leeuwen 
28736c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_digest(struct ahash_request *req)
28746c1c09b3SPascal van Leeuwen {
28756c1c09b3SPascal van Leeuwen 	if (req->nbytes)
28766c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_224_init(req) ?:
28776c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
28786c1c09b3SPascal van Leeuwen 
28796c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
28806c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
28816c1c09b3SPascal van Leeuwen }
28826c1c09b3SPascal van Leeuwen 
28836c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm)
28846c1c09b3SPascal van Leeuwen {
28856c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-224");
28866c1c09b3SPascal van Leeuwen }
28876c1c09b3SPascal van Leeuwen 
28886c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_224 = {
28896c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
28906c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
28916c1c09b3SPascal van Leeuwen 	.alg.ahash = {
28926c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_224_init,
28936c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
28946c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
28956c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
28966c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_224_digest,
28976c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
28986c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
28996c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
29006c1c09b3SPascal van Leeuwen 		.halg = {
29016c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_224_DIGEST_SIZE,
29026c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
29036c1c09b3SPascal van Leeuwen 			.base = {
29046c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-224)",
29056c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-224",
29066c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
29076c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
29086c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
29096c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
29106c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_224_BLOCK_SIZE,
29116c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
29126c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_224_cra_init,
29136c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
29146c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
29156c1c09b3SPascal van Leeuwen 			},
29166c1c09b3SPascal van Leeuwen 		},
29176c1c09b3SPascal van Leeuwen 	},
29186c1c09b3SPascal van Leeuwen };
29196c1c09b3SPascal van Leeuwen 
29206c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_init(struct ahash_request *areq)
29216c1c09b3SPascal van Leeuwen {
29226c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
29236c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
29246c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
29256c1c09b3SPascal van Leeuwen 
29266c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
29276c1c09b3SPascal van Leeuwen 
29286c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
29296c1c09b3SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA3_256_BLOCK_SIZE / 2);
29306c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
29316c1c09b3SPascal van Leeuwen 	req->len	= SHA3_256_BLOCK_SIZE;
29326c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_256_BLOCK_SIZE;
29336c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
29346c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
29356c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_256_BLOCK_SIZE / 2;
29366c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_256_DIGEST_SIZE;
29376c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_256_BLOCK_SIZE;
29386c1c09b3SPascal van Leeuwen 	req->hmac = true;
29396c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
29406c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
29416c1c09b3SPascal van Leeuwen 	return 0;
29426c1c09b3SPascal van Leeuwen }
29436c1c09b3SPascal van Leeuwen 
29446c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_digest(struct ahash_request *req)
29456c1c09b3SPascal van Leeuwen {
29466c1c09b3SPascal van Leeuwen 	if (req->nbytes)
29476c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_256_init(req) ?:
29486c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
29496c1c09b3SPascal van Leeuwen 
29506c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
29516c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
29526c1c09b3SPascal van Leeuwen }
29536c1c09b3SPascal van Leeuwen 
29546c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm)
29556c1c09b3SPascal van Leeuwen {
29566c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-256");
29576c1c09b3SPascal van Leeuwen }
29586c1c09b3SPascal van Leeuwen 
29596c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_256 = {
29606c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
29616c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
29626c1c09b3SPascal van Leeuwen 	.alg.ahash = {
29636c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_256_init,
29646c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
29656c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
29666c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
29676c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_256_digest,
29686c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
29696c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
29706c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
29716c1c09b3SPascal van Leeuwen 		.halg = {
29726c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_256_DIGEST_SIZE,
29736c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
29746c1c09b3SPascal van Leeuwen 			.base = {
29756c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-256)",
29766c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-256",
29776c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
29786c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
29796c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
29806c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
29816c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_256_BLOCK_SIZE,
29826c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
29836c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_256_cra_init,
29846c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
29856c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
29866c1c09b3SPascal van Leeuwen 			},
29876c1c09b3SPascal van Leeuwen 		},
29886c1c09b3SPascal van Leeuwen 	},
29896c1c09b3SPascal van Leeuwen };
29906c1c09b3SPascal van Leeuwen 
29916c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_init(struct ahash_request *areq)
29926c1c09b3SPascal van Leeuwen {
29936c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
29946c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
29956c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
29966c1c09b3SPascal van Leeuwen 
29976c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
29986c1c09b3SPascal van Leeuwen 
29996c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
30006c1c09b3SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA3_384_BLOCK_SIZE / 2);
30016c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
30026c1c09b3SPascal van Leeuwen 	req->len	= SHA3_384_BLOCK_SIZE;
30036c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_384_BLOCK_SIZE;
30046c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
30056c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
30066c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_384_BLOCK_SIZE / 2;
30076c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_384_DIGEST_SIZE;
30086c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_384_BLOCK_SIZE;
30096c1c09b3SPascal van Leeuwen 	req->hmac = true;
30106c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
30116c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
30126c1c09b3SPascal van Leeuwen 	return 0;
30136c1c09b3SPascal van Leeuwen }
30146c1c09b3SPascal van Leeuwen 
30156c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_digest(struct ahash_request *req)
30166c1c09b3SPascal van Leeuwen {
30176c1c09b3SPascal van Leeuwen 	if (req->nbytes)
30186c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_384_init(req) ?:
30196c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
30206c1c09b3SPascal van Leeuwen 
30216c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
30226c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
30236c1c09b3SPascal van Leeuwen }
30246c1c09b3SPascal van Leeuwen 
30256c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm)
30266c1c09b3SPascal van Leeuwen {
30276c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-384");
30286c1c09b3SPascal van Leeuwen }
30296c1c09b3SPascal van Leeuwen 
30306c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_384 = {
30316c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
30326c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
30336c1c09b3SPascal van Leeuwen 	.alg.ahash = {
30346c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_384_init,
30356c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
30366c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
30376c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
30386c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_384_digest,
30396c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
30406c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
30416c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
30426c1c09b3SPascal van Leeuwen 		.halg = {
30436c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_384_DIGEST_SIZE,
30446c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
30456c1c09b3SPascal van Leeuwen 			.base = {
30466c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-384)",
30476c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-384",
30486c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
30496c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
30506c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
30516c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
30526c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_384_BLOCK_SIZE,
30536c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
30546c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_384_cra_init,
30556c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
30566c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
30576c1c09b3SPascal van Leeuwen 			},
30586c1c09b3SPascal van Leeuwen 		},
30596c1c09b3SPascal van Leeuwen 	},
30606c1c09b3SPascal van Leeuwen };
30616c1c09b3SPascal van Leeuwen 
30626c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_init(struct ahash_request *areq)
30636c1c09b3SPascal van Leeuwen {
30646c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
30656c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
30666c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
30676c1c09b3SPascal van Leeuwen 
30686c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
30696c1c09b3SPascal van Leeuwen 
30706c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
30716c1c09b3SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA3_512_BLOCK_SIZE / 2);
30726c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
30736c1c09b3SPascal van Leeuwen 	req->len	= SHA3_512_BLOCK_SIZE;
30746c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_512_BLOCK_SIZE;
30756c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
30766c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
30776c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_512_BLOCK_SIZE / 2;
30786c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_512_DIGEST_SIZE;
30796c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_512_BLOCK_SIZE;
30806c1c09b3SPascal van Leeuwen 	req->hmac = true;
30816c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
30826c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
30836c1c09b3SPascal van Leeuwen 	return 0;
30846c1c09b3SPascal van Leeuwen }
30856c1c09b3SPascal van Leeuwen 
30866c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_digest(struct ahash_request *req)
30876c1c09b3SPascal van Leeuwen {
30886c1c09b3SPascal van Leeuwen 	if (req->nbytes)
30896c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_512_init(req) ?:
30906c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
30916c1c09b3SPascal van Leeuwen 
30926c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
30936c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
30946c1c09b3SPascal van Leeuwen }
30956c1c09b3SPascal van Leeuwen 
30966c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm)
30976c1c09b3SPascal van Leeuwen {
30986c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-512");
30996c1c09b3SPascal van Leeuwen }
31006c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_512 = {
31016c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
31026c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
31036c1c09b3SPascal van Leeuwen 	.alg.ahash = {
31046c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_512_init,
31056c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
31066c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
31076c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
31086c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_512_digest,
31096c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
31106c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
31116c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
31126c1c09b3SPascal van Leeuwen 		.halg = {
31136c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_512_DIGEST_SIZE,
31146c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
31156c1c09b3SPascal van Leeuwen 			.base = {
31166c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-512)",
31176c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-512",
31186c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
31196c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
31206c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
31216c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
31226c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_512_BLOCK_SIZE,
31236c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
31246c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_512_cra_init,
31256c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
31266c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
31276c1c09b3SPascal van Leeuwen 			},
31286c1c09b3SPascal van Leeuwen 		},
31296c1c09b3SPascal van Leeuwen 	},
31306c1c09b3SPascal van Leeuwen };
3131