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 
241b44c5a6SAntoine Ténart 	u32 alg;
25b98687bbSPascal van Leeuwen 	u8  key_sz;
2638f21b4bSPascal van Leeuwen 	bool cbcmac;
27aaf5a383SPascal van Leeuwen 	bool do_fallback;
28aaf5a383SPascal van Leeuwen 	bool fb_init_done;
296c1c09b3SPascal van Leeuwen 	bool fb_do_setkey;
301b44c5a6SAntoine Ténart 
3113a1bb93SPascal van Leeuwen 	__le32 ipad[SHA3_512_BLOCK_SIZE / sizeof(__le32)];
3213a1bb93SPascal van Leeuwen 	__le32 opad[SHA3_512_BLOCK_SIZE / sizeof(__le32)];
3338f21b4bSPascal van Leeuwen 
3438f21b4bSPascal van Leeuwen 	struct crypto_cipher *kaes;
35aaf5a383SPascal van Leeuwen 	struct crypto_ahash *fback;
366c1c09b3SPascal van Leeuwen 	struct crypto_shash *shpre;
376c1c09b3SPascal van Leeuwen 	struct shash_desc *shdesc;
381b44c5a6SAntoine Ténart };
391b44c5a6SAntoine Ténart 
401b44c5a6SAntoine Ténart struct safexcel_ahash_req {
411b44c5a6SAntoine Ténart 	bool last_req;
421b44c5a6SAntoine Ténart 	bool finish;
431b44c5a6SAntoine Ténart 	bool hmac;
441eb7b403SOfer Heifetz 	bool needs_inv;
4585b36ee8SPascal van Leeuwen 	bool hmac_zlen;
4685b36ee8SPascal van Leeuwen 	bool len_is_le;
47b98687bbSPascal van Leeuwen 	bool not_first;
48b98687bbSPascal van Leeuwen 	bool xcbcmac;
491b44c5a6SAntoine Ténart 
50c957f8b3SAntoine Ténart 	int nents;
51b8592027SOfer Heifetz 	dma_addr_t result_dma;
52c957f8b3SAntoine Ténart 
53b869648cSAntoine Tenart 	u32 digest;
54b869648cSAntoine Tenart 
5541abed7dSPascal van Leeuwen 	u8 state_sz;    /* expected state size, only set once */
5641abed7dSPascal van Leeuwen 	u8 block_sz;    /* block size, only set once */
576c1c09b3SPascal van Leeuwen 	u8 digest_sz;   /* output digest size, only set once */
5813a1bb93SPascal van Leeuwen 	__le32 state[SHA3_512_BLOCK_SIZE /
5913a1bb93SPascal van Leeuwen 		     sizeof(__le32)] __aligned(sizeof(__le32));
601b44c5a6SAntoine Ténart 
6131fb084cSPascal van Leeuwen 	u64 len;
6231fb084cSPascal van Leeuwen 	u64 processed;
631b44c5a6SAntoine Ténart 
6441abed7dSPascal van Leeuwen 	u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32));
65cff9a175SAntoine Tenart 	dma_addr_t cache_dma;
66cff9a175SAntoine Tenart 	unsigned int cache_sz;
67cff9a175SAntoine Tenart 
6841abed7dSPascal van Leeuwen 	u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32));
691b44c5a6SAntoine Ténart };
701b44c5a6SAntoine Ténart 
71b460edb6SAntoine Tenart static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req)
72b460edb6SAntoine Tenart {
7331fb084cSPascal van Leeuwen 	return req->len - req->processed;
74b460edb6SAntoine Tenart }
75b460edb6SAntoine Tenart 
761b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc,
77b98687bbSPascal van Leeuwen 				u32 input_length, u32 result_length,
7838f21b4bSPascal van Leeuwen 				bool cbcmac)
791b44c5a6SAntoine Ténart {
801b44c5a6SAntoine Ténart 	struct safexcel_token *token =
811b44c5a6SAntoine Ténart 		(struct safexcel_token *)cdesc->control_data.token;
821b44c5a6SAntoine Ténart 
831b44c5a6SAntoine Ténart 	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
841b44c5a6SAntoine Ténart 	token[0].packet_length = input_length;
851b44c5a6SAntoine Ténart 	token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH;
861b44c5a6SAntoine Ténart 
87b98687bbSPascal van Leeuwen 	input_length &= 15;
8838f21b4bSPascal van Leeuwen 	if (unlikely(cbcmac && input_length)) {
89098e51e5SPascal van Leeuwen 		token[0].stat =  0;
901b44c5a6SAntoine Ténart 		token[1].opcode = EIP197_TOKEN_OPCODE_INSERT;
91b98687bbSPascal van Leeuwen 		token[1].packet_length = 16 - input_length;
92b98687bbSPascal van Leeuwen 		token[1].stat = EIP197_TOKEN_STAT_LAST_HASH;
93b98687bbSPascal van Leeuwen 		token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH;
94b98687bbSPascal van Leeuwen 	} else {
95b98687bbSPascal van Leeuwen 		token[0].stat = EIP197_TOKEN_STAT_LAST_HASH;
96098e51e5SPascal van Leeuwen 		eip197_noop_token(&token[1]);
97b98687bbSPascal van Leeuwen 	}
98b98687bbSPascal van Leeuwen 
99b98687bbSPascal van Leeuwen 	token[2].opcode = EIP197_TOKEN_OPCODE_INSERT;
100b98687bbSPascal van Leeuwen 	token[2].stat = EIP197_TOKEN_STAT_LAST_HASH |
1011b44c5a6SAntoine Ténart 			EIP197_TOKEN_STAT_LAST_PACKET;
102b98687bbSPascal van Leeuwen 	token[2].packet_length = result_length;
103b98687bbSPascal van Leeuwen 	token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
1041b44c5a6SAntoine Ténart 				EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
105098e51e5SPascal van Leeuwen 
106098e51e5SPascal van Leeuwen 	eip197_noop_token(&token[3]);
1071b44c5a6SAntoine Ténart }
1081b44c5a6SAntoine Ténart 
1091b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx,
1101b44c5a6SAntoine Ténart 				     struct safexcel_ahash_req *req,
11141abed7dSPascal van Leeuwen 				     struct safexcel_command_desc *cdesc)
1121b44c5a6SAntoine Ténart {
11318e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
11441abed7dSPascal van Leeuwen 	u64 count = 0;
1151b44c5a6SAntoine Ténart 
116a7cf8658SPascal van Leeuwen 	cdesc->control_data.control0 = ctx->alg;
117098e51e5SPascal van Leeuwen 	cdesc->control_data.control1 = 0;
118dc5268b6SPascal van Leeuwen 
1191b44c5a6SAntoine Ténart 	/*
1201b44c5a6SAntoine Ténart 	 * Copy the input digest if needed, and setup the context
1211b44c5a6SAntoine Ténart 	 * fields. Do this now as we need it to setup the first command
1221b44c5a6SAntoine Ténart 	 * descriptor.
1231b44c5a6SAntoine Ténart 	 */
124a7cf8658SPascal van Leeuwen 	if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) {
125b98687bbSPascal van Leeuwen 		if (req->xcbcmac)
126b98687bbSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data, ctx->ipad, ctx->key_sz);
127b98687bbSPascal van Leeuwen 		else
128b98687bbSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
129a7cf8658SPascal van Leeuwen 
130b98687bbSPascal van Leeuwen 		if (!req->finish && req->xcbcmac)
131b98687bbSPascal van Leeuwen 			cdesc->control_data.control0 |=
132b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
133a7cf8658SPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
134b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_NO_FINISH_HASH |
135b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz /
136b98687bbSPascal van Leeuwen 						     sizeof(u32));
137b98687bbSPascal van Leeuwen 		else
138b98687bbSPascal van Leeuwen 			cdesc->control_data.control0 |=
139b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
140b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
141b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz /
142b98687bbSPascal van Leeuwen 						     sizeof(u32));
143a7cf8658SPascal van Leeuwen 		return;
144a7cf8658SPascal van Leeuwen 	} else if (!req->processed) {
14541abed7dSPascal van Leeuwen 		/* First - and possibly only - block of basic hash only */
146b98687bbSPascal van Leeuwen 		if (req->finish)
147a7cf8658SPascal van Leeuwen 			cdesc->control_data.control0 |= req->digest |
14841abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
14941abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH  |
15041abed7dSPascal van Leeuwen 				/* ensure its not 0! */
15141abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
152b98687bbSPascal van Leeuwen 		else
153a7cf8658SPascal van Leeuwen 			cdesc->control_data.control0 |= req->digest |
15441abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
15541abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH   |
15641abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_NO_FINISH_HASH |
15741abed7dSPascal van Leeuwen 				/* ensure its not 0! */
15841abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
15941abed7dSPascal van Leeuwen 		return;
16041abed7dSPascal van Leeuwen 	}
16141abed7dSPascal van Leeuwen 
16241abed7dSPascal van Leeuwen 	/* Hash continuation or HMAC, setup (inner) digest from state */
16341abed7dSPascal van Leeuwen 	memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
1641b44c5a6SAntoine Ténart 
165b460edb6SAntoine Tenart 	if (req->finish) {
16641abed7dSPascal van Leeuwen 		/* Compute digest count for hash/HMAC finish operations */
16741abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
16831fb084cSPascal van Leeuwen 		    req->hmac_zlen || (req->processed != req->block_sz)) {
16931fb084cSPascal van Leeuwen 			count = req->processed / EIP197_COUNTER_BLOCK_SIZE;
170b460edb6SAntoine Tenart 
17141abed7dSPascal van Leeuwen 			/* This is a hardware limitation, as the
172b460edb6SAntoine Tenart 			 * counter must fit into an u32. This represents
17341abed7dSPascal van Leeuwen 			 * a fairly big amount of input data, so we
174b460edb6SAntoine Tenart 			 * shouldn't see this.
175b460edb6SAntoine Tenart 			 */
17641abed7dSPascal van Leeuwen 			if (unlikely(count & 0xffffffff00000000ULL)) {
177b460edb6SAntoine Tenart 				dev_warn(priv->dev,
178b460edb6SAntoine Tenart 					 "Input data is too big\n");
179b460edb6SAntoine Tenart 				return;
180b460edb6SAntoine Tenart 			}
181b460edb6SAntoine Tenart 		}
1821b44c5a6SAntoine Ténart 
18341abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
18485b36ee8SPascal van Leeuwen 		    /* Special case: zero length HMAC */
18585b36ee8SPascal van Leeuwen 		    req->hmac_zlen ||
18641abed7dSPascal van Leeuwen 		    /* PE HW < 4.4 cannot do HMAC continue, fake using hash */
18731fb084cSPascal van Leeuwen 		    (req->processed != req->block_sz)) {
18841abed7dSPascal van Leeuwen 			/* Basic hash continue operation, need digest + cnt */
18941abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
19041abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) |
19141abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
19241abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
19385b36ee8SPascal van Leeuwen 			/* For zero-len HMAC, don't finalize, already padded! */
19485b36ee8SPascal van Leeuwen 			if (req->hmac_zlen)
19585b36ee8SPascal van Leeuwen 				cdesc->control_data.control0 |=
19685b36ee8SPascal van Leeuwen 					CONTEXT_CONTROL_NO_FINISH_HASH;
19741abed7dSPascal van Leeuwen 			cdesc->control_data.control1 |=
19841abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_CNT;
19941abed7dSPascal van Leeuwen 			ctx->base.ctxr->data[req->state_sz >> 2] =
20041abed7dSPascal van Leeuwen 				cpu_to_le32(count);
20141abed7dSPascal van Leeuwen 			req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
20285b36ee8SPascal van Leeuwen 
20385b36ee8SPascal van Leeuwen 			/* Clear zero-length HMAC flag for next operation! */
20485b36ee8SPascal van Leeuwen 			req->hmac_zlen = false;
20541abed7dSPascal van Leeuwen 		} else { /* HMAC */
20641abed7dSPascal van Leeuwen 			/* Need outer digest for HMAC finalization */
20741abed7dSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (req->state_sz >> 2),
2084505bb02SAntoine Tenart 			       ctx->opad, req->state_sz);
20941abed7dSPascal van Leeuwen 
21041abed7dSPascal van Leeuwen 			/* Single pass HMAC - no digest count */
21141abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
21241abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz >> 1) |
21341abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
21441abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_HMAC;
21541abed7dSPascal van Leeuwen 		}
21641abed7dSPascal van Leeuwen 	} else { /* Hash continuation, do not finish yet */
21741abed7dSPascal van Leeuwen 		cdesc->control_data.control0 |=
21841abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_SIZE(req->state_sz >> 2) |
21941abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_DIGEST_PRECOMPUTED |
22041abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_TYPE_HASH_OUT |
22141abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_NO_FINISH_HASH;
2221b44c5a6SAntoine Ténart 	}
2231b44c5a6SAntoine Ténart }
2241b44c5a6SAntoine Ténart 
22541abed7dSPascal van Leeuwen static int safexcel_ahash_enqueue(struct ahash_request *areq);
22641abed7dSPascal van Leeuwen 
22741abed7dSPascal van Leeuwen static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv,
22841abed7dSPascal van Leeuwen 				      int ring,
2291b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
2301b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
2311b44c5a6SAntoine Ténart {
2321b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
2331b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
2341b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2351b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *sreq = ahash_request_ctx(areq);
23641abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
237b460edb6SAntoine Tenart 	u64 cache_len;
2381b44c5a6SAntoine Ténart 
2391b44c5a6SAntoine Ténart 	*ret = 0;
2401b44c5a6SAntoine Ténart 
2411b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
2421b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
2431b44c5a6SAntoine Ténart 		dev_err(priv->dev,
2441b44c5a6SAntoine Ténart 			"hash: result: could not retrieve the result descriptor\n");
2451b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
246bdfd1909SAntoine Tenart 	} else {
247bdfd1909SAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
2481b44c5a6SAntoine Ténart 	}
2491b44c5a6SAntoine Ténart 
2501b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
2511b44c5a6SAntoine Ténart 
252c957f8b3SAntoine Ténart 	if (sreq->nents) {
253c957f8b3SAntoine Ténart 		dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE);
254c957f8b3SAntoine Ténart 		sreq->nents = 0;
255c957f8b3SAntoine Ténart 	}
2561b44c5a6SAntoine Ténart 
257b8592027SOfer Heifetz 	if (sreq->result_dma) {
2586c1c09b3SPascal van Leeuwen 		dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz,
259b8592027SOfer Heifetz 				 DMA_FROM_DEVICE);
260b8592027SOfer Heifetz 		sreq->result_dma = 0;
261b8592027SOfer Heifetz 	}
262b8592027SOfer Heifetz 
263cff9a175SAntoine Tenart 	if (sreq->cache_dma) {
264cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz,
265cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
266cff9a175SAntoine Tenart 		sreq->cache_dma = 0;
267aa524286SAntoine Tenart 		sreq->cache_sz = 0;
268cff9a175SAntoine Tenart 	}
2691b44c5a6SAntoine Ténart 
27041abed7dSPascal van Leeuwen 	if (sreq->finish) {
27141abed7dSPascal van Leeuwen 		if (sreq->hmac &&
27241abed7dSPascal van Leeuwen 		    (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) {
27341abed7dSPascal van Leeuwen 			/* Faking HMAC using hash - need to do outer hash */
27441abed7dSPascal van Leeuwen 			memcpy(sreq->cache, sreq->state,
27541abed7dSPascal van Leeuwen 			       crypto_ahash_digestsize(ahash));
27641abed7dSPascal van Leeuwen 
2776c1c09b3SPascal van Leeuwen 			memcpy(sreq->state, ctx->opad, sreq->digest_sz);
27841abed7dSPascal van Leeuwen 
27931fb084cSPascal van Leeuwen 			sreq->len = sreq->block_sz +
28041abed7dSPascal van Leeuwen 				    crypto_ahash_digestsize(ahash);
28131fb084cSPascal van Leeuwen 			sreq->processed = sreq->block_sz;
28241abed7dSPascal van Leeuwen 			sreq->hmac = 0;
28341abed7dSPascal van Leeuwen 
284177e358cSPascal van Leeuwen 			if (priv->flags & EIP197_TRC_CACHE)
28541abed7dSPascal van Leeuwen 				ctx->base.needs_inv = true;
28641abed7dSPascal van Leeuwen 			areq->nbytes = 0;
28741abed7dSPascal van Leeuwen 			safexcel_ahash_enqueue(areq);
28841abed7dSPascal van Leeuwen 
28941abed7dSPascal van Leeuwen 			*should_complete = false; /* Not done yet */
29041abed7dSPascal van Leeuwen 			return 1;
29141abed7dSPascal van Leeuwen 		}
29241abed7dSPascal van Leeuwen 
293b98687bbSPascal van Leeuwen 		if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM &&
294b98687bbSPascal van Leeuwen 			     ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) {
295a7cf8658SPascal van Leeuwen 			/* Undo final XOR with 0xffffffff ...*/
29613a1bb93SPascal van Leeuwen 			*(__le32 *)areq->result = ~sreq->state[0];
297a7cf8658SPascal van Leeuwen 		} else {
298b89a8159SAntoine Tenart 			memcpy(areq->result, sreq->state,
299b89a8159SAntoine Tenart 			       crypto_ahash_digestsize(ahash));
30041abed7dSPascal van Leeuwen 		}
301a7cf8658SPascal van Leeuwen 	}
302b89a8159SAntoine Tenart 
303b460edb6SAntoine Tenart 	cache_len = safexcel_queued_len(sreq);
3041b44c5a6SAntoine Ténart 	if (cache_len)
3051b44c5a6SAntoine Ténart 		memcpy(sreq->cache, sreq->cache_next, cache_len);
3061b44c5a6SAntoine Ténart 
3071b44c5a6SAntoine Ténart 	*should_complete = true;
3081b44c5a6SAntoine Ténart 
3091b44c5a6SAntoine Ténart 	return 1;
3101b44c5a6SAntoine Ténart }
3111b44c5a6SAntoine Ténart 
3121eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring,
3131eb7b403SOfer Heifetz 				   int *commands, int *results)
3141b44c5a6SAntoine Ténart {
3151b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
3161b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
3171b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
31818e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
3191b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc, *first_cdesc = NULL;
3201b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
3211b44c5a6SAntoine Ténart 	struct scatterlist *sg;
322098e51e5SPascal van Leeuwen 	struct safexcel_token *dmmy;
3236c1c09b3SPascal van Leeuwen 	int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0;
324b98687bbSPascal van Leeuwen 	u64 queued, len;
3251b44c5a6SAntoine Ténart 
326b98687bbSPascal van Leeuwen 	queued = safexcel_queued_len(req);
32741abed7dSPascal van Leeuwen 	if (queued <= HASH_CACHE_SIZE)
3281b44c5a6SAntoine Ténart 		cache_len = queued;
3291b44c5a6SAntoine Ténart 	else
3301b44c5a6SAntoine Ténart 		cache_len = queued - areq->nbytes;
3311b44c5a6SAntoine Ténart 
33241abed7dSPascal van Leeuwen 	if (!req->finish && !req->last_req) {
333809778e0SAntoine Ténart 		/* If this is not the last request and the queued data does not
33441abed7dSPascal van Leeuwen 		 * fit into full cache blocks, cache it for the next send call.
3351b44c5a6SAntoine Ténart 		 */
33641abed7dSPascal van Leeuwen 		extra = queued & (HASH_CACHE_SIZE - 1);
337082ec2d4SAntoine Tenart 
338809778e0SAntoine Ténart 		/* If this is not the last request and the queued data
339809778e0SAntoine Ténart 		 * is a multiple of a block, cache the last one for now.
340809778e0SAntoine Ténart 		 */
341dd4306a6SAntoine Tenart 		if (!extra)
34241abed7dSPascal van Leeuwen 			extra = HASH_CACHE_SIZE;
343809778e0SAntoine Ténart 
3441b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
345809778e0SAntoine Ténart 				   req->cache_next, extra,
346809778e0SAntoine Ténart 				   areq->nbytes - extra);
3471b44c5a6SAntoine Ténart 
3481b44c5a6SAntoine Ténart 		queued -= extra;
349dc5268b6SPascal van Leeuwen 
350dc5268b6SPascal van Leeuwen 		if (!queued) {
351dc5268b6SPascal van Leeuwen 			*commands = 0;
352dc5268b6SPascal van Leeuwen 			*results = 0;
353dc5268b6SPascal van Leeuwen 			return 0;
354dc5268b6SPascal van Leeuwen 		}
355b98687bbSPascal van Leeuwen 
356b98687bbSPascal van Leeuwen 		extra = 0;
357809778e0SAntoine Ténart 	}
3581b44c5a6SAntoine Ténart 
359b98687bbSPascal van Leeuwen 	if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) {
360b98687bbSPascal van Leeuwen 		if (unlikely(cache_len < AES_BLOCK_SIZE)) {
361b98687bbSPascal van Leeuwen 			/*
362b98687bbSPascal van Leeuwen 			 * Cache contains less than 1 full block, complete.
363b98687bbSPascal van Leeuwen 			 */
364b98687bbSPascal van Leeuwen 			extra = AES_BLOCK_SIZE - cache_len;
365b98687bbSPascal van Leeuwen 			if (queued > cache_len) {
366b98687bbSPascal van Leeuwen 				/* More data follows: borrow bytes */
367b98687bbSPascal van Leeuwen 				u64 tmp = queued - cache_len;
368b98687bbSPascal van Leeuwen 
369b98687bbSPascal van Leeuwen 				skip = min_t(u64, tmp, extra);
370b98687bbSPascal van Leeuwen 				sg_pcopy_to_buffer(areq->src,
371b98687bbSPascal van Leeuwen 					sg_nents(areq->src),
372b98687bbSPascal van Leeuwen 					req->cache + cache_len,
373b98687bbSPascal van Leeuwen 					skip, 0);
374b98687bbSPascal van Leeuwen 			}
375b98687bbSPascal van Leeuwen 			extra -= skip;
376b98687bbSPascal van Leeuwen 			memset(req->cache + cache_len + skip, 0, extra);
37738f21b4bSPascal van Leeuwen 			if (!ctx->cbcmac && extra) {
37838f21b4bSPascal van Leeuwen 				// 10- padding for XCBCMAC & CMAC
37938f21b4bSPascal van Leeuwen 				req->cache[cache_len + skip] = 0x80;
38038f21b4bSPascal van Leeuwen 				// HW will use K2 iso K3 - compensate!
38138f21b4bSPascal van Leeuwen 				for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
38213a1bb93SPascal van Leeuwen 					((__be32 *)req->cache)[i] ^=
38313a1bb93SPascal van Leeuwen 					  cpu_to_be32(le32_to_cpu(
38413a1bb93SPascal van Leeuwen 					    ctx->ipad[i] ^ ctx->ipad[i + 4]));
38538f21b4bSPascal van Leeuwen 			}
386b98687bbSPascal van Leeuwen 			cache_len = AES_BLOCK_SIZE;
387b98687bbSPascal van Leeuwen 			queued = queued + extra;
388b98687bbSPascal van Leeuwen 		}
389b98687bbSPascal van Leeuwen 
390b98687bbSPascal van Leeuwen 		/* XCBC continue: XOR previous result into 1st word */
391b98687bbSPascal van Leeuwen 		crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE);
392b98687bbSPascal van Leeuwen 	}
393b98687bbSPascal van Leeuwen 
394b98687bbSPascal van Leeuwen 	len = queued;
3951b44c5a6SAntoine Ténart 	/* Add a command descriptor for the cached data, if any */
3961b44c5a6SAntoine Ténart 	if (cache_len) {
397cff9a175SAntoine Tenart 		req->cache_dma = dma_map_single(priv->dev, req->cache,
3981b44c5a6SAntoine Ténart 						cache_len, DMA_TO_DEVICE);
3999744fec9SOfer Heifetz 		if (dma_mapping_error(priv->dev, req->cache_dma))
400cff9a175SAntoine Tenart 			return -EINVAL;
4011b44c5a6SAntoine Ténart 
402cff9a175SAntoine Tenart 		req->cache_sz = cache_len;
4031b44c5a6SAntoine Ténart 		first_cdesc = safexcel_add_cdesc(priv, ring, 1,
4041b44c5a6SAntoine Ténart 						 (cache_len == len),
405b98687bbSPascal van Leeuwen 						 req->cache_dma, cache_len,
406098e51e5SPascal van Leeuwen 						 len, ctx->base.ctxr_dma,
407098e51e5SPascal van Leeuwen 						 &dmmy);
4081b44c5a6SAntoine Ténart 		if (IS_ERR(first_cdesc)) {
4091b44c5a6SAntoine Ténart 			ret = PTR_ERR(first_cdesc);
4101b44c5a6SAntoine Ténart 			goto unmap_cache;
4111b44c5a6SAntoine Ténart 		}
4121b44c5a6SAntoine Ténart 		n_cdesc++;
4131b44c5a6SAntoine Ténart 
4141b44c5a6SAntoine Ténart 		queued -= cache_len;
4151b44c5a6SAntoine Ténart 		if (!queued)
4161b44c5a6SAntoine Ténart 			goto send_command;
4171b44c5a6SAntoine Ténart 	}
4181b44c5a6SAntoine Ténart 
4191b44c5a6SAntoine Ténart 	/* Now handle the current ahash request buffer(s) */
42041abed7dSPascal van Leeuwen 	req->nents = dma_map_sg(priv->dev, areq->src,
42141abed7dSPascal van Leeuwen 				sg_nents_for_len(areq->src,
42241abed7dSPascal van Leeuwen 						 areq->nbytes),
4231b44c5a6SAntoine Ténart 				DMA_TO_DEVICE);
424c957f8b3SAntoine Ténart 	if (!req->nents) {
4251b44c5a6SAntoine Ténart 		ret = -ENOMEM;
4261b44c5a6SAntoine Ténart 		goto cdesc_rollback;
4271b44c5a6SAntoine Ténart 	}
4281b44c5a6SAntoine Ténart 
429c957f8b3SAntoine Ténart 	for_each_sg(areq->src, sg, req->nents, i) {
4301b44c5a6SAntoine Ténart 		int sglen = sg_dma_len(sg);
4311b44c5a6SAntoine Ténart 
432b98687bbSPascal van Leeuwen 		if (unlikely(sglen <= skip)) {
433b98687bbSPascal van Leeuwen 			skip -= sglen;
434b98687bbSPascal van Leeuwen 			continue;
435b98687bbSPascal van Leeuwen 		}
436b98687bbSPascal van Leeuwen 
4371b44c5a6SAntoine Ténart 		/* Do not overflow the request */
438b98687bbSPascal van Leeuwen 		if ((queued + skip) <= sglen)
4391b44c5a6SAntoine Ténart 			sglen = queued;
440b98687bbSPascal van Leeuwen 		else
441b98687bbSPascal van Leeuwen 			sglen -= skip;
4421b44c5a6SAntoine Ténart 
4431b44c5a6SAntoine Ténart 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
44441abed7dSPascal van Leeuwen 					   !(queued - sglen),
445b98687bbSPascal van Leeuwen 					   sg_dma_address(sg) + skip, sglen,
446098e51e5SPascal van Leeuwen 					   len, ctx->base.ctxr_dma, &dmmy);
4471b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
4481b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
44957433b58SAntoine Tenart 			goto unmap_sg;
4501b44c5a6SAntoine Ténart 		}
4511b44c5a6SAntoine Ténart 
452b98687bbSPascal van Leeuwen 		if (!n_cdesc)
4531b44c5a6SAntoine Ténart 			first_cdesc = cdesc;
454b98687bbSPascal van Leeuwen 		n_cdesc++;
4551b44c5a6SAntoine Ténart 
4561b44c5a6SAntoine Ténart 		queued -= sglen;
4571b44c5a6SAntoine Ténart 		if (!queued)
4581b44c5a6SAntoine Ténart 			break;
459b98687bbSPascal van Leeuwen 		skip = 0;
4601b44c5a6SAntoine Ténart 	}
4611b44c5a6SAntoine Ténart 
4621b44c5a6SAntoine Ténart send_command:
4631b44c5a6SAntoine Ténart 	/* Setup the context options */
46441abed7dSPascal van Leeuwen 	safexcel_context_control(ctx, req, first_cdesc);
4651b44c5a6SAntoine Ténart 
4666c1c09b3SPascal van Leeuwen 	/* Add the token */
4676c1c09b3SPascal van Leeuwen 	safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac);
4681b44c5a6SAntoine Ténart 
4696c1c09b3SPascal van Leeuwen 	req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz,
470b8592027SOfer Heifetz 					 DMA_FROM_DEVICE);
471b8592027SOfer Heifetz 	if (dma_mapping_error(priv->dev, req->result_dma)) {
4721b44c5a6SAntoine Ténart 		ret = -EINVAL;
47357433b58SAntoine Tenart 		goto unmap_sg;
4741b44c5a6SAntoine Ténart 	}
4751b44c5a6SAntoine Ténart 
4761b44c5a6SAntoine Ténart 	/* Add a result descriptor */
477b8592027SOfer Heifetz 	rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma,
4786c1c09b3SPascal van Leeuwen 				   req->digest_sz);
4791b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
4801b44c5a6SAntoine Ténart 		ret = PTR_ERR(rdesc);
48157240a78SAntoine Tenart 		goto unmap_result;
4821b44c5a6SAntoine Ténart 	}
4831b44c5a6SAntoine Ténart 
4849744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, rdesc, &areq->base);
4851b44c5a6SAntoine Ténart 
486b98687bbSPascal van Leeuwen 	req->processed += len - extra;
487b460edb6SAntoine Tenart 
4881b44c5a6SAntoine Ténart 	*commands = n_cdesc;
4891b44c5a6SAntoine Ténart 	*results = 1;
4901b44c5a6SAntoine Ténart 	return 0;
4911b44c5a6SAntoine Ténart 
49257240a78SAntoine Tenart unmap_result:
4936c1c09b3SPascal van Leeuwen 	dma_unmap_single(priv->dev, req->result_dma, req->digest_sz,
49457433b58SAntoine Tenart 			 DMA_FROM_DEVICE);
49557433b58SAntoine Tenart unmap_sg:
496b98687bbSPascal van Leeuwen 	if (req->nents) {
49757240a78SAntoine Tenart 		dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE);
498b98687bbSPascal van Leeuwen 		req->nents = 0;
499b98687bbSPascal van Leeuwen 	}
5001b44c5a6SAntoine Ténart cdesc_rollback:
5011b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
5021b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
5031b44c5a6SAntoine Ténart unmap_cache:
504cff9a175SAntoine Tenart 	if (req->cache_dma) {
505cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz,
506cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
507aa524286SAntoine Tenart 		req->cache_dma = 0;
508cff9a175SAntoine Tenart 		req->cache_sz = 0;
5091b44c5a6SAntoine Ténart 	}
5101b44c5a6SAntoine Ténart 
5111b44c5a6SAntoine Ténart 	return ret;
5121b44c5a6SAntoine Ténart }
5131b44c5a6SAntoine Ténart 
5141b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
5151b44c5a6SAntoine Ténart 				      int ring,
5161b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
5171b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
5181b44c5a6SAntoine Ténart {
5191b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
5201b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
5211b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
5221b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
5231b44c5a6SAntoine Ténart 	int enq_ret;
5241b44c5a6SAntoine Ténart 
5251b44c5a6SAntoine Ténart 	*ret = 0;
5261b44c5a6SAntoine Ténart 
5271b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
5281b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
5291b44c5a6SAntoine Ténart 		dev_err(priv->dev,
5301b44c5a6SAntoine Ténart 			"hash: invalidate: could not retrieve the result descriptor\n");
5311b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
532cda3e73aSAntoine Tenart 	} else {
533cda3e73aSAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
5341b44c5a6SAntoine Ténart 	}
5351b44c5a6SAntoine Ténart 
5361b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
5371b44c5a6SAntoine Ténart 
5381b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
5391b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
5401b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
5411b44c5a6SAntoine Ténart 
5421b44c5a6SAntoine Ténart 		*should_complete = true;
5431b44c5a6SAntoine Ténart 		return 1;
5441b44c5a6SAntoine Ténart 	}
5451b44c5a6SAntoine Ténart 
54686671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
54786671abbSAntoine Ténart 	ctx->base.ring = ring;
5481b44c5a6SAntoine Ténart 
54986671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
55086671abbSAntoine Ténart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async);
55186671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
5521b44c5a6SAntoine Ténart 
5531b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
5541b44c5a6SAntoine Ténart 		*ret = enq_ret;
5551b44c5a6SAntoine Ténart 
5568472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
5578472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
55886671abbSAntoine Ténart 
5591b44c5a6SAntoine Ténart 	*should_complete = false;
5601b44c5a6SAntoine Ténart 
5611b44c5a6SAntoine Ténart 	return 1;
5621b44c5a6SAntoine Ténart }
5631b44c5a6SAntoine Ténart 
5641eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring,
5651eb7b403SOfer Heifetz 				  struct crypto_async_request *async,
5661eb7b403SOfer Heifetz 				  bool *should_complete, int *ret)
5671eb7b403SOfer Heifetz {
5681eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
5691eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5701eb7b403SOfer Heifetz 	int err;
5711eb7b403SOfer Heifetz 
57253c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv);
573871df319SAntoine Ténart 
5741eb7b403SOfer Heifetz 	if (req->needs_inv) {
5751eb7b403SOfer Heifetz 		req->needs_inv = false;
5761eb7b403SOfer Heifetz 		err = safexcel_handle_inv_result(priv, ring, async,
5771eb7b403SOfer Heifetz 						 should_complete, ret);
5781eb7b403SOfer Heifetz 	} else {
5791eb7b403SOfer Heifetz 		err = safexcel_handle_req_result(priv, ring, async,
5801eb7b403SOfer Heifetz 						 should_complete, ret);
5811eb7b403SOfer Heifetz 	}
5821eb7b403SOfer Heifetz 
5831eb7b403SOfer Heifetz 	return err;
5841eb7b403SOfer Heifetz }
5851eb7b403SOfer Heifetz 
5861b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async,
5879744fec9SOfer Heifetz 				   int ring, int *commands, int *results)
5881b44c5a6SAntoine Ténart {
5891b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
5901b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
5911b44c5a6SAntoine Ténart 	int ret;
5921b44c5a6SAntoine Ténart 
59318e51895SHerbert Xu 	ret = safexcel_invalidate_cache(async, ctx->base.priv,
5949744fec9SOfer Heifetz 					ctx->base.ctxr_dma, ring);
5951b44c5a6SAntoine Ténart 	if (unlikely(ret))
5961b44c5a6SAntoine Ténart 		return ret;
5971b44c5a6SAntoine Ténart 
5981b44c5a6SAntoine Ténart 	*commands = 1;
5991b44c5a6SAntoine Ténart 	*results = 1;
6001b44c5a6SAntoine Ténart 
6011b44c5a6SAntoine Ténart 	return 0;
6021b44c5a6SAntoine Ténart }
6031b44c5a6SAntoine Ténart 
6041eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async,
6059744fec9SOfer Heifetz 			       int ring, int *commands, int *results)
6061eb7b403SOfer Heifetz {
6071eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
6081eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6091eb7b403SOfer Heifetz 	int ret;
6101eb7b403SOfer Heifetz 
6111eb7b403SOfer Heifetz 	if (req->needs_inv)
6129744fec9SOfer Heifetz 		ret = safexcel_ahash_send_inv(async, ring, commands, results);
6131eb7b403SOfer Heifetz 	else
6149744fec9SOfer Heifetz 		ret = safexcel_ahash_send_req(async, ring, commands, results);
6159744fec9SOfer Heifetz 
6161eb7b403SOfer Heifetz 	return ret;
6171eb7b403SOfer Heifetz }
6181eb7b403SOfer Heifetz 
6191b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm)
6201b44c5a6SAntoine Ténart {
6211b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
62218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
62361824806SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE);
6247cad2fabSAntoine Ténart 	struct safexcel_ahash_req *rctx = ahash_request_ctx(req);
6253e1166b9SArnd Bergmann 	struct safexcel_inv_result result = {};
62686671abbSAntoine Ténart 	int ring = ctx->base.ring;
6271b44c5a6SAntoine Ténart 
628b926213dSAntoine Tenart 	memset(req, 0, EIP197_AHASH_REQ_SIZE);
6291b44c5a6SAntoine Ténart 
6301b44c5a6SAntoine Ténart 	/* create invalidation request */
6311b44c5a6SAntoine Ténart 	init_completion(&result.completion);
6327cad2fabSAntoine Ténart 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
6331b44c5a6SAntoine Ténart 				   safexcel_inv_complete, &result);
6341b44c5a6SAntoine Ténart 
6357cad2fabSAntoine Ténart 	ahash_request_set_tfm(req, __crypto_ahash_cast(tfm));
6367cad2fabSAntoine Ténart 	ctx = crypto_tfm_ctx(req->base.tfm);
6371b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
6381eb7b403SOfer Heifetz 	rctx->needs_inv = true;
6391b44c5a6SAntoine Ténart 
64086671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
6417cad2fabSAntoine Ténart 	crypto_enqueue_request(&priv->ring[ring].queue, &req->base);
64286671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
6431b44c5a6SAntoine Ténart 
6448472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
6458472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
6461b44c5a6SAntoine Ténart 
647b7007dbcSAntoine Tenart 	wait_for_completion(&result.completion);
6481b44c5a6SAntoine Ténart 
6491b44c5a6SAntoine Ténart 	if (result.error) {
6501b44c5a6SAntoine Ténart 		dev_warn(priv->dev, "hash: completion error (%d)\n",
6511b44c5a6SAntoine Ténart 			 result.error);
6521b44c5a6SAntoine Ténart 		return result.error;
6531b44c5a6SAntoine Ténart 	}
6541b44c5a6SAntoine Ténart 
6551b44c5a6SAntoine Ténart 	return 0;
6561b44c5a6SAntoine Ténart }
6571b44c5a6SAntoine Ténart 
658cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to
659cc75f5ceSAntoine Ténart  * the engine, aka. when there is at least 1 block size in the pipe.
660cc75f5ceSAntoine Ténart  */
66141abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq)
6621b44c5a6SAntoine Ténart {
6631b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
66441abed7dSPascal van Leeuwen 	u64 cache_len;
6651b44c5a6SAntoine Ténart 
666b460edb6SAntoine Tenart 	/* cache_len: everything accepted by the driver but not sent yet,
667b460edb6SAntoine Tenart 	 * tot sz handled by update() - last req sz - tot sz handled by send()
668b460edb6SAntoine Tenart 	 */
66941abed7dSPascal van Leeuwen 	cache_len = safexcel_queued_len(req);
6701b44c5a6SAntoine Ténart 
6711b44c5a6SAntoine Ténart 	/*
6721b44c5a6SAntoine Ténart 	 * In case there isn't enough bytes to proceed (less than a
6731b44c5a6SAntoine Ténart 	 * block size), cache the data until we have enough.
6741b44c5a6SAntoine Ténart 	 */
67541abed7dSPascal van Leeuwen 	if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) {
6761b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
6771b44c5a6SAntoine Ténart 				   req->cache + cache_len,
6781b44c5a6SAntoine Ténart 				   areq->nbytes, 0);
67941abed7dSPascal van Leeuwen 		return 0;
6801b44c5a6SAntoine Ténart 	}
6811b44c5a6SAntoine Ténart 
682dfbcc08fSAntoine Ténart 	/* We couldn't cache all the data */
6831b44c5a6SAntoine Ténart 	return -E2BIG;
6841b44c5a6SAntoine Ténart }
6851b44c5a6SAntoine Ténart 
6861b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq)
6871b44c5a6SAntoine Ténart {
6881b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
6891b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
69018e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
69186671abbSAntoine Ténart 	int ret, ring;
6921b44c5a6SAntoine Ténart 
6931eb7b403SOfer Heifetz 	req->needs_inv = false;
6941b44c5a6SAntoine Ténart 
695c4daf4ccSOfer Heifetz 	if (ctx->base.ctxr) {
69653c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv &&
697b98687bbSPascal van Leeuwen 		     /* invalidate for *any* non-XCBC continuation */
698b98687bbSPascal van Leeuwen 		   ((req->not_first && !req->xcbcmac) ||
69941abed7dSPascal van Leeuwen 		     /* invalidate if (i)digest changed */
70041abed7dSPascal van Leeuwen 		     memcmp(ctx->base.ctxr->data, req->state, req->state_sz) ||
70141abed7dSPascal van Leeuwen 		     /* invalidate for HMAC finish with odigest changed */
702a7cf8658SPascal van Leeuwen 		     (req->finish && req->hmac &&
70341abed7dSPascal van Leeuwen 		      memcmp(ctx->base.ctxr->data + (req->state_sz>>2),
70441abed7dSPascal van Leeuwen 			     ctx->opad, req->state_sz))))
70541abed7dSPascal van Leeuwen 			/*
70641abed7dSPascal van Leeuwen 			 * We're still setting needs_inv here, even though it is
707c4daf4ccSOfer Heifetz 			 * cleared right away, because the needs_inv flag can be
708c4daf4ccSOfer Heifetz 			 * set in other functions and we want to keep the same
709c4daf4ccSOfer Heifetz 			 * logic.
710c4daf4ccSOfer Heifetz 			 */
71141abed7dSPascal van Leeuwen 			ctx->base.needs_inv = true;
7121b44c5a6SAntoine Ténart 
7131eb7b403SOfer Heifetz 		if (ctx->base.needs_inv) {
7141eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
7151eb7b403SOfer Heifetz 			req->needs_inv = true;
7161eb7b403SOfer Heifetz 		}
7171b44c5a6SAntoine Ténart 	} else {
7181b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
7191b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
7201b44c5a6SAntoine Ténart 						 EIP197_GFP_FLAGS(areq->base),
7211b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
7221b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
7231b44c5a6SAntoine Ténart 			return -ENOMEM;
7241b44c5a6SAntoine Ténart 	}
725b98687bbSPascal van Leeuwen 	req->not_first = true;
7261b44c5a6SAntoine Ténart 
72786671abbSAntoine Ténart 	ring = ctx->base.ring;
7281b44c5a6SAntoine Ténart 
72986671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
73086671abbSAntoine Ténart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base);
73186671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
73286671abbSAntoine Ténart 
7338472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
7348472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
7351b44c5a6SAntoine Ténart 
7361b44c5a6SAntoine Ténart 	return ret;
7371b44c5a6SAntoine Ténart }
7381b44c5a6SAntoine Ténart 
7391b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq)
7401b44c5a6SAntoine Ténart {
7411b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
74241abed7dSPascal van Leeuwen 	int ret;
7431b44c5a6SAntoine Ténart 
7441b44c5a6SAntoine Ténart 	/* If the request is 0 length, do nothing */
7451b44c5a6SAntoine Ténart 	if (!areq->nbytes)
7461b44c5a6SAntoine Ténart 		return 0;
7471b44c5a6SAntoine Ténart 
74841abed7dSPascal van Leeuwen 	/* Add request to the cache if it fits */
74941abed7dSPascal van Leeuwen 	ret = safexcel_ahash_cache(areq);
75041abed7dSPascal van Leeuwen 
75141abed7dSPascal van Leeuwen 	/* Update total request length */
75231fb084cSPascal van Leeuwen 	req->len += areq->nbytes;
7531b44c5a6SAntoine Ténart 
75441abed7dSPascal van Leeuwen 	/* If not all data could fit into the cache, go process the excess.
75541abed7dSPascal van Leeuwen 	 * Also go process immediately for an HMAC IV precompute, which
75641abed7dSPascal van Leeuwen 	 * will never be finished at all, but needs to be processed anyway.
7571b44c5a6SAntoine Ténart 	 */
75841abed7dSPascal van Leeuwen 	if ((ret && !req->finish) || req->last_req)
7591b44c5a6SAntoine Ténart 		return safexcel_ahash_enqueue(areq);
7601b44c5a6SAntoine Ténart 
7611b44c5a6SAntoine Ténart 	return 0;
7621b44c5a6SAntoine Ténart }
7631b44c5a6SAntoine Ténart 
7641b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq)
7651b44c5a6SAntoine Ténart {
7661b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
7671b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
7681b44c5a6SAntoine Ténart 
7691b44c5a6SAntoine Ténart 	req->finish = true;
7701b44c5a6SAntoine Ténart 
77131fb084cSPascal van Leeuwen 	if (unlikely(!req->len && !areq->nbytes)) {
77285695b09SPascal van Leeuwen 		/*
77385695b09SPascal van Leeuwen 		 * If we have an overall 0 length *hash* request:
77485695b09SPascal van Leeuwen 		 * The HW cannot do 0 length hash, so we provide the correct
77585695b09SPascal van Leeuwen 		 * result directly here.
77685695b09SPascal van Leeuwen 		 */
777293f89cfSOfer Heifetz 		if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5)
778293f89cfSOfer Heifetz 			memcpy(areq->result, md5_zero_message_hash,
779293f89cfSOfer Heifetz 			       MD5_DIGEST_SIZE);
780293f89cfSOfer Heifetz 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1)
7811b44c5a6SAntoine Ténart 			memcpy(areq->result, sha1_zero_message_hash,
7821b44c5a6SAntoine Ténart 			       SHA1_DIGEST_SIZE);
7831b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224)
7841b44c5a6SAntoine Ténart 			memcpy(areq->result, sha224_zero_message_hash,
7851b44c5a6SAntoine Ténart 			       SHA224_DIGEST_SIZE);
7861b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256)
7871b44c5a6SAntoine Ténart 			memcpy(areq->result, sha256_zero_message_hash,
7881b44c5a6SAntoine Ténart 			       SHA256_DIGEST_SIZE);
7899e46eafdSAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384)
7909e46eafdSAntoine Tenart 			memcpy(areq->result, sha384_zero_message_hash,
7919e46eafdSAntoine Tenart 			       SHA384_DIGEST_SIZE);
792b460edb6SAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512)
793b460edb6SAntoine Tenart 			memcpy(areq->result, sha512_zero_message_hash,
794b460edb6SAntoine Tenart 			       SHA512_DIGEST_SIZE);
7950f2bc131SPascal van Leeuwen 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) {
7960f2bc131SPascal van Leeuwen 			memcpy(areq->result,
7970f2bc131SPascal van Leeuwen 			       EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE);
7980f2bc131SPascal van Leeuwen 		}
7991b44c5a6SAntoine Ténart 
8001b44c5a6SAntoine Ténart 		return 0;
801a7cf8658SPascal van Leeuwen 	} else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM &&
802a7cf8658SPascal van Leeuwen 			    ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 &&
803a7cf8658SPascal van Leeuwen 			    req->len == sizeof(u32) && !areq->nbytes)) {
804a7cf8658SPascal van Leeuwen 		/* Zero length CRC32 */
805a7cf8658SPascal van Leeuwen 		memcpy(areq->result, ctx->ipad, sizeof(u32));
806a7cf8658SPascal van Leeuwen 		return 0;
80738f21b4bSPascal van Leeuwen 	} else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE &&
808b98687bbSPascal van Leeuwen 			    !areq->nbytes)) {
809b98687bbSPascal van Leeuwen 		/* Zero length CBC MAC */
810b98687bbSPascal van Leeuwen 		memset(areq->result, 0, AES_BLOCK_SIZE);
811b98687bbSPascal van Leeuwen 		return 0;
81238f21b4bSPascal van Leeuwen 	} else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE &&
81338f21b4bSPascal van Leeuwen 			    !areq->nbytes)) {
81438f21b4bSPascal van Leeuwen 		/* Zero length (X)CBC/CMAC */
81538f21b4bSPascal van Leeuwen 		int i;
81638f21b4bSPascal van Leeuwen 
81738f21b4bSPascal van Leeuwen 		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
81813a1bb93SPascal van Leeuwen 			((__be32 *)areq->result)[i] =
81913a1bb93SPascal van Leeuwen 				cpu_to_be32(le32_to_cpu(ctx->ipad[i + 4]));//K3
82038f21b4bSPascal van Leeuwen 		areq->result[0] ^= 0x80;			// 10- padding
82138f21b4bSPascal van Leeuwen 		crypto_cipher_encrypt_one(ctx->kaes, areq->result, areq->result);
82238f21b4bSPascal van Leeuwen 		return 0;
82331fb084cSPascal van Leeuwen 	} else if (unlikely(req->hmac &&
82431fb084cSPascal van Leeuwen 			    (req->len == req->block_sz) &&
82541abed7dSPascal van Leeuwen 			    !areq->nbytes)) {
82685b36ee8SPascal van Leeuwen 		/*
82785b36ee8SPascal van Leeuwen 		 * If we have an overall 0 length *HMAC* request:
82885b36ee8SPascal van Leeuwen 		 * For HMAC, we need to finalize the inner digest
82985b36ee8SPascal van Leeuwen 		 * and then perform the outer hash.
83085b36ee8SPascal van Leeuwen 		 */
83185b36ee8SPascal van Leeuwen 
83285b36ee8SPascal van Leeuwen 		/* generate pad block in the cache */
83385b36ee8SPascal van Leeuwen 		/* start with a hash block of all zeroes */
83485b36ee8SPascal van Leeuwen 		memset(req->cache, 0, req->block_sz);
83585b36ee8SPascal van Leeuwen 		/* set the first byte to 0x80 to 'append a 1 bit' */
83685b36ee8SPascal van Leeuwen 		req->cache[0] = 0x80;
83785b36ee8SPascal van Leeuwen 		/* add the length in bits in the last 2 bytes */
83885b36ee8SPascal van Leeuwen 		if (req->len_is_le) {
83985b36ee8SPascal van Leeuwen 			/* Little endian length word (e.g. MD5) */
84085b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-8] = (req->block_sz << 3) &
84185b36ee8SPascal van Leeuwen 						      255;
84285b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-7] = (req->block_sz >> 5);
84385b36ee8SPascal van Leeuwen 		} else {
84485b36ee8SPascal van Leeuwen 			/* Big endian length word (e.g. any SHA) */
84585b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-2] = (req->block_sz >> 5);
84685b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-1] = (req->block_sz << 3) &
84785b36ee8SPascal van Leeuwen 						      255;
84885b36ee8SPascal van Leeuwen 		}
84985b36ee8SPascal van Leeuwen 
85031fb084cSPascal van Leeuwen 		req->len += req->block_sz; /* plus 1 hash block */
85185b36ee8SPascal van Leeuwen 
85285b36ee8SPascal van Leeuwen 		/* Set special zero-length HMAC flag */
85385b36ee8SPascal van Leeuwen 		req->hmac_zlen = true;
85485b36ee8SPascal van Leeuwen 
85585b36ee8SPascal van Leeuwen 		/* Finalize HMAC */
85685b36ee8SPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
85741abed7dSPascal van Leeuwen 	} else if (req->hmac) {
85841abed7dSPascal van Leeuwen 		/* Finalize HMAC */
85941abed7dSPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
8601b44c5a6SAntoine Ténart 	}
8611b44c5a6SAntoine Ténart 
8621b44c5a6SAntoine Ténart 	return safexcel_ahash_enqueue(areq);
8631b44c5a6SAntoine Ténart }
8641b44c5a6SAntoine Ténart 
8651b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq)
8661b44c5a6SAntoine Ténart {
8671b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8681b44c5a6SAntoine Ténart 
8691b44c5a6SAntoine Ténart 	req->finish = true;
8701b44c5a6SAntoine Ténart 
8711b44c5a6SAntoine Ténart 	safexcel_ahash_update(areq);
8721b44c5a6SAntoine Ténart 	return safexcel_ahash_final(areq);
8731b44c5a6SAntoine Ténart }
8741b44c5a6SAntoine Ténart 
8751b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out)
8761b44c5a6SAntoine Ténart {
8771b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8781b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state *export = out;
8791b44c5a6SAntoine Ténart 
88031fb084cSPascal van Leeuwen 	export->len = req->len;
88131fb084cSPascal van Leeuwen 	export->processed = req->processed;
8821b44c5a6SAntoine Ténart 
883b869648cSAntoine Tenart 	export->digest = req->digest;
884b869648cSAntoine Tenart 
8851b44c5a6SAntoine Ténart 	memcpy(export->state, req->state, req->state_sz);
88641abed7dSPascal van Leeuwen 	memcpy(export->cache, req->cache, HASH_CACHE_SIZE);
8871b44c5a6SAntoine Ténart 
8881b44c5a6SAntoine Ténart 	return 0;
8891b44c5a6SAntoine Ténart }
8901b44c5a6SAntoine Ténart 
8911b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in)
8921b44c5a6SAntoine Ténart {
8931b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8941b44c5a6SAntoine Ténart 	const struct safexcel_ahash_export_state *export = in;
8951b44c5a6SAntoine Ténart 	int ret;
8961b44c5a6SAntoine Ténart 
8971b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
8981b44c5a6SAntoine Ténart 	if (ret)
8991b44c5a6SAntoine Ténart 		return ret;
9001b44c5a6SAntoine Ténart 
90131fb084cSPascal van Leeuwen 	req->len = export->len;
90231fb084cSPascal van Leeuwen 	req->processed = export->processed;
9031b44c5a6SAntoine Ténart 
904b869648cSAntoine Tenart 	req->digest = export->digest;
905b869648cSAntoine Tenart 
90641abed7dSPascal van Leeuwen 	memcpy(req->cache, export->cache, HASH_CACHE_SIZE);
9071b44c5a6SAntoine Ténart 	memcpy(req->state, export->state, req->state_sz);
9081b44c5a6SAntoine Ténart 
9091b44c5a6SAntoine Ténart 	return 0;
9101b44c5a6SAntoine Ténart }
9111b44c5a6SAntoine Ténart 
9121b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm)
9131b44c5a6SAntoine Ténart {
9141b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
9151b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
9161b44c5a6SAntoine Ténart 		container_of(__crypto_ahash_alg(tfm->__crt_alg),
9171b44c5a6SAntoine Ténart 			     struct safexcel_alg_template, alg.ahash);
9181b44c5a6SAntoine Ténart 
91918e51895SHerbert Xu 	ctx->base.priv = tmpl->priv;
9201eb7b403SOfer Heifetz 	ctx->base.send = safexcel_ahash_send;
9211eb7b403SOfer Heifetz 	ctx->base.handle_result = safexcel_handle_result;
9226c1c09b3SPascal van Leeuwen 	ctx->fb_do_setkey = false;
9231b44c5a6SAntoine Ténart 
9241b44c5a6SAntoine Ténart 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
9251b44c5a6SAntoine Ténart 				 sizeof(struct safexcel_ahash_req));
9261b44c5a6SAntoine Ténart 	return 0;
9271b44c5a6SAntoine Ténart }
9281b44c5a6SAntoine Ténart 
9291b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq)
9301b44c5a6SAntoine Ténart {
9311b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
9321b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
9331b44c5a6SAntoine Ténart 
9341b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
9351b44c5a6SAntoine Ténart 
9361b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
937b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
9381b44c5a6SAntoine Ténart 	req->state_sz = SHA1_DIGEST_SIZE;
9396c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA1_DIGEST_SIZE;
94041abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
9411b44c5a6SAntoine Ténart 
9421b44c5a6SAntoine Ténart 	return 0;
9431b44c5a6SAntoine Ténart }
9441b44c5a6SAntoine Ténart 
9451b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq)
9461b44c5a6SAntoine Ténart {
9471b44c5a6SAntoine Ténart 	int ret = safexcel_sha1_init(areq);
9481b44c5a6SAntoine Ténart 
9491b44c5a6SAntoine Ténart 	if (ret)
9501b44c5a6SAntoine Ténart 		return ret;
9511b44c5a6SAntoine Ténart 
9521b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
9531b44c5a6SAntoine Ténart }
9541b44c5a6SAntoine Ténart 
9551b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm)
9561b44c5a6SAntoine Ténart {
9571b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
95818e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
9591b44c5a6SAntoine Ténart 	int ret;
9601b44c5a6SAntoine Ténart 
9611b44c5a6SAntoine Ténart 	/* context not allocated, skip invalidation */
9621b44c5a6SAntoine Ténart 	if (!ctx->base.ctxr)
9631b44c5a6SAntoine Ténart 		return;
9641b44c5a6SAntoine Ténart 
96553c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
9661b44c5a6SAntoine Ténart 		ret = safexcel_ahash_exit_inv(tfm);
9671b44c5a6SAntoine Ténart 		if (ret)
9681b44c5a6SAntoine Ténart 			dev_warn(priv->dev, "hash: invalidation error %d\n", ret);
969871df319SAntoine Ténart 	} else {
970871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
971871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
972871df319SAntoine Ténart 	}
9731b44c5a6SAntoine Ténart }
9741b44c5a6SAntoine Ténart 
9751b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = {
9761b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
977062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
9781b44c5a6SAntoine Ténart 	.alg.ahash = {
9791b44c5a6SAntoine Ténart 		.init = safexcel_sha1_init,
9801b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
9811b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
9821b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
9831b44c5a6SAntoine Ténart 		.digest = safexcel_sha1_digest,
9841b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
9851b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
9861b44c5a6SAntoine Ténart 		.halg = {
9871b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
9881b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
9891b44c5a6SAntoine Ténart 			.base = {
9901b44c5a6SAntoine Ténart 				.cra_name = "sha1",
9911b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha1",
992aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
9931b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
994b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
9951b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
9961b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
9971b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
9981b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
9991b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
10001b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
10011b44c5a6SAntoine Ténart 			},
10021b44c5a6SAntoine Ténart 		},
10031b44c5a6SAntoine Ténart 	},
10041b44c5a6SAntoine Ténart };
10051b44c5a6SAntoine Ténart 
10061b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq)
10071b44c5a6SAntoine Ténart {
100841abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1009b869648cSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
10101b44c5a6SAntoine Ténart 
101141abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
101241abed7dSPascal van Leeuwen 
101341abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
101441abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA1_DIGEST_SIZE);
101541abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
101631fb084cSPascal van Leeuwen 	req->len	= SHA1_BLOCK_SIZE;
101731fb084cSPascal van Leeuwen 	req->processed	= SHA1_BLOCK_SIZE;
101841abed7dSPascal van Leeuwen 
101941abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
102041abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
102141abed7dSPascal van Leeuwen 	req->state_sz = SHA1_DIGEST_SIZE;
10226c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA1_DIGEST_SIZE;
102341abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
102441abed7dSPascal van Leeuwen 	req->hmac = true;
102541abed7dSPascal van Leeuwen 
10261b44c5a6SAntoine Ténart 	return 0;
10271b44c5a6SAntoine Ténart }
10281b44c5a6SAntoine Ténart 
10291b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq)
10301b44c5a6SAntoine Ténart {
10311b44c5a6SAntoine Ténart 	int ret = safexcel_hmac_sha1_init(areq);
10321b44c5a6SAntoine Ténart 
10331b44c5a6SAntoine Ténart 	if (ret)
10341b44c5a6SAntoine Ténart 		return ret;
10351b44c5a6SAntoine Ténart 
10361b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
10371b44c5a6SAntoine Ténart }
10381b44c5a6SAntoine Ténart 
10391b44c5a6SAntoine Ténart struct safexcel_ahash_result {
10401b44c5a6SAntoine Ténart 	struct completion completion;
10411b44c5a6SAntoine Ténart 	int error;
10421b44c5a6SAntoine Ténart };
10431b44c5a6SAntoine Ténart 
10441b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error)
10451b44c5a6SAntoine Ténart {
10461b44c5a6SAntoine Ténart 	struct safexcel_ahash_result *result = req->data;
10471b44c5a6SAntoine Ténart 
10481b44c5a6SAntoine Ténart 	if (error == -EINPROGRESS)
10491b44c5a6SAntoine Ténart 		return;
10501b44c5a6SAntoine Ténart 
10511b44c5a6SAntoine Ténart 	result->error = error;
10521b44c5a6SAntoine Ténart 	complete(&result->completion);
10531b44c5a6SAntoine Ténart }
10541b44c5a6SAntoine Ténart 
10551b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq,
10561b44c5a6SAntoine Ténart 				  unsigned int blocksize, const u8 *key,
10571b44c5a6SAntoine Ténart 				  unsigned int keylen, u8 *ipad, u8 *opad)
10581b44c5a6SAntoine Ténart {
10591b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
10601b44c5a6SAntoine Ténart 	struct scatterlist sg;
10611b44c5a6SAntoine Ténart 	int ret, i;
10621b44c5a6SAntoine Ténart 	u8 *keydup;
10631b44c5a6SAntoine Ténart 
10641b44c5a6SAntoine Ténart 	if (keylen <= blocksize) {
10651b44c5a6SAntoine Ténart 		memcpy(ipad, key, keylen);
10661b44c5a6SAntoine Ténart 	} else {
10671b44c5a6SAntoine Ténart 		keydup = kmemdup(key, keylen, GFP_KERNEL);
10681b44c5a6SAntoine Ténart 		if (!keydup)
10691b44c5a6SAntoine Ténart 			return -ENOMEM;
10701b44c5a6SAntoine Ténart 
10711b44c5a6SAntoine Ténart 		ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
10721b44c5a6SAntoine Ténart 					   safexcel_ahash_complete, &result);
10731b44c5a6SAntoine Ténart 		sg_init_one(&sg, keydup, keylen);
10741b44c5a6SAntoine Ténart 		ahash_request_set_crypt(areq, &sg, ipad, keylen);
10751b44c5a6SAntoine Ténart 		init_completion(&result.completion);
10761b44c5a6SAntoine Ténart 
10771b44c5a6SAntoine Ténart 		ret = crypto_ahash_digest(areq);
10784dc5475aSAntoine Tenart 		if (ret == -EINPROGRESS || ret == -EBUSY) {
10791b44c5a6SAntoine Ténart 			wait_for_completion_interruptible(&result.completion);
10801b44c5a6SAntoine Ténart 			ret = result.error;
10811b44c5a6SAntoine Ténart 		}
10821b44c5a6SAntoine Ténart 
10831b44c5a6SAntoine Ténart 		/* Avoid leaking */
108457059185SDenis Efremov 		kfree_sensitive(keydup);
10851b44c5a6SAntoine Ténart 
10861b44c5a6SAntoine Ténart 		if (ret)
10871b44c5a6SAntoine Ténart 			return ret;
10881b44c5a6SAntoine Ténart 
10891b44c5a6SAntoine Ténart 		keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq));
10901b44c5a6SAntoine Ténart 	}
10911b44c5a6SAntoine Ténart 
10921b44c5a6SAntoine Ténart 	memset(ipad + keylen, 0, blocksize - keylen);
10931b44c5a6SAntoine Ténart 	memcpy(opad, ipad, blocksize);
10941b44c5a6SAntoine Ténart 
10951b44c5a6SAntoine Ténart 	for (i = 0; i < blocksize; i++) {
1096aed3731eSAntoine Ténart 		ipad[i] ^= HMAC_IPAD_VALUE;
1097aed3731eSAntoine Ténart 		opad[i] ^= HMAC_OPAD_VALUE;
10981b44c5a6SAntoine Ténart 	}
10991b44c5a6SAntoine Ténart 
11001b44c5a6SAntoine Ténart 	return 0;
11011b44c5a6SAntoine Ténart }
11021b44c5a6SAntoine Ténart 
11031b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq,
11041b44c5a6SAntoine Ténart 				 unsigned int blocksize, u8 *pad, void *state)
11051b44c5a6SAntoine Ténart {
11061b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
11071b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req;
11081b44c5a6SAntoine Ténart 	struct scatterlist sg;
11091b44c5a6SAntoine Ténart 	int ret;
11101b44c5a6SAntoine Ténart 
11111b44c5a6SAntoine Ténart 	ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
11121b44c5a6SAntoine Ténart 				   safexcel_ahash_complete, &result);
11131b44c5a6SAntoine Ténart 	sg_init_one(&sg, pad, blocksize);
11141b44c5a6SAntoine Ténart 	ahash_request_set_crypt(areq, &sg, pad, blocksize);
11151b44c5a6SAntoine Ténart 	init_completion(&result.completion);
11161b44c5a6SAntoine Ténart 
11171b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
11181b44c5a6SAntoine Ténart 	if (ret)
11191b44c5a6SAntoine Ténart 		return ret;
11201b44c5a6SAntoine Ténart 
11211b44c5a6SAntoine Ténart 	req = ahash_request_ctx(areq);
11221b44c5a6SAntoine Ténart 	req->hmac = true;
11231b44c5a6SAntoine Ténart 	req->last_req = true;
11241b44c5a6SAntoine Ténart 
11251b44c5a6SAntoine Ténart 	ret = crypto_ahash_update(areq);
112612bf4142SOfer Heifetz 	if (ret && ret != -EINPROGRESS && ret != -EBUSY)
11271b44c5a6SAntoine Ténart 		return ret;
11281b44c5a6SAntoine Ténart 
11291b44c5a6SAntoine Ténart 	wait_for_completion_interruptible(&result.completion);
11301b44c5a6SAntoine Ténart 	if (result.error)
11311b44c5a6SAntoine Ténart 		return result.error;
11321b44c5a6SAntoine Ténart 
11331b44c5a6SAntoine Ténart 	return crypto_ahash_export(areq, state);
11341b44c5a6SAntoine Ténart }
11351b44c5a6SAntoine Ténart 
1136f6beaea3SAntoine Tenart int safexcel_hmac_setkey(const char *alg, const u8 *key, unsigned int keylen,
1137f6beaea3SAntoine Tenart 			 void *istate, void *ostate)
11381b44c5a6SAntoine Ténart {
11391b44c5a6SAntoine Ténart 	struct ahash_request *areq;
11401b44c5a6SAntoine Ténart 	struct crypto_ahash *tfm;
11411b44c5a6SAntoine Ténart 	unsigned int blocksize;
11421b44c5a6SAntoine Ténart 	u8 *ipad, *opad;
11431b44c5a6SAntoine Ténart 	int ret;
11441b44c5a6SAntoine Ténart 
114585d7311fSEric Biggers 	tfm = crypto_alloc_ahash(alg, 0, 0);
11461b44c5a6SAntoine Ténart 	if (IS_ERR(tfm))
11471b44c5a6SAntoine Ténart 		return PTR_ERR(tfm);
11481b44c5a6SAntoine Ténart 
11491b44c5a6SAntoine Ténart 	areq = ahash_request_alloc(tfm, GFP_KERNEL);
11501b44c5a6SAntoine Ténart 	if (!areq) {
11511b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11521b44c5a6SAntoine Ténart 		goto free_ahash;
11531b44c5a6SAntoine Ténart 	}
11541b44c5a6SAntoine Ténart 
11551b44c5a6SAntoine Ténart 	crypto_ahash_clear_flags(tfm, ~0);
11561b44c5a6SAntoine Ténart 	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
11571b44c5a6SAntoine Ténart 
11586396bb22SKees Cook 	ipad = kcalloc(2, blocksize, GFP_KERNEL);
11591b44c5a6SAntoine Ténart 	if (!ipad) {
11601b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11611b44c5a6SAntoine Ténart 		goto free_request;
11621b44c5a6SAntoine Ténart 	}
11631b44c5a6SAntoine Ténart 
11641b44c5a6SAntoine Ténart 	opad = ipad + blocksize;
11651b44c5a6SAntoine Ténart 
11661b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad);
11671b44c5a6SAntoine Ténart 	if (ret)
11681b44c5a6SAntoine Ténart 		goto free_ipad;
11691b44c5a6SAntoine Ténart 
11701b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate);
11711b44c5a6SAntoine Ténart 	if (ret)
11721b44c5a6SAntoine Ténart 		goto free_ipad;
11731b44c5a6SAntoine Ténart 
11741b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate);
11751b44c5a6SAntoine Ténart 
11761b44c5a6SAntoine Ténart free_ipad:
11771b44c5a6SAntoine Ténart 	kfree(ipad);
11781b44c5a6SAntoine Ténart free_request:
11791b44c5a6SAntoine Ténart 	ahash_request_free(areq);
11801b44c5a6SAntoine Ténart free_ahash:
11811b44c5a6SAntoine Ténart 	crypto_free_ahash(tfm);
11821b44c5a6SAntoine Ténart 
11831b44c5a6SAntoine Ténart 	return ret;
11841b44c5a6SAntoine Ténart }
11851b44c5a6SAntoine Ténart 
118673f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key,
118773f36ea7SAntoine Tenart 				    unsigned int keylen, const char *alg,
118873f36ea7SAntoine Tenart 				    unsigned int state_sz)
11891b44c5a6SAntoine Ténart {
11901b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
119118e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
11921b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state istate, ostate;
119341abed7dSPascal van Leeuwen 	int ret;
11941b44c5a6SAntoine Ténart 
119573f36ea7SAntoine Tenart 	ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate);
11961b44c5a6SAntoine Ténart 	if (ret)
11971b44c5a6SAntoine Ténart 		return ret;
11981b44c5a6SAntoine Ténart 
119941abed7dSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr &&
120041abed7dSPascal van Leeuwen 	    (memcmp(ctx->ipad, istate.state, state_sz) ||
120141abed7dSPascal van Leeuwen 	     memcmp(ctx->opad, ostate.state, state_sz)))
12021b44c5a6SAntoine Ténart 		ctx->base.needs_inv = true;
12031b44c5a6SAntoine Ténart 
120473f36ea7SAntoine Tenart 	memcpy(ctx->ipad, &istate.state, state_sz);
120573f36ea7SAntoine Tenart 	memcpy(ctx->opad, &ostate.state, state_sz);
120642ef3bedSAntoine Ténart 
12071b44c5a6SAntoine Ténart 	return 0;
12081b44c5a6SAntoine Ténart }
12091b44c5a6SAntoine Ténart 
121073f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
121173f36ea7SAntoine Tenart 				     unsigned int keylen)
121273f36ea7SAntoine Tenart {
121373f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1",
121473f36ea7SAntoine Tenart 					SHA1_DIGEST_SIZE);
121573f36ea7SAntoine Tenart }
121673f36ea7SAntoine Tenart 
12171b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = {
12181b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1219062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
12201b44c5a6SAntoine Ténart 	.alg.ahash = {
12211b44c5a6SAntoine Ténart 		.init = safexcel_hmac_sha1_init,
12221b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12231b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12241b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12251b44c5a6SAntoine Ténart 		.digest = safexcel_hmac_sha1_digest,
12261b44c5a6SAntoine Ténart 		.setkey = safexcel_hmac_sha1_setkey,
12271b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12281b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12291b44c5a6SAntoine Ténart 		.halg = {
12301b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
12311b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12321b44c5a6SAntoine Ténart 			.base = {
12331b44c5a6SAntoine Ténart 				.cra_name = "hmac(sha1)",
12341b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-hmac-sha1",
1235aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12361b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1237b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
12381b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12391b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
12401b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12411b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
12421b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
12431b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
12441b44c5a6SAntoine Ténart 			},
12451b44c5a6SAntoine Ténart 		},
12461b44c5a6SAntoine Ténart 	},
12471b44c5a6SAntoine Ténart };
12481b44c5a6SAntoine Ténart 
12491b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq)
12501b44c5a6SAntoine Ténart {
12511b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
12521b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
12531b44c5a6SAntoine Ténart 
12541b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
12551b44c5a6SAntoine Ténart 
12561b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1257b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
12581b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
12596c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
126041abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
12611b44c5a6SAntoine Ténart 
12621b44c5a6SAntoine Ténart 	return 0;
12631b44c5a6SAntoine Ténart }
12641b44c5a6SAntoine Ténart 
12651b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq)
12661b44c5a6SAntoine Ténart {
12671b44c5a6SAntoine Ténart 	int ret = safexcel_sha256_init(areq);
12681b44c5a6SAntoine Ténart 
12691b44c5a6SAntoine Ténart 	if (ret)
12701b44c5a6SAntoine Ténart 		return ret;
12711b44c5a6SAntoine Ténart 
12721b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
12731b44c5a6SAntoine Ténart }
12741b44c5a6SAntoine Ténart 
12751b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = {
12761b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1277062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
12781b44c5a6SAntoine Ténart 	.alg.ahash = {
12791b44c5a6SAntoine Ténart 		.init = safexcel_sha256_init,
12801b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12811b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12821b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12831b44c5a6SAntoine Ténart 		.digest = safexcel_sha256_digest,
12841b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12851b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12861b44c5a6SAntoine Ténart 		.halg = {
12871b44c5a6SAntoine Ténart 			.digestsize = SHA256_DIGEST_SIZE,
12881b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12891b44c5a6SAntoine Ténart 			.base = {
12901b44c5a6SAntoine Ténart 				.cra_name = "sha256",
12911b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha256",
1292aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12931b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1294b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
12951b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12961b44c5a6SAntoine Ténart 				.cra_blocksize = SHA256_BLOCK_SIZE,
12971b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12981b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
12991b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
13001b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
13011b44c5a6SAntoine Ténart 			},
13021b44c5a6SAntoine Ténart 		},
13031b44c5a6SAntoine Ténart 	},
13041b44c5a6SAntoine Ténart };
13051b44c5a6SAntoine Ténart 
13061b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq)
13071b44c5a6SAntoine Ténart {
13081b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
13091b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
13101b44c5a6SAntoine Ténart 
13111b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
13121b44c5a6SAntoine Ténart 
13131b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1314b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
13151b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
13166c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
131741abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
13181b44c5a6SAntoine Ténart 
13191b44c5a6SAntoine Ténart 	return 0;
13201b44c5a6SAntoine Ténart }
13211b44c5a6SAntoine Ténart 
13221b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq)
13231b44c5a6SAntoine Ténart {
13241b44c5a6SAntoine Ténart 	int ret = safexcel_sha224_init(areq);
13251b44c5a6SAntoine Ténart 
13261b44c5a6SAntoine Ténart 	if (ret)
13271b44c5a6SAntoine Ténart 		return ret;
13281b44c5a6SAntoine Ténart 
13291b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
13301b44c5a6SAntoine Ténart }
13311b44c5a6SAntoine Ténart 
13321b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = {
13331b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1334062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
13351b44c5a6SAntoine Ténart 	.alg.ahash = {
13361b44c5a6SAntoine Ténart 		.init = safexcel_sha224_init,
13371b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
13381b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
13391b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
13401b44c5a6SAntoine Ténart 		.digest = safexcel_sha224_digest,
13411b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
13421b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
13431b44c5a6SAntoine Ténart 		.halg = {
13441b44c5a6SAntoine Ténart 			.digestsize = SHA224_DIGEST_SIZE,
13451b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
13461b44c5a6SAntoine Ténart 			.base = {
13471b44c5a6SAntoine Ténart 				.cra_name = "sha224",
13481b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha224",
1349aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
13501b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1351b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
13521b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
13531b44c5a6SAntoine Ténart 				.cra_blocksize = SHA224_BLOCK_SIZE,
13541b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
13551b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
13561b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
13571b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
13581b44c5a6SAntoine Ténart 			},
13591b44c5a6SAntoine Ténart 		},
13601b44c5a6SAntoine Ténart 	},
13611b44c5a6SAntoine Ténart };
136273f36ea7SAntoine Tenart 
13633ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key,
13643ad618d8SAntoine Tenart 				       unsigned int keylen)
13653ad618d8SAntoine Tenart {
13663ad618d8SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224",
13673ad618d8SAntoine Tenart 					SHA256_DIGEST_SIZE);
13683ad618d8SAntoine Tenart }
13693ad618d8SAntoine Tenart 
13703ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq)
13713ad618d8SAntoine Tenart {
137241abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
13733ad618d8SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
13743ad618d8SAntoine Tenart 
137541abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
137641abed7dSPascal van Leeuwen 
137741abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
137841abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE);
137941abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
138031fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
138131fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
138241abed7dSPascal van Leeuwen 
138341abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
138441abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
138541abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
13866c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
138741abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
138841abed7dSPascal van Leeuwen 	req->hmac = true;
138941abed7dSPascal van Leeuwen 
13903ad618d8SAntoine Tenart 	return 0;
13913ad618d8SAntoine Tenart }
13923ad618d8SAntoine Tenart 
13933ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq)
13943ad618d8SAntoine Tenart {
13953ad618d8SAntoine Tenart 	int ret = safexcel_hmac_sha224_init(areq);
13963ad618d8SAntoine Tenart 
13973ad618d8SAntoine Tenart 	if (ret)
13983ad618d8SAntoine Tenart 		return ret;
13993ad618d8SAntoine Tenart 
14003ad618d8SAntoine Tenart 	return safexcel_ahash_finup(areq);
14013ad618d8SAntoine Tenart }
14023ad618d8SAntoine Tenart 
14033ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = {
14043ad618d8SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1405062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
14063ad618d8SAntoine Tenart 	.alg.ahash = {
14073ad618d8SAntoine Tenart 		.init = safexcel_hmac_sha224_init,
14083ad618d8SAntoine Tenart 		.update = safexcel_ahash_update,
14093ad618d8SAntoine Tenart 		.final = safexcel_ahash_final,
14103ad618d8SAntoine Tenart 		.finup = safexcel_ahash_finup,
14113ad618d8SAntoine Tenart 		.digest = safexcel_hmac_sha224_digest,
14123ad618d8SAntoine Tenart 		.setkey = safexcel_hmac_sha224_setkey,
14133ad618d8SAntoine Tenart 		.export = safexcel_ahash_export,
14143ad618d8SAntoine Tenart 		.import = safexcel_ahash_import,
14153ad618d8SAntoine Tenart 		.halg = {
14163ad618d8SAntoine Tenart 			.digestsize = SHA224_DIGEST_SIZE,
14173ad618d8SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
14183ad618d8SAntoine Tenart 			.base = {
14193ad618d8SAntoine Tenart 				.cra_name = "hmac(sha224)",
14203ad618d8SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha224",
1421aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
14223ad618d8SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1423b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
14243ad618d8SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
14253ad618d8SAntoine Tenart 				.cra_blocksize = SHA224_BLOCK_SIZE,
14263ad618d8SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
14273ad618d8SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
14283ad618d8SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
14293ad618d8SAntoine Tenart 				.cra_module = THIS_MODULE,
14303ad618d8SAntoine Tenart 			},
14313ad618d8SAntoine Tenart 		},
14323ad618d8SAntoine Tenart 	},
14333ad618d8SAntoine Tenart };
14343ad618d8SAntoine Tenart 
143573f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
143673f36ea7SAntoine Tenart 				     unsigned int keylen)
143773f36ea7SAntoine Tenart {
143873f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256",
143973f36ea7SAntoine Tenart 					SHA256_DIGEST_SIZE);
144073f36ea7SAntoine Tenart }
144173f36ea7SAntoine Tenart 
144273f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq)
144373f36ea7SAntoine Tenart {
144441abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
144573f36ea7SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
144673f36ea7SAntoine Tenart 
144741abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
144841abed7dSPascal van Leeuwen 
144941abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
145041abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE);
145141abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
145231fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
145331fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
145441abed7dSPascal van Leeuwen 
145541abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
145641abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
145741abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
14586c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
145941abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
146041abed7dSPascal van Leeuwen 	req->hmac = true;
146141abed7dSPascal van Leeuwen 
146273f36ea7SAntoine Tenart 	return 0;
146373f36ea7SAntoine Tenart }
146473f36ea7SAntoine Tenart 
146573f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq)
146673f36ea7SAntoine Tenart {
146773f36ea7SAntoine Tenart 	int ret = safexcel_hmac_sha256_init(areq);
146873f36ea7SAntoine Tenart 
146973f36ea7SAntoine Tenart 	if (ret)
147073f36ea7SAntoine Tenart 		return ret;
147173f36ea7SAntoine Tenart 
147273f36ea7SAntoine Tenart 	return safexcel_ahash_finup(areq);
147373f36ea7SAntoine Tenart }
147473f36ea7SAntoine Tenart 
147573f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = {
147673f36ea7SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1477062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
147873f36ea7SAntoine Tenart 	.alg.ahash = {
147973f36ea7SAntoine Tenart 		.init = safexcel_hmac_sha256_init,
148073f36ea7SAntoine Tenart 		.update = safexcel_ahash_update,
148173f36ea7SAntoine Tenart 		.final = safexcel_ahash_final,
148273f36ea7SAntoine Tenart 		.finup = safexcel_ahash_finup,
148373f36ea7SAntoine Tenart 		.digest = safexcel_hmac_sha256_digest,
148473f36ea7SAntoine Tenart 		.setkey = safexcel_hmac_sha256_setkey,
148573f36ea7SAntoine Tenart 		.export = safexcel_ahash_export,
148673f36ea7SAntoine Tenart 		.import = safexcel_ahash_import,
148773f36ea7SAntoine Tenart 		.halg = {
148873f36ea7SAntoine Tenart 			.digestsize = SHA256_DIGEST_SIZE,
148973f36ea7SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
149073f36ea7SAntoine Tenart 			.base = {
149173f36ea7SAntoine Tenart 				.cra_name = "hmac(sha256)",
149273f36ea7SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha256",
1493aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
149473f36ea7SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1495b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
149673f36ea7SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
149773f36ea7SAntoine Tenart 				.cra_blocksize = SHA256_BLOCK_SIZE,
149873f36ea7SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
149973f36ea7SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
150073f36ea7SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
150173f36ea7SAntoine Tenart 				.cra_module = THIS_MODULE,
150273f36ea7SAntoine Tenart 			},
150373f36ea7SAntoine Tenart 		},
150473f36ea7SAntoine Tenart 	},
150573f36ea7SAntoine Tenart };
1506b460edb6SAntoine Tenart 
1507b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq)
1508b460edb6SAntoine Tenart {
1509b460edb6SAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1510b460edb6SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1511b460edb6SAntoine Tenart 
1512b460edb6SAntoine Tenart 	memset(req, 0, sizeof(*req));
1513b460edb6SAntoine Tenart 
1514b460edb6SAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
1515b460edb6SAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1516b460edb6SAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
15176c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
151841abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
1519b460edb6SAntoine Tenart 
1520b460edb6SAntoine Tenart 	return 0;
1521b460edb6SAntoine Tenart }
1522b460edb6SAntoine Tenart 
1523b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq)
1524b460edb6SAntoine Tenart {
1525b460edb6SAntoine Tenart 	int ret = safexcel_sha512_init(areq);
1526b460edb6SAntoine Tenart 
1527b460edb6SAntoine Tenart 	if (ret)
1528b460edb6SAntoine Tenart 		return ret;
1529b460edb6SAntoine Tenart 
1530b460edb6SAntoine Tenart 	return safexcel_ahash_finup(areq);
1531b460edb6SAntoine Tenart }
1532b460edb6SAntoine Tenart 
1533b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = {
1534b460edb6SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1535062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
1536b460edb6SAntoine Tenart 	.alg.ahash = {
1537b460edb6SAntoine Tenart 		.init = safexcel_sha512_init,
1538b460edb6SAntoine Tenart 		.update = safexcel_ahash_update,
1539b460edb6SAntoine Tenart 		.final = safexcel_ahash_final,
1540b460edb6SAntoine Tenart 		.finup = safexcel_ahash_finup,
1541b460edb6SAntoine Tenart 		.digest = safexcel_sha512_digest,
1542b460edb6SAntoine Tenart 		.export = safexcel_ahash_export,
1543b460edb6SAntoine Tenart 		.import = safexcel_ahash_import,
1544b460edb6SAntoine Tenart 		.halg = {
1545b460edb6SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
1546b460edb6SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
1547b460edb6SAntoine Tenart 			.base = {
1548b460edb6SAntoine Tenart 				.cra_name = "sha512",
1549b460edb6SAntoine Tenart 				.cra_driver_name = "safexcel-sha512",
1550aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1551b460edb6SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1552b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1553b460edb6SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1554b460edb6SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
1555b460edb6SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1556b460edb6SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
1557b460edb6SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
1558b460edb6SAntoine Tenart 				.cra_module = THIS_MODULE,
1559b460edb6SAntoine Tenart 			},
1560b460edb6SAntoine Tenart 		},
1561b460edb6SAntoine Tenart 	},
1562b460edb6SAntoine Tenart };
15630de54fb1SAntoine Tenart 
15649e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq)
15659e46eafdSAntoine Tenart {
15669e46eafdSAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
15679e46eafdSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
15689e46eafdSAntoine Tenart 
15699e46eafdSAntoine Tenart 	memset(req, 0, sizeof(*req));
15709e46eafdSAntoine Tenart 
15719e46eafdSAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
15729e46eafdSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
15739e46eafdSAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
15746c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
157541abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
15769e46eafdSAntoine Tenart 
15779e46eafdSAntoine Tenart 	return 0;
15789e46eafdSAntoine Tenart }
15799e46eafdSAntoine Tenart 
15809e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq)
15819e46eafdSAntoine Tenart {
15829e46eafdSAntoine Tenart 	int ret = safexcel_sha384_init(areq);
15839e46eafdSAntoine Tenart 
15849e46eafdSAntoine Tenart 	if (ret)
15859e46eafdSAntoine Tenart 		return ret;
15869e46eafdSAntoine Tenart 
15879e46eafdSAntoine Tenart 	return safexcel_ahash_finup(areq);
15889e46eafdSAntoine Tenart }
15899e46eafdSAntoine Tenart 
15909e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = {
15919e46eafdSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1592062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
15939e46eafdSAntoine Tenart 	.alg.ahash = {
15949e46eafdSAntoine Tenart 		.init = safexcel_sha384_init,
15959e46eafdSAntoine Tenart 		.update = safexcel_ahash_update,
15969e46eafdSAntoine Tenart 		.final = safexcel_ahash_final,
15979e46eafdSAntoine Tenart 		.finup = safexcel_ahash_finup,
15989e46eafdSAntoine Tenart 		.digest = safexcel_sha384_digest,
15999e46eafdSAntoine Tenart 		.export = safexcel_ahash_export,
16009e46eafdSAntoine Tenart 		.import = safexcel_ahash_import,
16019e46eafdSAntoine Tenart 		.halg = {
16029e46eafdSAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
16039e46eafdSAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
16049e46eafdSAntoine Tenart 			.base = {
16059e46eafdSAntoine Tenart 				.cra_name = "sha384",
16069e46eafdSAntoine Tenart 				.cra_driver_name = "safexcel-sha384",
1607aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
16089e46eafdSAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1609b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
16109e46eafdSAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16119e46eafdSAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
16129e46eafdSAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
16139e46eafdSAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
16149e46eafdSAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
16159e46eafdSAntoine Tenart 				.cra_module = THIS_MODULE,
16169e46eafdSAntoine Tenart 			},
16179e46eafdSAntoine Tenart 		},
16189e46eafdSAntoine Tenart 	},
16199e46eafdSAntoine Tenart };
16209e46eafdSAntoine Tenart 
16210de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key,
16220de54fb1SAntoine Tenart 				       unsigned int keylen)
16230de54fb1SAntoine Tenart {
16240de54fb1SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512",
16250de54fb1SAntoine Tenart 					SHA512_DIGEST_SIZE);
16260de54fb1SAntoine Tenart }
16270de54fb1SAntoine Tenart 
16280de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq)
16290de54fb1SAntoine Tenart {
163041abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
16310de54fb1SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
16320de54fb1SAntoine Tenart 
163341abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
163441abed7dSPascal van Leeuwen 
163541abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
163641abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE);
163741abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
163831fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
163931fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
164041abed7dSPascal van Leeuwen 
164141abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
164241abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
164341abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
16446c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
164541abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
164641abed7dSPascal van Leeuwen 	req->hmac = true;
164741abed7dSPascal van Leeuwen 
16480de54fb1SAntoine Tenart 	return 0;
16490de54fb1SAntoine Tenart }
16500de54fb1SAntoine Tenart 
16510de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq)
16520de54fb1SAntoine Tenart {
16530de54fb1SAntoine Tenart 	int ret = safexcel_hmac_sha512_init(areq);
16540de54fb1SAntoine Tenart 
16550de54fb1SAntoine Tenart 	if (ret)
16560de54fb1SAntoine Tenart 		return ret;
16570de54fb1SAntoine Tenart 
16580de54fb1SAntoine Tenart 	return safexcel_ahash_finup(areq);
16590de54fb1SAntoine Tenart }
16600de54fb1SAntoine Tenart 
16610de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = {
16620de54fb1SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1663062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
16640de54fb1SAntoine Tenart 	.alg.ahash = {
16650de54fb1SAntoine Tenart 		.init = safexcel_hmac_sha512_init,
16660de54fb1SAntoine Tenart 		.update = safexcel_ahash_update,
16670de54fb1SAntoine Tenart 		.final = safexcel_ahash_final,
16680de54fb1SAntoine Tenart 		.finup = safexcel_ahash_finup,
16690de54fb1SAntoine Tenart 		.digest = safexcel_hmac_sha512_digest,
16700de54fb1SAntoine Tenart 		.setkey = safexcel_hmac_sha512_setkey,
16710de54fb1SAntoine Tenart 		.export = safexcel_ahash_export,
16720de54fb1SAntoine Tenart 		.import = safexcel_ahash_import,
16730de54fb1SAntoine Tenart 		.halg = {
16740de54fb1SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
16750de54fb1SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
16760de54fb1SAntoine Tenart 			.base = {
16770de54fb1SAntoine Tenart 				.cra_name = "hmac(sha512)",
16780de54fb1SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha512",
1679aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
16800de54fb1SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1681b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
16820de54fb1SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16830de54fb1SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
16840de54fb1SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
16850de54fb1SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
16860de54fb1SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
16870de54fb1SAntoine Tenart 				.cra_module = THIS_MODULE,
16880de54fb1SAntoine Tenart 			},
16890de54fb1SAntoine Tenart 		},
16900de54fb1SAntoine Tenart 	},
16910de54fb1SAntoine Tenart };
16921f5d5d98SAntoine Tenart 
16931f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key,
16941f5d5d98SAntoine Tenart 				       unsigned int keylen)
16951f5d5d98SAntoine Tenart {
16961f5d5d98SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384",
16971f5d5d98SAntoine Tenart 					SHA512_DIGEST_SIZE);
16981f5d5d98SAntoine Tenart }
16991f5d5d98SAntoine Tenart 
17001f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq)
17011f5d5d98SAntoine Tenart {
170241abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
17031f5d5d98SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
17041f5d5d98SAntoine Tenart 
170541abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
170641abed7dSPascal van Leeuwen 
170741abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
170841abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE);
170941abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
171031fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
171131fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
171241abed7dSPascal van Leeuwen 
171341abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
171441abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
171541abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
17166c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
171741abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
171841abed7dSPascal van Leeuwen 	req->hmac = true;
171941abed7dSPascal van Leeuwen 
17201f5d5d98SAntoine Tenart 	return 0;
17211f5d5d98SAntoine Tenart }
17221f5d5d98SAntoine Tenart 
17231f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq)
17241f5d5d98SAntoine Tenart {
17251f5d5d98SAntoine Tenart 	int ret = safexcel_hmac_sha384_init(areq);
17261f5d5d98SAntoine Tenart 
17271f5d5d98SAntoine Tenart 	if (ret)
17281f5d5d98SAntoine Tenart 		return ret;
17291f5d5d98SAntoine Tenart 
17301f5d5d98SAntoine Tenart 	return safexcel_ahash_finup(areq);
17311f5d5d98SAntoine Tenart }
17321f5d5d98SAntoine Tenart 
17331f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = {
17341f5d5d98SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1735062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
17361f5d5d98SAntoine Tenart 	.alg.ahash = {
17371f5d5d98SAntoine Tenart 		.init = safexcel_hmac_sha384_init,
17381f5d5d98SAntoine Tenart 		.update = safexcel_ahash_update,
17391f5d5d98SAntoine Tenart 		.final = safexcel_ahash_final,
17401f5d5d98SAntoine Tenart 		.finup = safexcel_ahash_finup,
17411f5d5d98SAntoine Tenart 		.digest = safexcel_hmac_sha384_digest,
17421f5d5d98SAntoine Tenart 		.setkey = safexcel_hmac_sha384_setkey,
17431f5d5d98SAntoine Tenart 		.export = safexcel_ahash_export,
17441f5d5d98SAntoine Tenart 		.import = safexcel_ahash_import,
17451f5d5d98SAntoine Tenart 		.halg = {
17461f5d5d98SAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
17471f5d5d98SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
17481f5d5d98SAntoine Tenart 			.base = {
17491f5d5d98SAntoine Tenart 				.cra_name = "hmac(sha384)",
17501f5d5d98SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha384",
1751aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
17521f5d5d98SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1753b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
17541f5d5d98SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
17551f5d5d98SAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
17561f5d5d98SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
17571f5d5d98SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
17581f5d5d98SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
17591f5d5d98SAntoine Tenart 				.cra_module = THIS_MODULE,
17601f5d5d98SAntoine Tenart 			},
17611f5d5d98SAntoine Tenart 		},
17621f5d5d98SAntoine Tenart 	},
17631f5d5d98SAntoine Tenart };
1764293f89cfSOfer Heifetz 
1765293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq)
1766293f89cfSOfer Heifetz {
1767293f89cfSOfer Heifetz 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1768293f89cfSOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1769293f89cfSOfer Heifetz 
1770293f89cfSOfer Heifetz 	memset(req, 0, sizeof(*req));
1771293f89cfSOfer Heifetz 
1772293f89cfSOfer Heifetz 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
1773293f89cfSOfer Heifetz 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1774293f89cfSOfer Heifetz 	req->state_sz = MD5_DIGEST_SIZE;
17756c1c09b3SPascal van Leeuwen 	req->digest_sz = MD5_DIGEST_SIZE;
177641abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
1777293f89cfSOfer Heifetz 
1778293f89cfSOfer Heifetz 	return 0;
1779293f89cfSOfer Heifetz }
1780293f89cfSOfer Heifetz 
1781293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq)
1782293f89cfSOfer Heifetz {
1783293f89cfSOfer Heifetz 	int ret = safexcel_md5_init(areq);
1784293f89cfSOfer Heifetz 
1785293f89cfSOfer Heifetz 	if (ret)
1786293f89cfSOfer Heifetz 		return ret;
1787293f89cfSOfer Heifetz 
1788293f89cfSOfer Heifetz 	return safexcel_ahash_finup(areq);
1789293f89cfSOfer Heifetz }
1790293f89cfSOfer Heifetz 
1791293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = {
1792293f89cfSOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1793062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1794293f89cfSOfer Heifetz 	.alg.ahash = {
1795293f89cfSOfer Heifetz 		.init = safexcel_md5_init,
1796293f89cfSOfer Heifetz 		.update = safexcel_ahash_update,
1797293f89cfSOfer Heifetz 		.final = safexcel_ahash_final,
1798293f89cfSOfer Heifetz 		.finup = safexcel_ahash_finup,
1799293f89cfSOfer Heifetz 		.digest = safexcel_md5_digest,
1800293f89cfSOfer Heifetz 		.export = safexcel_ahash_export,
1801293f89cfSOfer Heifetz 		.import = safexcel_ahash_import,
1802293f89cfSOfer Heifetz 		.halg = {
1803293f89cfSOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1804293f89cfSOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1805293f89cfSOfer Heifetz 			.base = {
1806293f89cfSOfer Heifetz 				.cra_name = "md5",
1807293f89cfSOfer Heifetz 				.cra_driver_name = "safexcel-md5",
1808aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1809293f89cfSOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1810b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1811293f89cfSOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1812293f89cfSOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1813293f89cfSOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1814293f89cfSOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1815293f89cfSOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1816293f89cfSOfer Heifetz 				.cra_module = THIS_MODULE,
1817293f89cfSOfer Heifetz 			},
1818293f89cfSOfer Heifetz 		},
1819293f89cfSOfer Heifetz 	},
1820293f89cfSOfer Heifetz };
1821b471e4b9SOfer Heifetz 
1822b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq)
1823b471e4b9SOfer Heifetz {
182441abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1825b471e4b9SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1826b471e4b9SOfer Heifetz 
182741abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
182841abed7dSPascal van Leeuwen 
182941abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
183041abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, MD5_DIGEST_SIZE);
183141abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
183231fb084cSPascal van Leeuwen 	req->len	= MD5_HMAC_BLOCK_SIZE;
183331fb084cSPascal van Leeuwen 	req->processed	= MD5_HMAC_BLOCK_SIZE;
183441abed7dSPascal van Leeuwen 
183541abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
183641abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
183741abed7dSPascal van Leeuwen 	req->state_sz = MD5_DIGEST_SIZE;
18386c1c09b3SPascal van Leeuwen 	req->digest_sz = MD5_DIGEST_SIZE;
183941abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
184085b36ee8SPascal van Leeuwen 	req->len_is_le = true; /* MD5 is little endian! ... */
184141abed7dSPascal van Leeuwen 	req->hmac = true;
184241abed7dSPascal van Leeuwen 
1843b471e4b9SOfer Heifetz 	return 0;
1844b471e4b9SOfer Heifetz }
1845b471e4b9SOfer Heifetz 
1846b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key,
1847b471e4b9SOfer Heifetz 				     unsigned int keylen)
1848b471e4b9SOfer Heifetz {
1849b471e4b9SOfer Heifetz 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5",
1850b471e4b9SOfer Heifetz 					MD5_DIGEST_SIZE);
1851b471e4b9SOfer Heifetz }
1852b471e4b9SOfer Heifetz 
1853b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq)
1854b471e4b9SOfer Heifetz {
1855b471e4b9SOfer Heifetz 	int ret = safexcel_hmac_md5_init(areq);
1856b471e4b9SOfer Heifetz 
1857b471e4b9SOfer Heifetz 	if (ret)
1858b471e4b9SOfer Heifetz 		return ret;
1859b471e4b9SOfer Heifetz 
1860b471e4b9SOfer Heifetz 	return safexcel_ahash_finup(areq);
1861b471e4b9SOfer Heifetz }
1862b471e4b9SOfer Heifetz 
1863b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = {
1864b471e4b9SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1865062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1866b471e4b9SOfer Heifetz 	.alg.ahash = {
1867b471e4b9SOfer Heifetz 		.init = safexcel_hmac_md5_init,
1868b471e4b9SOfer Heifetz 		.update = safexcel_ahash_update,
1869b471e4b9SOfer Heifetz 		.final = safexcel_ahash_final,
1870b471e4b9SOfer Heifetz 		.finup = safexcel_ahash_finup,
1871b471e4b9SOfer Heifetz 		.digest = safexcel_hmac_md5_digest,
1872b471e4b9SOfer Heifetz 		.setkey = safexcel_hmac_md5_setkey,
1873b471e4b9SOfer Heifetz 		.export = safexcel_ahash_export,
1874b471e4b9SOfer Heifetz 		.import = safexcel_ahash_import,
1875b471e4b9SOfer Heifetz 		.halg = {
1876b471e4b9SOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1877b471e4b9SOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1878b471e4b9SOfer Heifetz 			.base = {
1879b471e4b9SOfer Heifetz 				.cra_name = "hmac(md5)",
1880b471e4b9SOfer Heifetz 				.cra_driver_name = "safexcel-hmac-md5",
1881aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1882b471e4b9SOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1883b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1884b471e4b9SOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1885b471e4b9SOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1886b471e4b9SOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1887b471e4b9SOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1888b471e4b9SOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1889b471e4b9SOfer Heifetz 				.cra_module = THIS_MODULE,
1890b471e4b9SOfer Heifetz 			},
1891b471e4b9SOfer Heifetz 		},
1892b471e4b9SOfer Heifetz 	},
1893b471e4b9SOfer Heifetz };
1894a7cf8658SPascal van Leeuwen 
1895a7cf8658SPascal van Leeuwen static int safexcel_crc32_cra_init(struct crypto_tfm *tfm)
1896a7cf8658SPascal van Leeuwen {
1897a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
1898a7cf8658SPascal van Leeuwen 	int ret = safexcel_ahash_cra_init(tfm);
1899a7cf8658SPascal van Leeuwen 
1900a7cf8658SPascal van Leeuwen 	/* Default 'key' is all zeroes */
1901a7cf8658SPascal van Leeuwen 	memset(ctx->ipad, 0, sizeof(u32));
1902a7cf8658SPascal van Leeuwen 	return ret;
1903a7cf8658SPascal van Leeuwen }
1904a7cf8658SPascal van Leeuwen 
1905a7cf8658SPascal van Leeuwen static int safexcel_crc32_init(struct ahash_request *areq)
1906a7cf8658SPascal van Leeuwen {
1907a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1908a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1909a7cf8658SPascal van Leeuwen 
1910a7cf8658SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1911a7cf8658SPascal van Leeuwen 
1912a7cf8658SPascal van Leeuwen 	/* Start from loaded key */
191313a1bb93SPascal van Leeuwen 	req->state[0]	= (__force __le32)le32_to_cpu(~ctx->ipad[0]);
1914a7cf8658SPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
1915a7cf8658SPascal van Leeuwen 	req->len	= sizeof(u32);
1916a7cf8658SPascal van Leeuwen 	req->processed	= sizeof(u32);
1917a7cf8658SPascal van Leeuwen 
1918a7cf8658SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32;
1919a7cf8658SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_XCM;
1920a7cf8658SPascal van Leeuwen 	req->state_sz = sizeof(u32);
19216c1c09b3SPascal van Leeuwen 	req->digest_sz = sizeof(u32);
1922a7cf8658SPascal van Leeuwen 	req->block_sz = sizeof(u32);
1923a7cf8658SPascal van Leeuwen 
1924a7cf8658SPascal van Leeuwen 	return 0;
1925a7cf8658SPascal van Leeuwen }
1926a7cf8658SPascal van Leeuwen 
1927a7cf8658SPascal van Leeuwen static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key,
1928a7cf8658SPascal van Leeuwen 				 unsigned int keylen)
1929a7cf8658SPascal van Leeuwen {
1930a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1931a7cf8658SPascal van Leeuwen 
1932674f368aSEric Biggers 	if (keylen != sizeof(u32))
1933a7cf8658SPascal van Leeuwen 		return -EINVAL;
1934a7cf8658SPascal van Leeuwen 
1935a7cf8658SPascal van Leeuwen 	memcpy(ctx->ipad, key, sizeof(u32));
1936a7cf8658SPascal van Leeuwen 	return 0;
1937a7cf8658SPascal van Leeuwen }
1938a7cf8658SPascal van Leeuwen 
1939a7cf8658SPascal van Leeuwen static int safexcel_crc32_digest(struct ahash_request *areq)
1940a7cf8658SPascal van Leeuwen {
1941a7cf8658SPascal van Leeuwen 	return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq);
1942a7cf8658SPascal van Leeuwen }
1943a7cf8658SPascal van Leeuwen 
1944a7cf8658SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_crc32 = {
1945a7cf8658SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1946a7cf8658SPascal van Leeuwen 	.algo_mask = 0,
1947a7cf8658SPascal van Leeuwen 	.alg.ahash = {
1948a7cf8658SPascal van Leeuwen 		.init = safexcel_crc32_init,
1949a7cf8658SPascal van Leeuwen 		.update = safexcel_ahash_update,
1950a7cf8658SPascal van Leeuwen 		.final = safexcel_ahash_final,
1951a7cf8658SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
1952a7cf8658SPascal van Leeuwen 		.digest = safexcel_crc32_digest,
1953a7cf8658SPascal van Leeuwen 		.setkey = safexcel_crc32_setkey,
1954a7cf8658SPascal van Leeuwen 		.export = safexcel_ahash_export,
1955a7cf8658SPascal van Leeuwen 		.import = safexcel_ahash_import,
1956a7cf8658SPascal van Leeuwen 		.halg = {
1957a7cf8658SPascal van Leeuwen 			.digestsize = sizeof(u32),
1958a7cf8658SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
1959a7cf8658SPascal van Leeuwen 			.base = {
1960a7cf8658SPascal van Leeuwen 				.cra_name = "crc32",
1961a7cf8658SPascal van Leeuwen 				.cra_driver_name = "safexcel-crc32",
1962a7cf8658SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1963a7cf8658SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_OPTIONAL_KEY |
1964a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_ASYNC |
1965b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1966a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1967a7cf8658SPascal van Leeuwen 				.cra_blocksize = 1,
1968a7cf8658SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1969a7cf8658SPascal van Leeuwen 				.cra_init = safexcel_crc32_cra_init,
1970a7cf8658SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
1971a7cf8658SPascal van Leeuwen 				.cra_module = THIS_MODULE,
1972a7cf8658SPascal van Leeuwen 			},
1973a7cf8658SPascal van Leeuwen 		},
1974a7cf8658SPascal van Leeuwen 	},
1975a7cf8658SPascal van Leeuwen };
1976b98687bbSPascal van Leeuwen 
1977b98687bbSPascal van Leeuwen static int safexcel_cbcmac_init(struct ahash_request *areq)
1978b98687bbSPascal van Leeuwen {
1979b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1980b98687bbSPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1981b98687bbSPascal van Leeuwen 
1982b98687bbSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1983b98687bbSPascal van Leeuwen 
1984b98687bbSPascal van Leeuwen 	/* Start from loaded keys */
1985b98687bbSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, ctx->key_sz);
1986b98687bbSPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
1987b98687bbSPascal van Leeuwen 	req->len	= AES_BLOCK_SIZE;
1988b98687bbSPascal van Leeuwen 	req->processed	= AES_BLOCK_SIZE;
1989b98687bbSPascal van Leeuwen 
1990b98687bbSPascal van Leeuwen 	req->digest   = CONTEXT_CONTROL_DIGEST_XCM;
1991b98687bbSPascal van Leeuwen 	req->state_sz = ctx->key_sz;
19926c1c09b3SPascal van Leeuwen 	req->digest_sz = AES_BLOCK_SIZE;
1993b98687bbSPascal van Leeuwen 	req->block_sz = AES_BLOCK_SIZE;
1994b98687bbSPascal van Leeuwen 	req->xcbcmac  = true;
1995b98687bbSPascal van Leeuwen 
1996b98687bbSPascal van Leeuwen 	return 0;
1997b98687bbSPascal van Leeuwen }
1998b98687bbSPascal van Leeuwen 
1999b98687bbSPascal van Leeuwen static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
2000b98687bbSPascal van Leeuwen 				 unsigned int len)
2001b98687bbSPascal van Leeuwen {
2002b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
2003b98687bbSPascal van Leeuwen 	struct crypto_aes_ctx aes;
2004b98687bbSPascal van Leeuwen 	int ret, i;
2005b98687bbSPascal van Leeuwen 
2006b98687bbSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
2007674f368aSEric Biggers 	if (ret)
2008b98687bbSPascal van Leeuwen 		return ret;
2009b98687bbSPascal van Leeuwen 
2010b98687bbSPascal van Leeuwen 	memset(ctx->ipad, 0, 2 * AES_BLOCK_SIZE);
2011b98687bbSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
201213a1bb93SPascal van Leeuwen 		ctx->ipad[i + 8] = (__force __le32)cpu_to_be32(aes.key_enc[i]);
2013b98687bbSPascal van Leeuwen 
2014b98687bbSPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
2015b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
2016b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2017b98687bbSPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
2018b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
2019b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2020b98687bbSPascal van Leeuwen 	} else {
2021b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
2022b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2023b98687bbSPascal van Leeuwen 	}
202438f21b4bSPascal van Leeuwen 	ctx->cbcmac  = true;
2025b98687bbSPascal van Leeuwen 
2026b98687bbSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
2027b98687bbSPascal van Leeuwen 	return 0;
2028b98687bbSPascal van Leeuwen }
2029b98687bbSPascal van Leeuwen 
2030b98687bbSPascal van Leeuwen static int safexcel_cbcmac_digest(struct ahash_request *areq)
2031b98687bbSPascal van Leeuwen {
2032b98687bbSPascal van Leeuwen 	return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq);
2033b98687bbSPascal van Leeuwen }
2034b98687bbSPascal van Leeuwen 
2035b98687bbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbcmac = {
2036b98687bbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2037b98687bbSPascal van Leeuwen 	.algo_mask = 0,
2038b98687bbSPascal van Leeuwen 	.alg.ahash = {
2039b98687bbSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
2040b98687bbSPascal van Leeuwen 		.update = safexcel_ahash_update,
2041b98687bbSPascal van Leeuwen 		.final = safexcel_ahash_final,
2042b98687bbSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
2043b98687bbSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
2044b98687bbSPascal van Leeuwen 		.setkey = safexcel_cbcmac_setkey,
2045b98687bbSPascal van Leeuwen 		.export = safexcel_ahash_export,
2046b98687bbSPascal van Leeuwen 		.import = safexcel_ahash_import,
2047b98687bbSPascal van Leeuwen 		.halg = {
2048b98687bbSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
2049b98687bbSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2050b98687bbSPascal van Leeuwen 			.base = {
2051b98687bbSPascal van Leeuwen 				.cra_name = "cbcmac(aes)",
2052b98687bbSPascal van Leeuwen 				.cra_driver_name = "safexcel-cbcmac-aes",
2053b98687bbSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2054b98687bbSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2055b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
2056b98687bbSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
2057b98687bbSPascal van Leeuwen 				.cra_blocksize = 1,
2058b98687bbSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2059b98687bbSPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
2060b98687bbSPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
2061b98687bbSPascal van Leeuwen 				.cra_module = THIS_MODULE,
2062b98687bbSPascal van Leeuwen 			},
2063b98687bbSPascal van Leeuwen 		},
2064b98687bbSPascal van Leeuwen 	},
2065b98687bbSPascal van Leeuwen };
206638f21b4bSPascal van Leeuwen 
206738f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
206838f21b4bSPascal van Leeuwen 				 unsigned int len)
206938f21b4bSPascal van Leeuwen {
207038f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
207138f21b4bSPascal van Leeuwen 	struct crypto_aes_ctx aes;
207238f21b4bSPascal van Leeuwen 	u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)];
207338f21b4bSPascal van Leeuwen 	int ret, i;
207438f21b4bSPascal van Leeuwen 
207538f21b4bSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
2076674f368aSEric Biggers 	if (ret)
207738f21b4bSPascal van Leeuwen 		return ret;
207838f21b4bSPascal van Leeuwen 
207938f21b4bSPascal van Leeuwen 	/* precompute the XCBC key material */
208038f21b4bSPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK);
208138f21b4bSPascal van Leeuwen 	crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) &
208238f21b4bSPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
208338f21b4bSPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->kaes, key, len);
208438f21b4bSPascal van Leeuwen 	if (ret)
208538f21b4bSPascal van Leeuwen 		return ret;
208638f21b4bSPascal van Leeuwen 
208738f21b4bSPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
208838f21b4bSPascal van Leeuwen 		"\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1");
208938f21b4bSPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp,
209038f21b4bSPascal van Leeuwen 		"\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2");
209138f21b4bSPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + AES_BLOCK_SIZE,
209238f21b4bSPascal van Leeuwen 		"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3");
209338f21b4bSPascal van Leeuwen 	for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++)
209413a1bb93SPascal van Leeuwen 		ctx->ipad[i] =
209513a1bb93SPascal van Leeuwen 			cpu_to_le32((__force u32)cpu_to_be32(key_tmp[i]));
209638f21b4bSPascal van Leeuwen 
209738f21b4bSPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK);
209838f21b4bSPascal van Leeuwen 	crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) &
209938f21b4bSPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
210038f21b4bSPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->kaes,
210138f21b4bSPascal van Leeuwen 				   (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
210238f21b4bSPascal van Leeuwen 				   AES_MIN_KEY_SIZE);
210338f21b4bSPascal van Leeuwen 	if (ret)
210438f21b4bSPascal van Leeuwen 		return ret;
210538f21b4bSPascal van Leeuwen 
210638f21b4bSPascal van Leeuwen 	ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
210738f21b4bSPascal van Leeuwen 	ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
210838f21b4bSPascal van Leeuwen 	ctx->cbcmac = false;
210938f21b4bSPascal van Leeuwen 
211038f21b4bSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
211138f21b4bSPascal van Leeuwen 	return 0;
211238f21b4bSPascal van Leeuwen }
211338f21b4bSPascal van Leeuwen 
211438f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm)
211538f21b4bSPascal van Leeuwen {
211638f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
211738f21b4bSPascal van Leeuwen 
211838f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_init(tfm);
211938f21b4bSPascal van Leeuwen 	ctx->kaes = crypto_alloc_cipher("aes", 0, 0);
212027018ab1SYueHaibing 	return PTR_ERR_OR_ZERO(ctx->kaes);
212138f21b4bSPascal van Leeuwen }
212238f21b4bSPascal van Leeuwen 
212338f21b4bSPascal van Leeuwen static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm)
212438f21b4bSPascal van Leeuwen {
212538f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
212638f21b4bSPascal van Leeuwen 
212738f21b4bSPascal van Leeuwen 	crypto_free_cipher(ctx->kaes);
212838f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
212938f21b4bSPascal van Leeuwen }
213038f21b4bSPascal van Leeuwen 
213138f21b4bSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xcbcmac = {
213238f21b4bSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
213338f21b4bSPascal van Leeuwen 	.algo_mask = 0,
213438f21b4bSPascal van Leeuwen 	.alg.ahash = {
213538f21b4bSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
213638f21b4bSPascal van Leeuwen 		.update = safexcel_ahash_update,
213738f21b4bSPascal van Leeuwen 		.final = safexcel_ahash_final,
213838f21b4bSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
213938f21b4bSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
214038f21b4bSPascal van Leeuwen 		.setkey = safexcel_xcbcmac_setkey,
214138f21b4bSPascal van Leeuwen 		.export = safexcel_ahash_export,
214238f21b4bSPascal van Leeuwen 		.import = safexcel_ahash_import,
214338f21b4bSPascal van Leeuwen 		.halg = {
214438f21b4bSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
214538f21b4bSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
214638f21b4bSPascal van Leeuwen 			.base = {
214738f21b4bSPascal van Leeuwen 				.cra_name = "xcbc(aes)",
214838f21b4bSPascal van Leeuwen 				.cra_driver_name = "safexcel-xcbc-aes",
214938f21b4bSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
215038f21b4bSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2151b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
215238f21b4bSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
215338f21b4bSPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
215438f21b4bSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
215538f21b4bSPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
215638f21b4bSPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
215738f21b4bSPascal van Leeuwen 				.cra_module = THIS_MODULE,
215838f21b4bSPascal van Leeuwen 			},
215938f21b4bSPascal van Leeuwen 		},
216038f21b4bSPascal van Leeuwen 	},
216138f21b4bSPascal van Leeuwen };
21627a627db9SPascal van Leeuwen 
21637a627db9SPascal van Leeuwen static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
21647a627db9SPascal van Leeuwen 				unsigned int len)
21657a627db9SPascal van Leeuwen {
21667a627db9SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
21677a627db9SPascal van Leeuwen 	struct crypto_aes_ctx aes;
21687a627db9SPascal van Leeuwen 	__be64 consts[4];
21697a627db9SPascal van Leeuwen 	u64 _const[2];
21707a627db9SPascal van Leeuwen 	u8 msb_mask, gfmask;
21717a627db9SPascal van Leeuwen 	int ret, i;
21727a627db9SPascal van Leeuwen 
21737a627db9SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
2174674f368aSEric Biggers 	if (ret)
21757a627db9SPascal van Leeuwen 		return ret;
21767a627db9SPascal van Leeuwen 
21777a627db9SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
217813a1bb93SPascal van Leeuwen 		ctx->ipad[i + 8] =
217913a1bb93SPascal van Leeuwen 			cpu_to_le32((__force u32)cpu_to_be32(aes.key_enc[i]));
21807a627db9SPascal van Leeuwen 
21817a627db9SPascal van Leeuwen 	/* precompute the CMAC key material */
21827a627db9SPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK);
21837a627db9SPascal van Leeuwen 	crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) &
21847a627db9SPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
21857a627db9SPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->kaes, key, len);
21867a627db9SPascal van Leeuwen 	if (ret)
21877a627db9SPascal van Leeuwen 		return ret;
21887a627db9SPascal van Leeuwen 
21897a627db9SPascal van Leeuwen 	/* code below borrowed from crypto/cmac.c */
21907a627db9SPascal van Leeuwen 	/* encrypt the zero block */
21917a627db9SPascal van Leeuwen 	memset(consts, 0, AES_BLOCK_SIZE);
21927a627db9SPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)consts, (u8 *)consts);
21937a627db9SPascal van Leeuwen 
21947a627db9SPascal van Leeuwen 	gfmask = 0x87;
21957a627db9SPascal van Leeuwen 	_const[0] = be64_to_cpu(consts[1]);
21967a627db9SPascal van Leeuwen 	_const[1] = be64_to_cpu(consts[0]);
21977a627db9SPascal van Leeuwen 
21987a627db9SPascal van Leeuwen 	/* gf(2^128) multiply zero-ciphertext with u and u^2 */
21997a627db9SPascal van Leeuwen 	for (i = 0; i < 4; i += 2) {
22007a627db9SPascal van Leeuwen 		msb_mask = ((s64)_const[1] >> 63) & gfmask;
22017a627db9SPascal van Leeuwen 		_const[1] = (_const[1] << 1) | (_const[0] >> 63);
22027a627db9SPascal van Leeuwen 		_const[0] = (_const[0] << 1) ^ msb_mask;
22037a627db9SPascal van Leeuwen 
22047a627db9SPascal van Leeuwen 		consts[i + 0] = cpu_to_be64(_const[1]);
22057a627db9SPascal van Leeuwen 		consts[i + 1] = cpu_to_be64(_const[0]);
22067a627db9SPascal van Leeuwen 	}
22077a627db9SPascal van Leeuwen 	/* end of code borrowed from crypto/cmac.c */
22087a627db9SPascal van Leeuwen 
22097a627db9SPascal van Leeuwen 	for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++)
221013a1bb93SPascal van Leeuwen 		ctx->ipad[i] = (__force __le32)cpu_to_be32(((u32 *)consts)[i]);
22117a627db9SPascal van Leeuwen 
22127a627db9SPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
22137a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
22147a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
22157a627db9SPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
22167a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
22177a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
22187a627db9SPascal van Leeuwen 	} else {
22197a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
22207a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
22217a627db9SPascal van Leeuwen 	}
22227a627db9SPascal van Leeuwen 	ctx->cbcmac = false;
22237a627db9SPascal van Leeuwen 
22247a627db9SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
22257a627db9SPascal van Leeuwen 	return 0;
22267a627db9SPascal van Leeuwen }
22277a627db9SPascal van Leeuwen 
22287a627db9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cmac = {
22297a627db9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
22307a627db9SPascal van Leeuwen 	.algo_mask = 0,
22317a627db9SPascal van Leeuwen 	.alg.ahash = {
22327a627db9SPascal van Leeuwen 		.init = safexcel_cbcmac_init,
22337a627db9SPascal van Leeuwen 		.update = safexcel_ahash_update,
22347a627db9SPascal van Leeuwen 		.final = safexcel_ahash_final,
22357a627db9SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22367a627db9SPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
22377a627db9SPascal van Leeuwen 		.setkey = safexcel_cmac_setkey,
22387a627db9SPascal van Leeuwen 		.export = safexcel_ahash_export,
22397a627db9SPascal van Leeuwen 		.import = safexcel_ahash_import,
22407a627db9SPascal van Leeuwen 		.halg = {
22417a627db9SPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
22427a627db9SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
22437a627db9SPascal van Leeuwen 			.base = {
22447a627db9SPascal van Leeuwen 				.cra_name = "cmac(aes)",
22457a627db9SPascal van Leeuwen 				.cra_driver_name = "safexcel-cmac-aes",
22467a627db9SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
22477a627db9SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2248b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
22497a627db9SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
22507a627db9SPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
22517a627db9SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
22527a627db9SPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
22537a627db9SPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
22547a627db9SPascal van Leeuwen 				.cra_module = THIS_MODULE,
22557a627db9SPascal van Leeuwen 			},
22567a627db9SPascal van Leeuwen 		},
22577a627db9SPascal van Leeuwen 	},
22587a627db9SPascal van Leeuwen };
22590f2bc131SPascal van Leeuwen 
22600f2bc131SPascal van Leeuwen static int safexcel_sm3_init(struct ahash_request *areq)
22610f2bc131SPascal van Leeuwen {
22620f2bc131SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
22630f2bc131SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
22640f2bc131SPascal van Leeuwen 
22650f2bc131SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
22660f2bc131SPascal van Leeuwen 
22670f2bc131SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
22680f2bc131SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
22690f2bc131SPascal van Leeuwen 	req->state_sz = SM3_DIGEST_SIZE;
22706c1c09b3SPascal van Leeuwen 	req->digest_sz = SM3_DIGEST_SIZE;
22710f2bc131SPascal van Leeuwen 	req->block_sz = SM3_BLOCK_SIZE;
22720f2bc131SPascal van Leeuwen 
22730f2bc131SPascal van Leeuwen 	return 0;
22740f2bc131SPascal van Leeuwen }
22750f2bc131SPascal van Leeuwen 
22760f2bc131SPascal van Leeuwen static int safexcel_sm3_digest(struct ahash_request *areq)
22770f2bc131SPascal van Leeuwen {
22780f2bc131SPascal van Leeuwen 	int ret = safexcel_sm3_init(areq);
22790f2bc131SPascal van Leeuwen 
22800f2bc131SPascal van Leeuwen 	if (ret)
22810f2bc131SPascal van Leeuwen 		return ret;
22820f2bc131SPascal van Leeuwen 
22830f2bc131SPascal van Leeuwen 	return safexcel_ahash_finup(areq);
22840f2bc131SPascal van Leeuwen }
22850f2bc131SPascal van Leeuwen 
22860f2bc131SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sm3 = {
22870f2bc131SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
22880f2bc131SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM3,
22890f2bc131SPascal van Leeuwen 	.alg.ahash = {
22900f2bc131SPascal van Leeuwen 		.init = safexcel_sm3_init,
22910f2bc131SPascal van Leeuwen 		.update = safexcel_ahash_update,
22920f2bc131SPascal van Leeuwen 		.final = safexcel_ahash_final,
22930f2bc131SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22940f2bc131SPascal van Leeuwen 		.digest = safexcel_sm3_digest,
22950f2bc131SPascal van Leeuwen 		.export = safexcel_ahash_export,
22960f2bc131SPascal van Leeuwen 		.import = safexcel_ahash_import,
22970f2bc131SPascal van Leeuwen 		.halg = {
22980f2bc131SPascal van Leeuwen 			.digestsize = SM3_DIGEST_SIZE,
22990f2bc131SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
23000f2bc131SPascal van Leeuwen 			.base = {
23010f2bc131SPascal van Leeuwen 				.cra_name = "sm3",
23020f2bc131SPascal van Leeuwen 				.cra_driver_name = "safexcel-sm3",
23030f2bc131SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
23040f2bc131SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2305b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
23060f2bc131SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
23070f2bc131SPascal van Leeuwen 				.cra_blocksize = SM3_BLOCK_SIZE,
23080f2bc131SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
23090f2bc131SPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
23100f2bc131SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
23110f2bc131SPascal van Leeuwen 				.cra_module = THIS_MODULE,
23120f2bc131SPascal van Leeuwen 			},
23130f2bc131SPascal van Leeuwen 		},
23140f2bc131SPascal van Leeuwen 	},
23150f2bc131SPascal van Leeuwen };
2316aa3a43e6SPascal van Leeuwen 
2317aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key,
2318aa3a43e6SPascal van Leeuwen 				    unsigned int keylen)
2319aa3a43e6SPascal van Leeuwen {
2320aa3a43e6SPascal van Leeuwen 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3",
2321aa3a43e6SPascal van Leeuwen 					SM3_DIGEST_SIZE);
2322aa3a43e6SPascal van Leeuwen }
2323aa3a43e6SPascal van Leeuwen 
2324aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_init(struct ahash_request *areq)
2325aa3a43e6SPascal van Leeuwen {
2326aa3a43e6SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
2327aa3a43e6SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2328aa3a43e6SPascal van Leeuwen 
2329aa3a43e6SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2330aa3a43e6SPascal van Leeuwen 
2331aa3a43e6SPascal van Leeuwen 	/* Start from ipad precompute */
2332aa3a43e6SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SM3_DIGEST_SIZE);
2333aa3a43e6SPascal van Leeuwen 	/* Already processed the key^ipad part now! */
2334aa3a43e6SPascal van Leeuwen 	req->len	= SM3_BLOCK_SIZE;
2335aa3a43e6SPascal van Leeuwen 	req->processed	= SM3_BLOCK_SIZE;
2336aa3a43e6SPascal van Leeuwen 
2337aa3a43e6SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
2338aa3a43e6SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
2339aa3a43e6SPascal van Leeuwen 	req->state_sz = SM3_DIGEST_SIZE;
23406c1c09b3SPascal van Leeuwen 	req->digest_sz = SM3_DIGEST_SIZE;
2341aa3a43e6SPascal van Leeuwen 	req->block_sz = SM3_BLOCK_SIZE;
2342aa3a43e6SPascal van Leeuwen 	req->hmac = true;
2343aa3a43e6SPascal van Leeuwen 
2344aa3a43e6SPascal van Leeuwen 	return 0;
2345aa3a43e6SPascal van Leeuwen }
2346aa3a43e6SPascal van Leeuwen 
2347aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_digest(struct ahash_request *areq)
2348aa3a43e6SPascal van Leeuwen {
2349aa3a43e6SPascal van Leeuwen 	int ret = safexcel_hmac_sm3_init(areq);
2350aa3a43e6SPascal van Leeuwen 
2351aa3a43e6SPascal van Leeuwen 	if (ret)
2352aa3a43e6SPascal van Leeuwen 		return ret;
2353aa3a43e6SPascal van Leeuwen 
2354aa3a43e6SPascal van Leeuwen 	return safexcel_ahash_finup(areq);
2355aa3a43e6SPascal van Leeuwen }
2356aa3a43e6SPascal van Leeuwen 
2357aa3a43e6SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sm3 = {
2358aa3a43e6SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2359aa3a43e6SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM3,
2360aa3a43e6SPascal van Leeuwen 	.alg.ahash = {
2361aa3a43e6SPascal van Leeuwen 		.init = safexcel_hmac_sm3_init,
2362aa3a43e6SPascal van Leeuwen 		.update = safexcel_ahash_update,
2363aa3a43e6SPascal van Leeuwen 		.final = safexcel_ahash_final,
2364aa3a43e6SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
2365aa3a43e6SPascal van Leeuwen 		.digest = safexcel_hmac_sm3_digest,
2366aa3a43e6SPascal van Leeuwen 		.setkey = safexcel_hmac_sm3_setkey,
2367aa3a43e6SPascal van Leeuwen 		.export = safexcel_ahash_export,
2368aa3a43e6SPascal van Leeuwen 		.import = safexcel_ahash_import,
2369aa3a43e6SPascal van Leeuwen 		.halg = {
2370aa3a43e6SPascal van Leeuwen 			.digestsize = SM3_DIGEST_SIZE,
2371aa3a43e6SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2372aa3a43e6SPascal van Leeuwen 			.base = {
2373aa3a43e6SPascal van Leeuwen 				.cra_name = "hmac(sm3)",
2374aa3a43e6SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sm3",
2375aa3a43e6SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2376aa3a43e6SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2377b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
2378aa3a43e6SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
2379aa3a43e6SPascal van Leeuwen 				.cra_blocksize = SM3_BLOCK_SIZE,
2380aa3a43e6SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2381aa3a43e6SPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
2382aa3a43e6SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
2383aa3a43e6SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2384aa3a43e6SPascal van Leeuwen 			},
2385aa3a43e6SPascal van Leeuwen 		},
2386aa3a43e6SPascal van Leeuwen 	},
2387aa3a43e6SPascal van Leeuwen };
2388aaf5a383SPascal van Leeuwen 
2389aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_init(struct ahash_request *areq)
2390aaf5a383SPascal van Leeuwen {
2391aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2392aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2393aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2394aaf5a383SPascal van Leeuwen 
2395aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2396aaf5a383SPascal van Leeuwen 
2397aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
2398aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2399aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_224_DIGEST_SIZE;
24006c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_224_DIGEST_SIZE;
2401aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_224_BLOCK_SIZE;
2402aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2403aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2404aaf5a383SPascal van Leeuwen 	return 0;
2405aaf5a383SPascal van Leeuwen }
2406aaf5a383SPascal van Leeuwen 
2407aaf5a383SPascal van Leeuwen static int safexcel_sha3_fbcheck(struct ahash_request *req)
2408aaf5a383SPascal van Leeuwen {
2409aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2410aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2411aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2412aaf5a383SPascal van Leeuwen 	int ret = 0;
2413aaf5a383SPascal van Leeuwen 
2414aaf5a383SPascal van Leeuwen 	if (ctx->do_fallback) {
2415aaf5a383SPascal van Leeuwen 		ahash_request_set_tfm(subreq, ctx->fback);
2416aaf5a383SPascal van Leeuwen 		ahash_request_set_callback(subreq, req->base.flags,
2417aaf5a383SPascal van Leeuwen 					   req->base.complete, req->base.data);
2418aaf5a383SPascal van Leeuwen 		ahash_request_set_crypt(subreq, req->src, req->result,
2419aaf5a383SPascal van Leeuwen 					req->nbytes);
2420aaf5a383SPascal van Leeuwen 		if (!ctx->fb_init_done) {
24216c1c09b3SPascal van Leeuwen 			if (ctx->fb_do_setkey) {
24226c1c09b3SPascal van Leeuwen 				/* Set fallback cipher HMAC key */
24236c1c09b3SPascal van Leeuwen 				u8 key[SHA3_224_BLOCK_SIZE];
24246c1c09b3SPascal van Leeuwen 
24256c1c09b3SPascal van Leeuwen 				memcpy(key, ctx->ipad,
24266c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2);
24276c1c09b3SPascal van Leeuwen 				memcpy(key +
24286c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2,
24296c1c09b3SPascal van Leeuwen 				       ctx->opad,
24306c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2);
24316c1c09b3SPascal van Leeuwen 				ret = crypto_ahash_setkey(ctx->fback, key,
24326c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(ctx->fback));
24336c1c09b3SPascal van Leeuwen 				memzero_explicit(key,
24346c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(ctx->fback));
24356c1c09b3SPascal van Leeuwen 				ctx->fb_do_setkey = false;
24366c1c09b3SPascal van Leeuwen 			}
24376c1c09b3SPascal van Leeuwen 			ret = ret ?: crypto_ahash_init(subreq);
2438aaf5a383SPascal van Leeuwen 			ctx->fb_init_done = true;
2439aaf5a383SPascal van Leeuwen 		}
2440aaf5a383SPascal van Leeuwen 	}
2441aaf5a383SPascal van Leeuwen 	return ret;
2442aaf5a383SPascal van Leeuwen }
2443aaf5a383SPascal van Leeuwen 
2444aaf5a383SPascal van Leeuwen static int safexcel_sha3_update(struct ahash_request *req)
2445aaf5a383SPascal van Leeuwen {
2446aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2447aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2448aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2449aaf5a383SPascal van Leeuwen 
2450aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2451aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq);
2452aaf5a383SPascal van Leeuwen }
2453aaf5a383SPascal van Leeuwen 
2454aaf5a383SPascal van Leeuwen static int safexcel_sha3_final(struct ahash_request *req)
2455aaf5a383SPascal van Leeuwen {
2456aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2457aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2458aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2459aaf5a383SPascal van Leeuwen 
2460aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2461aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq);
2462aaf5a383SPascal van Leeuwen }
2463aaf5a383SPascal van Leeuwen 
2464aaf5a383SPascal van Leeuwen static int safexcel_sha3_finup(struct ahash_request *req)
2465aaf5a383SPascal van Leeuwen {
2466aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2467aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2468aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2469aaf5a383SPascal van Leeuwen 
2470aaf5a383SPascal van Leeuwen 	ctx->do_fallback |= !req->nbytes;
2471aaf5a383SPascal van Leeuwen 	if (ctx->do_fallback)
2472aaf5a383SPascal van Leeuwen 		/* Update or ex/import happened or len 0, cannot use the HW */
2473aaf5a383SPascal van Leeuwen 		return safexcel_sha3_fbcheck(req) ?:
2474aaf5a383SPascal van Leeuwen 		       crypto_ahash_finup(subreq);
2475aaf5a383SPascal van Leeuwen 	else
2476aaf5a383SPascal van Leeuwen 		return safexcel_ahash_finup(req);
2477aaf5a383SPascal van Leeuwen }
2478aaf5a383SPascal van Leeuwen 
2479aaf5a383SPascal van Leeuwen static int safexcel_sha3_digest_fallback(struct ahash_request *req)
2480aaf5a383SPascal van Leeuwen {
2481aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2482aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2483aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2484aaf5a383SPascal van Leeuwen 
2485aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2486aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2487aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq);
2488aaf5a383SPascal van Leeuwen }
2489aaf5a383SPascal van Leeuwen 
2490aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_digest(struct ahash_request *req)
2491aaf5a383SPascal van Leeuwen {
2492aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2493aaf5a383SPascal van Leeuwen 		return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req);
2494aaf5a383SPascal van Leeuwen 
2495aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2496aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2497aaf5a383SPascal van Leeuwen }
2498aaf5a383SPascal van Leeuwen 
2499aaf5a383SPascal van Leeuwen static int safexcel_sha3_export(struct ahash_request *req, void *out)
2500aaf5a383SPascal van Leeuwen {
2501aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2502aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2503aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2504aaf5a383SPascal van Leeuwen 
2505aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2506aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out);
2507aaf5a383SPascal van Leeuwen }
2508aaf5a383SPascal van Leeuwen 
2509aaf5a383SPascal van Leeuwen static int safexcel_sha3_import(struct ahash_request *req, const void *in)
2510aaf5a383SPascal van Leeuwen {
2511aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2512aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2513aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2514aaf5a383SPascal van Leeuwen 
2515aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2516aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in);
2517aaf5a383SPascal van Leeuwen 	// return safexcel_ahash_import(req, in);
2518aaf5a383SPascal van Leeuwen }
2519aaf5a383SPascal van Leeuwen 
2520aaf5a383SPascal van Leeuwen static int safexcel_sha3_cra_init(struct crypto_tfm *tfm)
2521aaf5a383SPascal van Leeuwen {
2522aaf5a383SPascal van Leeuwen 	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
2523aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
2524aaf5a383SPascal van Leeuwen 
2525aaf5a383SPascal van Leeuwen 	safexcel_ahash_cra_init(tfm);
2526aaf5a383SPascal van Leeuwen 
2527aaf5a383SPascal van Leeuwen 	/* Allocate fallback implementation */
2528aaf5a383SPascal van Leeuwen 	ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0,
2529aaf5a383SPascal van Leeuwen 					CRYPTO_ALG_ASYNC |
2530aaf5a383SPascal van Leeuwen 					CRYPTO_ALG_NEED_FALLBACK);
2531aaf5a383SPascal van Leeuwen 	if (IS_ERR(ctx->fback))
2532aaf5a383SPascal van Leeuwen 		return PTR_ERR(ctx->fback);
2533aaf5a383SPascal van Leeuwen 
2534aaf5a383SPascal van Leeuwen 	/* Update statesize from fallback algorithm! */
2535aaf5a383SPascal van Leeuwen 	crypto_hash_alg_common(ahash)->statesize =
2536aaf5a383SPascal van Leeuwen 		crypto_ahash_statesize(ctx->fback);
2537aaf5a383SPascal van Leeuwen 	crypto_ahash_set_reqsize(ahash, max(sizeof(struct safexcel_ahash_req),
2538aaf5a383SPascal van Leeuwen 					    sizeof(struct ahash_request) +
2539aaf5a383SPascal van Leeuwen 					    crypto_ahash_reqsize(ctx->fback)));
2540aaf5a383SPascal van Leeuwen 	return 0;
2541aaf5a383SPascal van Leeuwen }
2542aaf5a383SPascal van Leeuwen 
2543aaf5a383SPascal van Leeuwen static void safexcel_sha3_cra_exit(struct crypto_tfm *tfm)
2544aaf5a383SPascal van Leeuwen {
2545aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
2546aaf5a383SPascal van Leeuwen 
2547aaf5a383SPascal van Leeuwen 	crypto_free_ahash(ctx->fback);
2548aaf5a383SPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
2549aaf5a383SPascal van Leeuwen }
2550aaf5a383SPascal van Leeuwen 
2551aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_224 = {
2552aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2553aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2554aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2555aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_224_init,
2556aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2557aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2558aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2559aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_224_digest,
2560aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2561aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2562aaf5a383SPascal van Leeuwen 		.halg = {
2563aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_224_DIGEST_SIZE,
2564aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2565aaf5a383SPascal van Leeuwen 			.base = {
2566aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-224",
2567aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-224",
2568aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2569aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2570aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2571aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2572aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_224_BLOCK_SIZE,
2573aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2574aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2575aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2576aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2577aaf5a383SPascal van Leeuwen 			},
2578aaf5a383SPascal van Leeuwen 		},
2579aaf5a383SPascal van Leeuwen 	},
2580aaf5a383SPascal van Leeuwen };
2581aaf5a383SPascal van Leeuwen 
2582aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_init(struct ahash_request *areq)
2583aaf5a383SPascal van Leeuwen {
2584aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2585aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2586aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2587aaf5a383SPascal van Leeuwen 
2588aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2589aaf5a383SPascal van Leeuwen 
2590aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
2591aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2592aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_256_DIGEST_SIZE;
25936c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_256_DIGEST_SIZE;
2594aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_256_BLOCK_SIZE;
2595aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2596aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2597aaf5a383SPascal van Leeuwen 	return 0;
2598aaf5a383SPascal van Leeuwen }
2599aaf5a383SPascal van Leeuwen 
2600aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_digest(struct ahash_request *req)
2601aaf5a383SPascal van Leeuwen {
2602aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2603aaf5a383SPascal van Leeuwen 		return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req);
2604aaf5a383SPascal van Leeuwen 
2605aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2606aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2607aaf5a383SPascal van Leeuwen }
2608aaf5a383SPascal van Leeuwen 
2609aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_256 = {
2610aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2611aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2612aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2613aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_256_init,
2614aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2615aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2616aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2617aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_256_digest,
2618aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2619aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2620aaf5a383SPascal van Leeuwen 		.halg = {
2621aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_256_DIGEST_SIZE,
2622aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2623aaf5a383SPascal van Leeuwen 			.base = {
2624aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-256",
2625aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-256",
2626aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2627aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2628aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2629aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2630aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_256_BLOCK_SIZE,
2631aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2632aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2633aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2634aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2635aaf5a383SPascal van Leeuwen 			},
2636aaf5a383SPascal van Leeuwen 		},
2637aaf5a383SPascal van Leeuwen 	},
2638aaf5a383SPascal van Leeuwen };
2639aaf5a383SPascal van Leeuwen 
2640aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_init(struct ahash_request *areq)
2641aaf5a383SPascal van Leeuwen {
2642aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2643aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2644aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2645aaf5a383SPascal van Leeuwen 
2646aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2647aaf5a383SPascal van Leeuwen 
2648aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
2649aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2650aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_384_DIGEST_SIZE;
26516c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_384_DIGEST_SIZE;
2652aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_384_BLOCK_SIZE;
2653aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2654aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2655aaf5a383SPascal van Leeuwen 	return 0;
2656aaf5a383SPascal van Leeuwen }
2657aaf5a383SPascal van Leeuwen 
2658aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_digest(struct ahash_request *req)
2659aaf5a383SPascal van Leeuwen {
2660aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2661aaf5a383SPascal van Leeuwen 		return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req);
2662aaf5a383SPascal van Leeuwen 
2663aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2664aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2665aaf5a383SPascal van Leeuwen }
2666aaf5a383SPascal van Leeuwen 
2667aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_384 = {
2668aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2669aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2670aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2671aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_384_init,
2672aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2673aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2674aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2675aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_384_digest,
2676aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2677aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2678aaf5a383SPascal van Leeuwen 		.halg = {
2679aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_384_DIGEST_SIZE,
2680aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2681aaf5a383SPascal van Leeuwen 			.base = {
2682aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-384",
2683aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-384",
2684aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2685aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2686aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2687aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2688aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_384_BLOCK_SIZE,
2689aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2690aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2691aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2692aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2693aaf5a383SPascal van Leeuwen 			},
2694aaf5a383SPascal van Leeuwen 		},
2695aaf5a383SPascal van Leeuwen 	},
2696aaf5a383SPascal van Leeuwen };
2697aaf5a383SPascal van Leeuwen 
2698aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_init(struct ahash_request *areq)
2699aaf5a383SPascal van Leeuwen {
2700aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2701aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2702aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2703aaf5a383SPascal van Leeuwen 
2704aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2705aaf5a383SPascal van Leeuwen 
2706aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
2707aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2708aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_512_DIGEST_SIZE;
27096c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_512_DIGEST_SIZE;
2710aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_512_BLOCK_SIZE;
2711aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2712aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2713aaf5a383SPascal van Leeuwen 	return 0;
2714aaf5a383SPascal van Leeuwen }
2715aaf5a383SPascal van Leeuwen 
2716aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_digest(struct ahash_request *req)
2717aaf5a383SPascal van Leeuwen {
2718aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2719aaf5a383SPascal van Leeuwen 		return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req);
2720aaf5a383SPascal van Leeuwen 
2721aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2722aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2723aaf5a383SPascal van Leeuwen }
2724aaf5a383SPascal van Leeuwen 
2725aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_512 = {
2726aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2727aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2728aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2729aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_512_init,
2730aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2731aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2732aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2733aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_512_digest,
2734aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2735aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2736aaf5a383SPascal van Leeuwen 		.halg = {
2737aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_512_DIGEST_SIZE,
2738aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2739aaf5a383SPascal van Leeuwen 			.base = {
2740aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-512",
2741aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-512",
2742aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2743aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2744aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2745aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2746aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_512_BLOCK_SIZE,
2747aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2748aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2749aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2750aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2751aaf5a383SPascal van Leeuwen 			},
2752aaf5a383SPascal van Leeuwen 		},
2753aaf5a383SPascal van Leeuwen 	},
2754aaf5a383SPascal van Leeuwen };
27556c1c09b3SPascal van Leeuwen 
27566c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg)
27576c1c09b3SPascal van Leeuwen {
27586c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
27596c1c09b3SPascal van Leeuwen 	int ret;
27606c1c09b3SPascal van Leeuwen 
27616c1c09b3SPascal van Leeuwen 	ret = safexcel_sha3_cra_init(tfm);
27626c1c09b3SPascal van Leeuwen 	if (ret)
27636c1c09b3SPascal van Leeuwen 		return ret;
27646c1c09b3SPascal van Leeuwen 
27656c1c09b3SPascal van Leeuwen 	/* Allocate precalc basic digest implementation */
27666c1c09b3SPascal van Leeuwen 	ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
27676c1c09b3SPascal van Leeuwen 	if (IS_ERR(ctx->shpre))
27686c1c09b3SPascal van Leeuwen 		return PTR_ERR(ctx->shpre);
27696c1c09b3SPascal van Leeuwen 
27706c1c09b3SPascal van Leeuwen 	ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) +
27716c1c09b3SPascal van Leeuwen 			      crypto_shash_descsize(ctx->shpre), GFP_KERNEL);
27726c1c09b3SPascal van Leeuwen 	if (!ctx->shdesc) {
27736c1c09b3SPascal van Leeuwen 		crypto_free_shash(ctx->shpre);
27746c1c09b3SPascal van Leeuwen 		return -ENOMEM;
27756c1c09b3SPascal van Leeuwen 	}
27766c1c09b3SPascal van Leeuwen 	ctx->shdesc->tfm = ctx->shpre;
27776c1c09b3SPascal van Leeuwen 	return 0;
27786c1c09b3SPascal van Leeuwen }
27796c1c09b3SPascal van Leeuwen 
27806c1c09b3SPascal van Leeuwen static void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm)
27816c1c09b3SPascal van Leeuwen {
27826c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
27836c1c09b3SPascal van Leeuwen 
27846c1c09b3SPascal van Leeuwen 	crypto_free_ahash(ctx->fback);
27856c1c09b3SPascal van Leeuwen 	crypto_free_shash(ctx->shpre);
27866c1c09b3SPascal van Leeuwen 	kfree(ctx->shdesc);
27876c1c09b3SPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
27886c1c09b3SPascal van Leeuwen }
27896c1c09b3SPascal van Leeuwen 
27906c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key,
27916c1c09b3SPascal van Leeuwen 				     unsigned int keylen)
27926c1c09b3SPascal van Leeuwen {
27936c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
27946c1c09b3SPascal van Leeuwen 	int ret = 0;
27956c1c09b3SPascal van Leeuwen 
27966c1c09b3SPascal van Leeuwen 	if (keylen > crypto_ahash_blocksize(tfm)) {
27976c1c09b3SPascal van Leeuwen 		/*
27986c1c09b3SPascal van Leeuwen 		 * If the key is larger than the blocksize, then hash it
27996c1c09b3SPascal van Leeuwen 		 * first using our fallback cipher
28006c1c09b3SPascal van Leeuwen 		 */
28016c1c09b3SPascal van Leeuwen 		ret = crypto_shash_digest(ctx->shdesc, key, keylen,
28026c1c09b3SPascal van Leeuwen 					  (u8 *)ctx->ipad);
28036c1c09b3SPascal van Leeuwen 		keylen = crypto_shash_digestsize(ctx->shpre);
28046c1c09b3SPascal van Leeuwen 
28056c1c09b3SPascal van Leeuwen 		/*
28066c1c09b3SPascal van Leeuwen 		 * If the digest is larger than half the blocksize, we need to
28076c1c09b3SPascal van Leeuwen 		 * move the rest to opad due to the way our HMAC infra works.
28086c1c09b3SPascal van Leeuwen 		 */
28096c1c09b3SPascal van Leeuwen 		if (keylen > crypto_ahash_blocksize(tfm) / 2)
28106c1c09b3SPascal van Leeuwen 			/* Buffers overlap, need to use memmove iso memcpy! */
28116c1c09b3SPascal van Leeuwen 			memmove(ctx->opad,
28126c1c09b3SPascal van Leeuwen 				(u8 *)ctx->ipad +
28136c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(tfm) / 2,
28146c1c09b3SPascal van Leeuwen 				keylen - crypto_ahash_blocksize(tfm) / 2);
28156c1c09b3SPascal van Leeuwen 	} else {
28166c1c09b3SPascal van Leeuwen 		/*
28176c1c09b3SPascal van Leeuwen 		 * Copy the key to our ipad & opad buffers
28186c1c09b3SPascal van Leeuwen 		 * Note that ipad and opad each contain one half of the key,
28196c1c09b3SPascal van Leeuwen 		 * to match the existing HMAC driver infrastructure.
28206c1c09b3SPascal van Leeuwen 		 */
28216c1c09b3SPascal van Leeuwen 		if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
28226c1c09b3SPascal van Leeuwen 			memcpy(ctx->ipad, key, keylen);
28236c1c09b3SPascal van Leeuwen 		} else {
28246c1c09b3SPascal van Leeuwen 			memcpy(ctx->ipad, key,
28256c1c09b3SPascal van Leeuwen 			       crypto_ahash_blocksize(tfm) / 2);
28266c1c09b3SPascal van Leeuwen 			memcpy(ctx->opad,
28276c1c09b3SPascal van Leeuwen 			       key + crypto_ahash_blocksize(tfm) / 2,
28286c1c09b3SPascal van Leeuwen 			       keylen - crypto_ahash_blocksize(tfm) / 2);
28296c1c09b3SPascal van Leeuwen 		}
28306c1c09b3SPascal van Leeuwen 	}
28316c1c09b3SPascal van Leeuwen 
28326c1c09b3SPascal van Leeuwen 	/* Pad key with zeroes */
28336c1c09b3SPascal van Leeuwen 	if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
28346c1c09b3SPascal van Leeuwen 		memset((u8 *)ctx->ipad + keylen, 0,
28356c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) / 2 - keylen);
28366c1c09b3SPascal van Leeuwen 		memset(ctx->opad, 0, crypto_ahash_blocksize(tfm) / 2);
28376c1c09b3SPascal van Leeuwen 	} else {
28386c1c09b3SPascal van Leeuwen 		memset((u8 *)ctx->opad + keylen -
28396c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) / 2, 0,
28406c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) - keylen);
28416c1c09b3SPascal van Leeuwen 	}
28426c1c09b3SPascal van Leeuwen 
28436c1c09b3SPascal van Leeuwen 	/* If doing fallback, still need to set the new key! */
28446c1c09b3SPascal van Leeuwen 	ctx->fb_do_setkey = true;
28456c1c09b3SPascal van Leeuwen 	return ret;
28466c1c09b3SPascal van Leeuwen }
28476c1c09b3SPascal van Leeuwen 
28486c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_init(struct ahash_request *areq)
28496c1c09b3SPascal van Leeuwen {
28506c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
28516c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
28526c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
28536c1c09b3SPascal van Leeuwen 
28546c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
28556c1c09b3SPascal van Leeuwen 
28566c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
28576c1c09b3SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA3_224_BLOCK_SIZE / 2);
28586c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
28596c1c09b3SPascal van Leeuwen 	req->len	= SHA3_224_BLOCK_SIZE;
28606c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_224_BLOCK_SIZE;
28616c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
28626c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
28636c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_224_BLOCK_SIZE / 2;
28646c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_224_DIGEST_SIZE;
28656c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_224_BLOCK_SIZE;
28666c1c09b3SPascal van Leeuwen 	req->hmac = true;
28676c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
28686c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
28696c1c09b3SPascal van Leeuwen 	return 0;
28706c1c09b3SPascal van Leeuwen }
28716c1c09b3SPascal van Leeuwen 
28726c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_digest(struct ahash_request *req)
28736c1c09b3SPascal van Leeuwen {
28746c1c09b3SPascal van Leeuwen 	if (req->nbytes)
28756c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_224_init(req) ?:
28766c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
28776c1c09b3SPascal van Leeuwen 
28786c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
28796c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
28806c1c09b3SPascal van Leeuwen }
28816c1c09b3SPascal van Leeuwen 
28826c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm)
28836c1c09b3SPascal van Leeuwen {
28846c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-224");
28856c1c09b3SPascal van Leeuwen }
28866c1c09b3SPascal van Leeuwen 
28876c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_224 = {
28886c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
28896c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
28906c1c09b3SPascal van Leeuwen 	.alg.ahash = {
28916c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_224_init,
28926c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
28936c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
28946c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
28956c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_224_digest,
28966c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
28976c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
28986c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
28996c1c09b3SPascal van Leeuwen 		.halg = {
29006c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_224_DIGEST_SIZE,
29016c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
29026c1c09b3SPascal van Leeuwen 			.base = {
29036c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-224)",
29046c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-224",
29056c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
29066c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
29076c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
29086c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
29096c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_224_BLOCK_SIZE,
29106c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
29116c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_224_cra_init,
29126c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
29136c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
29146c1c09b3SPascal van Leeuwen 			},
29156c1c09b3SPascal van Leeuwen 		},
29166c1c09b3SPascal van Leeuwen 	},
29176c1c09b3SPascal van Leeuwen };
29186c1c09b3SPascal van Leeuwen 
29196c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_init(struct ahash_request *areq)
29206c1c09b3SPascal van Leeuwen {
29216c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
29226c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
29236c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
29246c1c09b3SPascal van Leeuwen 
29256c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
29266c1c09b3SPascal van Leeuwen 
29276c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
29286c1c09b3SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA3_256_BLOCK_SIZE / 2);
29296c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
29306c1c09b3SPascal van Leeuwen 	req->len	= SHA3_256_BLOCK_SIZE;
29316c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_256_BLOCK_SIZE;
29326c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
29336c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
29346c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_256_BLOCK_SIZE / 2;
29356c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_256_DIGEST_SIZE;
29366c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_256_BLOCK_SIZE;
29376c1c09b3SPascal van Leeuwen 	req->hmac = true;
29386c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
29396c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
29406c1c09b3SPascal van Leeuwen 	return 0;
29416c1c09b3SPascal van Leeuwen }
29426c1c09b3SPascal van Leeuwen 
29436c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_digest(struct ahash_request *req)
29446c1c09b3SPascal van Leeuwen {
29456c1c09b3SPascal van Leeuwen 	if (req->nbytes)
29466c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_256_init(req) ?:
29476c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
29486c1c09b3SPascal van Leeuwen 
29496c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
29506c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
29516c1c09b3SPascal van Leeuwen }
29526c1c09b3SPascal van Leeuwen 
29536c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm)
29546c1c09b3SPascal van Leeuwen {
29556c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-256");
29566c1c09b3SPascal van Leeuwen }
29576c1c09b3SPascal van Leeuwen 
29586c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_256 = {
29596c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
29606c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
29616c1c09b3SPascal van Leeuwen 	.alg.ahash = {
29626c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_256_init,
29636c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
29646c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
29656c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
29666c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_256_digest,
29676c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
29686c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
29696c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
29706c1c09b3SPascal van Leeuwen 		.halg = {
29716c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_256_DIGEST_SIZE,
29726c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
29736c1c09b3SPascal van Leeuwen 			.base = {
29746c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-256)",
29756c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-256",
29766c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
29776c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
29786c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
29796c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
29806c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_256_BLOCK_SIZE,
29816c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
29826c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_256_cra_init,
29836c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
29846c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
29856c1c09b3SPascal van Leeuwen 			},
29866c1c09b3SPascal van Leeuwen 		},
29876c1c09b3SPascal van Leeuwen 	},
29886c1c09b3SPascal van Leeuwen };
29896c1c09b3SPascal van Leeuwen 
29906c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_init(struct ahash_request *areq)
29916c1c09b3SPascal van Leeuwen {
29926c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
29936c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
29946c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
29956c1c09b3SPascal van Leeuwen 
29966c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
29976c1c09b3SPascal van Leeuwen 
29986c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
29996c1c09b3SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA3_384_BLOCK_SIZE / 2);
30006c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
30016c1c09b3SPascal van Leeuwen 	req->len	= SHA3_384_BLOCK_SIZE;
30026c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_384_BLOCK_SIZE;
30036c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
30046c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
30056c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_384_BLOCK_SIZE / 2;
30066c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_384_DIGEST_SIZE;
30076c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_384_BLOCK_SIZE;
30086c1c09b3SPascal van Leeuwen 	req->hmac = true;
30096c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
30106c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
30116c1c09b3SPascal van Leeuwen 	return 0;
30126c1c09b3SPascal van Leeuwen }
30136c1c09b3SPascal van Leeuwen 
30146c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_digest(struct ahash_request *req)
30156c1c09b3SPascal van Leeuwen {
30166c1c09b3SPascal van Leeuwen 	if (req->nbytes)
30176c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_384_init(req) ?:
30186c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
30196c1c09b3SPascal van Leeuwen 
30206c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
30216c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
30226c1c09b3SPascal van Leeuwen }
30236c1c09b3SPascal van Leeuwen 
30246c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm)
30256c1c09b3SPascal van Leeuwen {
30266c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-384");
30276c1c09b3SPascal van Leeuwen }
30286c1c09b3SPascal van Leeuwen 
30296c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_384 = {
30306c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
30316c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
30326c1c09b3SPascal van Leeuwen 	.alg.ahash = {
30336c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_384_init,
30346c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
30356c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
30366c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
30376c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_384_digest,
30386c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
30396c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
30406c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
30416c1c09b3SPascal van Leeuwen 		.halg = {
30426c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_384_DIGEST_SIZE,
30436c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
30446c1c09b3SPascal van Leeuwen 			.base = {
30456c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-384)",
30466c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-384",
30476c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
30486c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
30496c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
30506c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
30516c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_384_BLOCK_SIZE,
30526c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
30536c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_384_cra_init,
30546c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
30556c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
30566c1c09b3SPascal van Leeuwen 			},
30576c1c09b3SPascal van Leeuwen 		},
30586c1c09b3SPascal van Leeuwen 	},
30596c1c09b3SPascal van Leeuwen };
30606c1c09b3SPascal van Leeuwen 
30616c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_init(struct ahash_request *areq)
30626c1c09b3SPascal van Leeuwen {
30636c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
30646c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
30656c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
30666c1c09b3SPascal van Leeuwen 
30676c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
30686c1c09b3SPascal van Leeuwen 
30696c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
30706c1c09b3SPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA3_512_BLOCK_SIZE / 2);
30716c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
30726c1c09b3SPascal van Leeuwen 	req->len	= SHA3_512_BLOCK_SIZE;
30736c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_512_BLOCK_SIZE;
30746c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
30756c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
30766c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_512_BLOCK_SIZE / 2;
30776c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_512_DIGEST_SIZE;
30786c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_512_BLOCK_SIZE;
30796c1c09b3SPascal van Leeuwen 	req->hmac = true;
30806c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
30816c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
30826c1c09b3SPascal van Leeuwen 	return 0;
30836c1c09b3SPascal van Leeuwen }
30846c1c09b3SPascal van Leeuwen 
30856c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_digest(struct ahash_request *req)
30866c1c09b3SPascal van Leeuwen {
30876c1c09b3SPascal van Leeuwen 	if (req->nbytes)
30886c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_512_init(req) ?:
30896c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
30906c1c09b3SPascal van Leeuwen 
30916c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
30926c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
30936c1c09b3SPascal van Leeuwen }
30946c1c09b3SPascal van Leeuwen 
30956c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm)
30966c1c09b3SPascal van Leeuwen {
30976c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-512");
30986c1c09b3SPascal van Leeuwen }
30996c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_512 = {
31006c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
31016c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
31026c1c09b3SPascal van Leeuwen 	.alg.ahash = {
31036c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_512_init,
31046c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
31056c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
31066c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
31076c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_512_digest,
31086c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
31096c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
31106c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
31116c1c09b3SPascal van Leeuwen 		.halg = {
31126c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_512_DIGEST_SIZE,
31136c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
31146c1c09b3SPascal van Leeuwen 			.base = {
31156c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-512)",
31166c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-512",
31176c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
31186c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
31196c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
31206c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
31216c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_512_BLOCK_SIZE,
31226c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
31236c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_512_cra_init,
31246c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
31256c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
31266c1c09b3SPascal van Leeuwen 			},
31276c1c09b3SPascal van Leeuwen 		},
31286c1c09b3SPascal van Leeuwen 	},
31296c1c09b3SPascal van Leeuwen };
3130