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>
11a24d22b2SEric Biggers #include <crypto/sha1.h>
12a24d22b2SEric Biggers #include <crypto/sha2.h>
13aaf5a383SPascal van Leeuwen #include <crypto/sha3.h>
1438f21b4bSPascal van Leeuwen #include <crypto/skcipher.h>
150f2bc131SPascal van Leeuwen #include <crypto/sm3.h>
160eb76ba2SArd Biesheuvel #include <crypto/internal/cipher.h>
171b44c5a6SAntoine Ténart #include <linux/device.h>
181b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
191b44c5a6SAntoine Ténart #include <linux/dmapool.h>
201b44c5a6SAntoine Ténart 
211b44c5a6SAntoine Ténart #include "safexcel.h"
221b44c5a6SAntoine Ténart 
231b44c5a6SAntoine Ténart struct safexcel_ahash_ctx {
241b44c5a6SAntoine Ténart 	struct safexcel_context base;
251b44c5a6SAntoine Ténart 
261b44c5a6SAntoine Ténart 	u32 alg;
27b98687bbSPascal van Leeuwen 	u8  key_sz;
2838f21b4bSPascal van Leeuwen 	bool cbcmac;
29aaf5a383SPascal van Leeuwen 	bool do_fallback;
30aaf5a383SPascal van Leeuwen 	bool fb_init_done;
316c1c09b3SPascal van Leeuwen 	bool fb_do_setkey;
321b44c5a6SAntoine Ténart 
33*320406cbSPeter Harliman Liem 	struct crypto_aes_ctx *aes;
34aaf5a383SPascal van Leeuwen 	struct crypto_ahash *fback;
356c1c09b3SPascal van Leeuwen 	struct crypto_shash *shpre;
366c1c09b3SPascal van Leeuwen 	struct shash_desc *shdesc;
371b44c5a6SAntoine Ténart };
381b44c5a6SAntoine Ténart 
391b44c5a6SAntoine Ténart struct safexcel_ahash_req {
401b44c5a6SAntoine Ténart 	bool last_req;
411b44c5a6SAntoine Ténart 	bool finish;
421b44c5a6SAntoine Ténart 	bool hmac;
431eb7b403SOfer Heifetz 	bool needs_inv;
4485b36ee8SPascal van Leeuwen 	bool hmac_zlen;
4585b36ee8SPascal van Leeuwen 	bool len_is_le;
46b98687bbSPascal van Leeuwen 	bool not_first;
47b98687bbSPascal van Leeuwen 	bool xcbcmac;
481b44c5a6SAntoine Ténart 
49c957f8b3SAntoine Ténart 	int nents;
50b8592027SOfer Heifetz 	dma_addr_t result_dma;
51c957f8b3SAntoine Ténart 
52b869648cSAntoine Tenart 	u32 digest;
53b869648cSAntoine Tenart 
5441abed7dSPascal van Leeuwen 	u8 state_sz;    /* expected state size, only set once */
5541abed7dSPascal van Leeuwen 	u8 block_sz;    /* block size, only set once */
566c1c09b3SPascal van Leeuwen 	u8 digest_sz;   /* output digest size, only set once */
5713a1bb93SPascal van Leeuwen 	__le32 state[SHA3_512_BLOCK_SIZE /
5813a1bb93SPascal van Leeuwen 		     sizeof(__le32)] __aligned(sizeof(__le32));
591b44c5a6SAntoine Ténart 
6031fb084cSPascal van Leeuwen 	u64 len;
6131fb084cSPascal van Leeuwen 	u64 processed;
621b44c5a6SAntoine Ténart 
6341abed7dSPascal van Leeuwen 	u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32));
64cff9a175SAntoine Tenart 	dma_addr_t cache_dma;
65cff9a175SAntoine Tenart 	unsigned int cache_sz;
66cff9a175SAntoine Tenart 
6741abed7dSPascal van Leeuwen 	u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32));
681b44c5a6SAntoine Ténart };
691b44c5a6SAntoine Ténart 
70b460edb6SAntoine Tenart static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req)
71b460edb6SAntoine Tenart {
7231fb084cSPascal van Leeuwen 	return req->len - req->processed;
73b460edb6SAntoine Tenart }
74b460edb6SAntoine Tenart 
751b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc,
76b98687bbSPascal van Leeuwen 				u32 input_length, u32 result_length,
7738f21b4bSPascal van Leeuwen 				bool cbcmac)
781b44c5a6SAntoine Ténart {
791b44c5a6SAntoine Ténart 	struct safexcel_token *token =
801b44c5a6SAntoine Ténart 		(struct safexcel_token *)cdesc->control_data.token;
811b44c5a6SAntoine Ténart 
821b44c5a6SAntoine Ténart 	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
831b44c5a6SAntoine Ténart 	token[0].packet_length = input_length;
841b44c5a6SAntoine Ténart 	token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH;
851b44c5a6SAntoine Ténart 
86b98687bbSPascal van Leeuwen 	input_length &= 15;
8738f21b4bSPascal van Leeuwen 	if (unlikely(cbcmac && input_length)) {
88098e51e5SPascal van Leeuwen 		token[0].stat =  0;
891b44c5a6SAntoine Ténart 		token[1].opcode = EIP197_TOKEN_OPCODE_INSERT;
90b98687bbSPascal van Leeuwen 		token[1].packet_length = 16 - input_length;
91b98687bbSPascal van Leeuwen 		token[1].stat = EIP197_TOKEN_STAT_LAST_HASH;
92b98687bbSPascal van Leeuwen 		token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH;
93b98687bbSPascal van Leeuwen 	} else {
94b98687bbSPascal van Leeuwen 		token[0].stat = EIP197_TOKEN_STAT_LAST_HASH;
95098e51e5SPascal van Leeuwen 		eip197_noop_token(&token[1]);
96b98687bbSPascal van Leeuwen 	}
97b98687bbSPascal van Leeuwen 
98b98687bbSPascal van Leeuwen 	token[2].opcode = EIP197_TOKEN_OPCODE_INSERT;
99b98687bbSPascal van Leeuwen 	token[2].stat = EIP197_TOKEN_STAT_LAST_HASH |
1001b44c5a6SAntoine Ténart 			EIP197_TOKEN_STAT_LAST_PACKET;
101b98687bbSPascal van Leeuwen 	token[2].packet_length = result_length;
102b98687bbSPascal van Leeuwen 	token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
1031b44c5a6SAntoine Ténart 				EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
104098e51e5SPascal van Leeuwen 
105098e51e5SPascal van Leeuwen 	eip197_noop_token(&token[3]);
1061b44c5a6SAntoine Ténart }
1071b44c5a6SAntoine Ténart 
1081b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx,
1091b44c5a6SAntoine Ténart 				     struct safexcel_ahash_req *req,
11041abed7dSPascal van Leeuwen 				     struct safexcel_command_desc *cdesc)
1111b44c5a6SAntoine Ténart {
11218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
11341abed7dSPascal van Leeuwen 	u64 count = 0;
1141b44c5a6SAntoine Ténart 
115a7cf8658SPascal van Leeuwen 	cdesc->control_data.control0 = ctx->alg;
116098e51e5SPascal van Leeuwen 	cdesc->control_data.control1 = 0;
117dc5268b6SPascal van Leeuwen 
1181b44c5a6SAntoine Ténart 	/*
1191b44c5a6SAntoine Ténart 	 * Copy the input digest if needed, and setup the context
1201b44c5a6SAntoine Ténart 	 * fields. Do this now as we need it to setup the first command
1211b44c5a6SAntoine Ténart 	 * descriptor.
1221b44c5a6SAntoine Ténart 	 */
123a7cf8658SPascal van Leeuwen 	if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) {
124b98687bbSPascal van Leeuwen 		if (req->xcbcmac)
12578cf1c8bSHerbert Xu 			memcpy(ctx->base.ctxr->data, &ctx->base.ipad, ctx->key_sz);
126b98687bbSPascal van Leeuwen 		else
127b98687bbSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
128a7cf8658SPascal van Leeuwen 
129b98687bbSPascal van Leeuwen 		if (!req->finish && req->xcbcmac)
130b98687bbSPascal van Leeuwen 			cdesc->control_data.control0 |=
131b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
132a7cf8658SPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
133b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_NO_FINISH_HASH |
134b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz /
135b98687bbSPascal van Leeuwen 						     sizeof(u32));
136b98687bbSPascal van Leeuwen 		else
137b98687bbSPascal van Leeuwen 			cdesc->control_data.control0 |=
138b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
139b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
140b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz /
141b98687bbSPascal van Leeuwen 						     sizeof(u32));
142a7cf8658SPascal van Leeuwen 		return;
143a7cf8658SPascal van Leeuwen 	} else if (!req->processed) {
14441abed7dSPascal van Leeuwen 		/* First - and possibly only - block of basic hash only */
145b98687bbSPascal van Leeuwen 		if (req->finish)
146a7cf8658SPascal van Leeuwen 			cdesc->control_data.control0 |= req->digest |
14741abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
14841abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH  |
14941abed7dSPascal van Leeuwen 				/* ensure its not 0! */
15041abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
151b98687bbSPascal van Leeuwen 		else
152a7cf8658SPascal van Leeuwen 			cdesc->control_data.control0 |= req->digest |
15341abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
15441abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH   |
15541abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_NO_FINISH_HASH |
15641abed7dSPascal van Leeuwen 				/* ensure its not 0! */
15741abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
15841abed7dSPascal van Leeuwen 		return;
15941abed7dSPascal van Leeuwen 	}
16041abed7dSPascal van Leeuwen 
16141abed7dSPascal van Leeuwen 	/* Hash continuation or HMAC, setup (inner) digest from state */
16241abed7dSPascal van Leeuwen 	memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
1631b44c5a6SAntoine Ténart 
164b460edb6SAntoine Tenart 	if (req->finish) {
16541abed7dSPascal van Leeuwen 		/* Compute digest count for hash/HMAC finish operations */
16641abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
16731fb084cSPascal van Leeuwen 		    req->hmac_zlen || (req->processed != req->block_sz)) {
16831fb084cSPascal van Leeuwen 			count = req->processed / EIP197_COUNTER_BLOCK_SIZE;
169b460edb6SAntoine Tenart 
17041abed7dSPascal van Leeuwen 			/* This is a hardware limitation, as the
171b460edb6SAntoine Tenart 			 * counter must fit into an u32. This represents
17241abed7dSPascal van Leeuwen 			 * a fairly big amount of input data, so we
173b460edb6SAntoine Tenart 			 * shouldn't see this.
174b460edb6SAntoine Tenart 			 */
17541abed7dSPascal van Leeuwen 			if (unlikely(count & 0xffffffff00000000ULL)) {
176b460edb6SAntoine Tenart 				dev_warn(priv->dev,
177b460edb6SAntoine Tenart 					 "Input data is too big\n");
178b460edb6SAntoine Tenart 				return;
179b460edb6SAntoine Tenart 			}
180b460edb6SAntoine Tenart 		}
1811b44c5a6SAntoine Ténart 
18241abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
18385b36ee8SPascal van Leeuwen 		    /* Special case: zero length HMAC */
18485b36ee8SPascal van Leeuwen 		    req->hmac_zlen ||
18541abed7dSPascal van Leeuwen 		    /* PE HW < 4.4 cannot do HMAC continue, fake using hash */
18631fb084cSPascal van Leeuwen 		    (req->processed != req->block_sz)) {
18741abed7dSPascal van Leeuwen 			/* Basic hash continue operation, need digest + cnt */
18841abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
18941abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) |
19041abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
19141abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
19285b36ee8SPascal van Leeuwen 			/* For zero-len HMAC, don't finalize, already padded! */
19385b36ee8SPascal van Leeuwen 			if (req->hmac_zlen)
19485b36ee8SPascal van Leeuwen 				cdesc->control_data.control0 |=
19585b36ee8SPascal van Leeuwen 					CONTEXT_CONTROL_NO_FINISH_HASH;
19641abed7dSPascal van Leeuwen 			cdesc->control_data.control1 |=
19741abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_CNT;
19841abed7dSPascal van Leeuwen 			ctx->base.ctxr->data[req->state_sz >> 2] =
19941abed7dSPascal van Leeuwen 				cpu_to_le32(count);
20041abed7dSPascal van Leeuwen 			req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
20185b36ee8SPascal van Leeuwen 
20285b36ee8SPascal van Leeuwen 			/* Clear zero-length HMAC flag for next operation! */
20385b36ee8SPascal van Leeuwen 			req->hmac_zlen = false;
20441abed7dSPascal van Leeuwen 		} else { /* HMAC */
20541abed7dSPascal van Leeuwen 			/* Need outer digest for HMAC finalization */
20641abed7dSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (req->state_sz >> 2),
20778cf1c8bSHerbert Xu 			       &ctx->base.opad, req->state_sz);
20841abed7dSPascal van Leeuwen 
20941abed7dSPascal van Leeuwen 			/* Single pass HMAC - no digest count */
21041abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
21141abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz >> 1) |
21241abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
21341abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_HMAC;
21441abed7dSPascal van Leeuwen 		}
21541abed7dSPascal van Leeuwen 	} else { /* Hash continuation, do not finish yet */
21641abed7dSPascal van Leeuwen 		cdesc->control_data.control0 |=
21741abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_SIZE(req->state_sz >> 2) |
21841abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_DIGEST_PRECOMPUTED |
21941abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_TYPE_HASH_OUT |
22041abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_NO_FINISH_HASH;
2211b44c5a6SAntoine Ténart 	}
2221b44c5a6SAntoine Ténart }
2231b44c5a6SAntoine Ténart 
22441abed7dSPascal van Leeuwen static int safexcel_ahash_enqueue(struct ahash_request *areq);
22541abed7dSPascal van Leeuwen 
22641abed7dSPascal van Leeuwen static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv,
22741abed7dSPascal van Leeuwen 				      int ring,
2281b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
2291b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
2301b44c5a6SAntoine Ténart {
2311b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
2321b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
2331b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2341b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *sreq = ahash_request_ctx(areq);
23541abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
236b460edb6SAntoine Tenart 	u64 cache_len;
2371b44c5a6SAntoine Ténart 
2381b44c5a6SAntoine Ténart 	*ret = 0;
2391b44c5a6SAntoine Ténart 
2401b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
2411b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
2421b44c5a6SAntoine Ténart 		dev_err(priv->dev,
2431b44c5a6SAntoine Ténart 			"hash: result: could not retrieve the result descriptor\n");
2441b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
245bdfd1909SAntoine Tenart 	} else {
246bdfd1909SAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
2471b44c5a6SAntoine Ténart 	}
2481b44c5a6SAntoine Ténart 
2491b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
2501b44c5a6SAntoine Ténart 
251c957f8b3SAntoine Ténart 	if (sreq->nents) {
252c957f8b3SAntoine Ténart 		dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE);
253c957f8b3SAntoine Ténart 		sreq->nents = 0;
254c957f8b3SAntoine Ténart 	}
2551b44c5a6SAntoine Ténart 
256b8592027SOfer Heifetz 	if (sreq->result_dma) {
2576c1c09b3SPascal van Leeuwen 		dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz,
258b8592027SOfer Heifetz 				 DMA_FROM_DEVICE);
259b8592027SOfer Heifetz 		sreq->result_dma = 0;
260b8592027SOfer Heifetz 	}
261b8592027SOfer Heifetz 
262cff9a175SAntoine Tenart 	if (sreq->cache_dma) {
263cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz,
264cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
265cff9a175SAntoine Tenart 		sreq->cache_dma = 0;
266aa524286SAntoine Tenart 		sreq->cache_sz = 0;
267cff9a175SAntoine Tenart 	}
2681b44c5a6SAntoine Ténart 
26941abed7dSPascal van Leeuwen 	if (sreq->finish) {
27041abed7dSPascal van Leeuwen 		if (sreq->hmac &&
27141abed7dSPascal van Leeuwen 		    (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) {
27241abed7dSPascal van Leeuwen 			/* Faking HMAC using hash - need to do outer hash */
27341abed7dSPascal van Leeuwen 			memcpy(sreq->cache, sreq->state,
27441abed7dSPascal van Leeuwen 			       crypto_ahash_digestsize(ahash));
27541abed7dSPascal van Leeuwen 
27678cf1c8bSHerbert Xu 			memcpy(sreq->state, &ctx->base.opad, sreq->digest_sz);
27741abed7dSPascal van Leeuwen 
27831fb084cSPascal van Leeuwen 			sreq->len = sreq->block_sz +
27941abed7dSPascal van Leeuwen 				    crypto_ahash_digestsize(ahash);
28031fb084cSPascal van Leeuwen 			sreq->processed = sreq->block_sz;
28141abed7dSPascal van Leeuwen 			sreq->hmac = 0;
28241abed7dSPascal van Leeuwen 
283177e358cSPascal van Leeuwen 			if (priv->flags & EIP197_TRC_CACHE)
28441abed7dSPascal van Leeuwen 				ctx->base.needs_inv = true;
28541abed7dSPascal van Leeuwen 			areq->nbytes = 0;
28641abed7dSPascal van Leeuwen 			safexcel_ahash_enqueue(areq);
28741abed7dSPascal van Leeuwen 
28841abed7dSPascal van Leeuwen 			*should_complete = false; /* Not done yet */
28941abed7dSPascal van Leeuwen 			return 1;
29041abed7dSPascal van Leeuwen 		}
29141abed7dSPascal van Leeuwen 
292b98687bbSPascal van Leeuwen 		if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM &&
293b98687bbSPascal van Leeuwen 			     ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) {
294a7cf8658SPascal van Leeuwen 			/* Undo final XOR with 0xffffffff ...*/
29513a1bb93SPascal van Leeuwen 			*(__le32 *)areq->result = ~sreq->state[0];
296a7cf8658SPascal van Leeuwen 		} else {
297b89a8159SAntoine Tenart 			memcpy(areq->result, sreq->state,
298b89a8159SAntoine Tenart 			       crypto_ahash_digestsize(ahash));
29941abed7dSPascal van Leeuwen 		}
300a7cf8658SPascal van Leeuwen 	}
301b89a8159SAntoine Tenart 
302b460edb6SAntoine Tenart 	cache_len = safexcel_queued_len(sreq);
3031b44c5a6SAntoine Ténart 	if (cache_len)
3041b44c5a6SAntoine Ténart 		memcpy(sreq->cache, sreq->cache_next, cache_len);
3051b44c5a6SAntoine Ténart 
3061b44c5a6SAntoine Ténart 	*should_complete = true;
3071b44c5a6SAntoine Ténart 
3081b44c5a6SAntoine Ténart 	return 1;
3091b44c5a6SAntoine Ténart }
3101b44c5a6SAntoine Ténart 
3111eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring,
3121eb7b403SOfer Heifetz 				   int *commands, int *results)
3131b44c5a6SAntoine Ténart {
3141b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
3151b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
3161b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
31718e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
3181b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc, *first_cdesc = NULL;
3191b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
3201b44c5a6SAntoine Ténart 	struct scatterlist *sg;
321098e51e5SPascal van Leeuwen 	struct safexcel_token *dmmy;
3226c1c09b3SPascal van Leeuwen 	int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0;
323b98687bbSPascal van Leeuwen 	u64 queued, len;
3241b44c5a6SAntoine Ténart 
325b98687bbSPascal van Leeuwen 	queued = safexcel_queued_len(req);
32641abed7dSPascal van Leeuwen 	if (queued <= HASH_CACHE_SIZE)
3271b44c5a6SAntoine Ténart 		cache_len = queued;
3281b44c5a6SAntoine Ténart 	else
3291b44c5a6SAntoine Ténart 		cache_len = queued - areq->nbytes;
3301b44c5a6SAntoine Ténart 
33141abed7dSPascal van Leeuwen 	if (!req->finish && !req->last_req) {
332809778e0SAntoine Ténart 		/* If this is not the last request and the queued data does not
33341abed7dSPascal van Leeuwen 		 * fit into full cache blocks, cache it for the next send call.
3341b44c5a6SAntoine Ténart 		 */
33541abed7dSPascal van Leeuwen 		extra = queued & (HASH_CACHE_SIZE - 1);
336082ec2d4SAntoine Tenart 
337809778e0SAntoine Ténart 		/* If this is not the last request and the queued data
338809778e0SAntoine Ténart 		 * is a multiple of a block, cache the last one for now.
339809778e0SAntoine Ténart 		 */
340dd4306a6SAntoine Tenart 		if (!extra)
34141abed7dSPascal van Leeuwen 			extra = HASH_CACHE_SIZE;
342809778e0SAntoine Ténart 
3431b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
344809778e0SAntoine Ténart 				   req->cache_next, extra,
345809778e0SAntoine Ténart 				   areq->nbytes - extra);
3461b44c5a6SAntoine Ténart 
3471b44c5a6SAntoine Ténart 		queued -= extra;
348dc5268b6SPascal van Leeuwen 
349dc5268b6SPascal van Leeuwen 		if (!queued) {
350dc5268b6SPascal van Leeuwen 			*commands = 0;
351dc5268b6SPascal van Leeuwen 			*results = 0;
352dc5268b6SPascal van Leeuwen 			return 0;
353dc5268b6SPascal van Leeuwen 		}
354b98687bbSPascal van Leeuwen 
355b98687bbSPascal van Leeuwen 		extra = 0;
356809778e0SAntoine Ténart 	}
3571b44c5a6SAntoine Ténart 
358b98687bbSPascal van Leeuwen 	if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) {
359b98687bbSPascal van Leeuwen 		if (unlikely(cache_len < AES_BLOCK_SIZE)) {
360b98687bbSPascal van Leeuwen 			/*
361b98687bbSPascal van Leeuwen 			 * Cache contains less than 1 full block, complete.
362b98687bbSPascal van Leeuwen 			 */
363b98687bbSPascal van Leeuwen 			extra = AES_BLOCK_SIZE - cache_len;
364b98687bbSPascal van Leeuwen 			if (queued > cache_len) {
365b98687bbSPascal van Leeuwen 				/* More data follows: borrow bytes */
366b98687bbSPascal van Leeuwen 				u64 tmp = queued - cache_len;
367b98687bbSPascal van Leeuwen 
368b98687bbSPascal van Leeuwen 				skip = min_t(u64, tmp, extra);
369b98687bbSPascal van Leeuwen 				sg_pcopy_to_buffer(areq->src,
370b98687bbSPascal van Leeuwen 					sg_nents(areq->src),
371b98687bbSPascal van Leeuwen 					req->cache + cache_len,
372b98687bbSPascal van Leeuwen 					skip, 0);
373b98687bbSPascal van Leeuwen 			}
374b98687bbSPascal van Leeuwen 			extra -= skip;
375b98687bbSPascal van Leeuwen 			memset(req->cache + cache_len + skip, 0, extra);
37638f21b4bSPascal van Leeuwen 			if (!ctx->cbcmac && extra) {
37738f21b4bSPascal van Leeuwen 				// 10- padding for XCBCMAC & CMAC
37838f21b4bSPascal van Leeuwen 				req->cache[cache_len + skip] = 0x80;
37938f21b4bSPascal van Leeuwen 				// HW will use K2 iso K3 - compensate!
38078cf1c8bSHerbert Xu 				for (i = 0; i < AES_BLOCK_SIZE / 4; i++) {
38178cf1c8bSHerbert Xu 					u32 *cache = (void *)req->cache;
38278cf1c8bSHerbert Xu 					u32 *ipad = ctx->base.ipad.word;
38378cf1c8bSHerbert Xu 					u32 x;
38478cf1c8bSHerbert Xu 
38578cf1c8bSHerbert Xu 					x = ipad[i] ^ ipad[i + 4];
38666459340SPeter Harliman Liem 					cache[i] ^= swab32(x);
38778cf1c8bSHerbert Xu 				}
38838f21b4bSPascal van Leeuwen 			}
389b98687bbSPascal van Leeuwen 			cache_len = AES_BLOCK_SIZE;
390b98687bbSPascal van Leeuwen 			queued = queued + extra;
391b98687bbSPascal van Leeuwen 		}
392b98687bbSPascal van Leeuwen 
393b98687bbSPascal van Leeuwen 		/* XCBC continue: XOR previous result into 1st word */
394b98687bbSPascal van Leeuwen 		crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE);
395b98687bbSPascal van Leeuwen 	}
396b98687bbSPascal van Leeuwen 
397b98687bbSPascal van Leeuwen 	len = queued;
3981b44c5a6SAntoine Ténart 	/* Add a command descriptor for the cached data, if any */
3991b44c5a6SAntoine Ténart 	if (cache_len) {
400cff9a175SAntoine Tenart 		req->cache_dma = dma_map_single(priv->dev, req->cache,
4011b44c5a6SAntoine Ténart 						cache_len, DMA_TO_DEVICE);
4029744fec9SOfer Heifetz 		if (dma_mapping_error(priv->dev, req->cache_dma))
403cff9a175SAntoine Tenart 			return -EINVAL;
4041b44c5a6SAntoine Ténart 
405cff9a175SAntoine Tenart 		req->cache_sz = cache_len;
4061b44c5a6SAntoine Ténart 		first_cdesc = safexcel_add_cdesc(priv, ring, 1,
4071b44c5a6SAntoine Ténart 						 (cache_len == len),
408b98687bbSPascal van Leeuwen 						 req->cache_dma, cache_len,
409098e51e5SPascal van Leeuwen 						 len, ctx->base.ctxr_dma,
410098e51e5SPascal van Leeuwen 						 &dmmy);
4111b44c5a6SAntoine Ténart 		if (IS_ERR(first_cdesc)) {
4121b44c5a6SAntoine Ténart 			ret = PTR_ERR(first_cdesc);
4131b44c5a6SAntoine Ténart 			goto unmap_cache;
4141b44c5a6SAntoine Ténart 		}
4151b44c5a6SAntoine Ténart 		n_cdesc++;
4161b44c5a6SAntoine Ténart 
4171b44c5a6SAntoine Ténart 		queued -= cache_len;
4181b44c5a6SAntoine Ténart 		if (!queued)
4191b44c5a6SAntoine Ténart 			goto send_command;
4201b44c5a6SAntoine Ténart 	}
4211b44c5a6SAntoine Ténart 
4221b44c5a6SAntoine Ténart 	/* Now handle the current ahash request buffer(s) */
42341abed7dSPascal van Leeuwen 	req->nents = dma_map_sg(priv->dev, areq->src,
42441abed7dSPascal van Leeuwen 				sg_nents_for_len(areq->src,
42541abed7dSPascal van Leeuwen 						 areq->nbytes),
4261b44c5a6SAntoine Ténart 				DMA_TO_DEVICE);
427c957f8b3SAntoine Ténart 	if (!req->nents) {
4281b44c5a6SAntoine Ténart 		ret = -ENOMEM;
4291b44c5a6SAntoine Ténart 		goto cdesc_rollback;
4301b44c5a6SAntoine Ténart 	}
4311b44c5a6SAntoine Ténart 
432c957f8b3SAntoine Ténart 	for_each_sg(areq->src, sg, req->nents, i) {
4331b44c5a6SAntoine Ténart 		int sglen = sg_dma_len(sg);
4341b44c5a6SAntoine Ténart 
435b98687bbSPascal van Leeuwen 		if (unlikely(sglen <= skip)) {
436b98687bbSPascal van Leeuwen 			skip -= sglen;
437b98687bbSPascal van Leeuwen 			continue;
438b98687bbSPascal van Leeuwen 		}
439b98687bbSPascal van Leeuwen 
4401b44c5a6SAntoine Ténart 		/* Do not overflow the request */
441b98687bbSPascal van Leeuwen 		if ((queued + skip) <= sglen)
4421b44c5a6SAntoine Ténart 			sglen = queued;
443b98687bbSPascal van Leeuwen 		else
444b98687bbSPascal van Leeuwen 			sglen -= skip;
4451b44c5a6SAntoine Ténart 
4461b44c5a6SAntoine Ténart 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
44741abed7dSPascal van Leeuwen 					   !(queued - sglen),
448b98687bbSPascal van Leeuwen 					   sg_dma_address(sg) + skip, sglen,
449098e51e5SPascal van Leeuwen 					   len, ctx->base.ctxr_dma, &dmmy);
4501b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
4511b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
45257433b58SAntoine Tenart 			goto unmap_sg;
4531b44c5a6SAntoine Ténart 		}
4541b44c5a6SAntoine Ténart 
455b98687bbSPascal van Leeuwen 		if (!n_cdesc)
4561b44c5a6SAntoine Ténart 			first_cdesc = cdesc;
457b98687bbSPascal van Leeuwen 		n_cdesc++;
4581b44c5a6SAntoine Ténart 
4591b44c5a6SAntoine Ténart 		queued -= sglen;
4601b44c5a6SAntoine Ténart 		if (!queued)
4611b44c5a6SAntoine Ténart 			break;
462b98687bbSPascal van Leeuwen 		skip = 0;
4631b44c5a6SAntoine Ténart 	}
4641b44c5a6SAntoine Ténart 
4651b44c5a6SAntoine Ténart send_command:
4661b44c5a6SAntoine Ténart 	/* Setup the context options */
46741abed7dSPascal van Leeuwen 	safexcel_context_control(ctx, req, first_cdesc);
4681b44c5a6SAntoine Ténart 
4696c1c09b3SPascal van Leeuwen 	/* Add the token */
4706c1c09b3SPascal van Leeuwen 	safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac);
4711b44c5a6SAntoine Ténart 
4726c1c09b3SPascal van Leeuwen 	req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz,
473b8592027SOfer Heifetz 					 DMA_FROM_DEVICE);
474b8592027SOfer Heifetz 	if (dma_mapping_error(priv->dev, req->result_dma)) {
4751b44c5a6SAntoine Ténart 		ret = -EINVAL;
47657433b58SAntoine Tenart 		goto unmap_sg;
4771b44c5a6SAntoine Ténart 	}
4781b44c5a6SAntoine Ténart 
4791b44c5a6SAntoine Ténart 	/* Add a result descriptor */
480b8592027SOfer Heifetz 	rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma,
4816c1c09b3SPascal van Leeuwen 				   req->digest_sz);
4821b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
4831b44c5a6SAntoine Ténart 		ret = PTR_ERR(rdesc);
48457240a78SAntoine Tenart 		goto unmap_result;
4851b44c5a6SAntoine Ténart 	}
4861b44c5a6SAntoine Ténart 
4879744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, rdesc, &areq->base);
4881b44c5a6SAntoine Ténart 
489b98687bbSPascal van Leeuwen 	req->processed += len - extra;
490b460edb6SAntoine Tenart 
4911b44c5a6SAntoine Ténart 	*commands = n_cdesc;
4921b44c5a6SAntoine Ténart 	*results = 1;
4931b44c5a6SAntoine Ténart 	return 0;
4941b44c5a6SAntoine Ténart 
49557240a78SAntoine Tenart unmap_result:
4966c1c09b3SPascal van Leeuwen 	dma_unmap_single(priv->dev, req->result_dma, req->digest_sz,
49757433b58SAntoine Tenart 			 DMA_FROM_DEVICE);
49857433b58SAntoine Tenart unmap_sg:
499b98687bbSPascal van Leeuwen 	if (req->nents) {
50057240a78SAntoine Tenart 		dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE);
501b98687bbSPascal van Leeuwen 		req->nents = 0;
502b98687bbSPascal van Leeuwen 	}
5031b44c5a6SAntoine Ténart cdesc_rollback:
5041b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
5051b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
5061b44c5a6SAntoine Ténart unmap_cache:
507cff9a175SAntoine Tenart 	if (req->cache_dma) {
508cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz,
509cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
510aa524286SAntoine Tenart 		req->cache_dma = 0;
511cff9a175SAntoine Tenart 		req->cache_sz = 0;
5121b44c5a6SAntoine Ténart 	}
5131b44c5a6SAntoine Ténart 
5141b44c5a6SAntoine Ténart 	return ret;
5151b44c5a6SAntoine Ténart }
5161b44c5a6SAntoine Ténart 
5171b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
5181b44c5a6SAntoine Ténart 				      int ring,
5191b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
5201b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
5211b44c5a6SAntoine Ténart {
5221b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
5231b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
5241b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
5251b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
5261b44c5a6SAntoine Ténart 	int enq_ret;
5271b44c5a6SAntoine Ténart 
5281b44c5a6SAntoine Ténart 	*ret = 0;
5291b44c5a6SAntoine Ténart 
5301b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
5311b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
5321b44c5a6SAntoine Ténart 		dev_err(priv->dev,
5331b44c5a6SAntoine Ténart 			"hash: invalidate: could not retrieve the result descriptor\n");
5341b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
535cda3e73aSAntoine Tenart 	} else {
536cda3e73aSAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
5371b44c5a6SAntoine Ténart 	}
5381b44c5a6SAntoine Ténart 
5391b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
5401b44c5a6SAntoine Ténart 
5411b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
5421b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
5431b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
5441b44c5a6SAntoine Ténart 
5451b44c5a6SAntoine Ténart 		*should_complete = true;
5461b44c5a6SAntoine Ténart 		return 1;
5471b44c5a6SAntoine Ténart 	}
5481b44c5a6SAntoine Ténart 
54986671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
55086671abbSAntoine Ténart 	ctx->base.ring = ring;
5511b44c5a6SAntoine Ténart 
55286671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
55386671abbSAntoine Ténart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async);
55486671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
5551b44c5a6SAntoine Ténart 
5561b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
5571b44c5a6SAntoine Ténart 		*ret = enq_ret;
5581b44c5a6SAntoine Ténart 
5598472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
5608472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
56186671abbSAntoine Ténart 
5621b44c5a6SAntoine Ténart 	*should_complete = false;
5631b44c5a6SAntoine Ténart 
5641b44c5a6SAntoine Ténart 	return 1;
5651b44c5a6SAntoine Ténart }
5661b44c5a6SAntoine Ténart 
5671eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring,
5681eb7b403SOfer Heifetz 				  struct crypto_async_request *async,
5691eb7b403SOfer Heifetz 				  bool *should_complete, int *ret)
5701eb7b403SOfer Heifetz {
5711eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
5721eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5731eb7b403SOfer Heifetz 	int err;
5741eb7b403SOfer Heifetz 
57553c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv);
576871df319SAntoine Ténart 
5771eb7b403SOfer Heifetz 	if (req->needs_inv) {
5781eb7b403SOfer Heifetz 		req->needs_inv = false;
5791eb7b403SOfer Heifetz 		err = safexcel_handle_inv_result(priv, ring, async,
5801eb7b403SOfer Heifetz 						 should_complete, ret);
5811eb7b403SOfer Heifetz 	} else {
5821eb7b403SOfer Heifetz 		err = safexcel_handle_req_result(priv, ring, async,
5831eb7b403SOfer Heifetz 						 should_complete, ret);
5841eb7b403SOfer Heifetz 	}
5851eb7b403SOfer Heifetz 
5861eb7b403SOfer Heifetz 	return err;
5871eb7b403SOfer Heifetz }
5881eb7b403SOfer Heifetz 
5891b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async,
5909744fec9SOfer Heifetz 				   int ring, int *commands, int *results)
5911b44c5a6SAntoine Ténart {
5921b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
5931b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
5941b44c5a6SAntoine Ténart 	int ret;
5951b44c5a6SAntoine Ténart 
59618e51895SHerbert Xu 	ret = safexcel_invalidate_cache(async, ctx->base.priv,
5979744fec9SOfer Heifetz 					ctx->base.ctxr_dma, ring);
5981b44c5a6SAntoine Ténart 	if (unlikely(ret))
5991b44c5a6SAntoine Ténart 		return ret;
6001b44c5a6SAntoine Ténart 
6011b44c5a6SAntoine Ténart 	*commands = 1;
6021b44c5a6SAntoine Ténart 	*results = 1;
6031b44c5a6SAntoine Ténart 
6041b44c5a6SAntoine Ténart 	return 0;
6051b44c5a6SAntoine Ténart }
6061b44c5a6SAntoine Ténart 
6071eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async,
6089744fec9SOfer Heifetz 			       int ring, int *commands, int *results)
6091eb7b403SOfer Heifetz {
6101eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
6111eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6121eb7b403SOfer Heifetz 	int ret;
6131eb7b403SOfer Heifetz 
6141eb7b403SOfer Heifetz 	if (req->needs_inv)
6159744fec9SOfer Heifetz 		ret = safexcel_ahash_send_inv(async, ring, commands, results);
6161eb7b403SOfer Heifetz 	else
6179744fec9SOfer Heifetz 		ret = safexcel_ahash_send_req(async, ring, commands, results);
6189744fec9SOfer Heifetz 
6191eb7b403SOfer Heifetz 	return ret;
6201eb7b403SOfer Heifetz }
6211eb7b403SOfer Heifetz 
6221b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm)
6231b44c5a6SAntoine Ténart {
6241b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
62518e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
62661824806SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE);
6277cad2fabSAntoine Ténart 	struct safexcel_ahash_req *rctx = ahash_request_ctx(req);
6283e1166b9SArnd Bergmann 	struct safexcel_inv_result result = {};
62986671abbSAntoine Ténart 	int ring = ctx->base.ring;
6301b44c5a6SAntoine Ténart 
631b926213dSAntoine Tenart 	memset(req, 0, EIP197_AHASH_REQ_SIZE);
6321b44c5a6SAntoine Ténart 
6331b44c5a6SAntoine Ténart 	/* create invalidation request */
6341b44c5a6SAntoine Ténart 	init_completion(&result.completion);
6357cad2fabSAntoine Ténart 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
6361b44c5a6SAntoine Ténart 				   safexcel_inv_complete, &result);
6371b44c5a6SAntoine Ténart 
6387cad2fabSAntoine Ténart 	ahash_request_set_tfm(req, __crypto_ahash_cast(tfm));
6397cad2fabSAntoine Ténart 	ctx = crypto_tfm_ctx(req->base.tfm);
6401b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
6411eb7b403SOfer Heifetz 	rctx->needs_inv = true;
6421b44c5a6SAntoine Ténart 
64386671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
6447cad2fabSAntoine Ténart 	crypto_enqueue_request(&priv->ring[ring].queue, &req->base);
64586671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
6461b44c5a6SAntoine Ténart 
6478472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
6488472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
6491b44c5a6SAntoine Ténart 
650b7007dbcSAntoine Tenart 	wait_for_completion(&result.completion);
6511b44c5a6SAntoine Ténart 
6521b44c5a6SAntoine Ténart 	if (result.error) {
6531b44c5a6SAntoine Ténart 		dev_warn(priv->dev, "hash: completion error (%d)\n",
6541b44c5a6SAntoine Ténart 			 result.error);
6551b44c5a6SAntoine Ténart 		return result.error;
6561b44c5a6SAntoine Ténart 	}
6571b44c5a6SAntoine Ténart 
6581b44c5a6SAntoine Ténart 	return 0;
6591b44c5a6SAntoine Ténart }
6601b44c5a6SAntoine Ténart 
661cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to
662cc75f5ceSAntoine Ténart  * the engine, aka. when there is at least 1 block size in the pipe.
663cc75f5ceSAntoine Ténart  */
66441abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq)
6651b44c5a6SAntoine Ténart {
6661b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
66741abed7dSPascal van Leeuwen 	u64 cache_len;
6681b44c5a6SAntoine Ténart 
669b460edb6SAntoine Tenart 	/* cache_len: everything accepted by the driver but not sent yet,
670b460edb6SAntoine Tenart 	 * tot sz handled by update() - last req sz - tot sz handled by send()
671b460edb6SAntoine Tenart 	 */
67241abed7dSPascal van Leeuwen 	cache_len = safexcel_queued_len(req);
6731b44c5a6SAntoine Ténart 
6741b44c5a6SAntoine Ténart 	/*
6751b44c5a6SAntoine Ténart 	 * In case there isn't enough bytes to proceed (less than a
6761b44c5a6SAntoine Ténart 	 * block size), cache the data until we have enough.
6771b44c5a6SAntoine Ténart 	 */
67841abed7dSPascal van Leeuwen 	if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) {
6791b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
6801b44c5a6SAntoine Ténart 				   req->cache + cache_len,
6811b44c5a6SAntoine Ténart 				   areq->nbytes, 0);
68241abed7dSPascal van Leeuwen 		return 0;
6831b44c5a6SAntoine Ténart 	}
6841b44c5a6SAntoine Ténart 
685dfbcc08fSAntoine Ténart 	/* We couldn't cache all the data */
6861b44c5a6SAntoine Ténart 	return -E2BIG;
6871b44c5a6SAntoine Ténart }
6881b44c5a6SAntoine Ténart 
6891b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq)
6901b44c5a6SAntoine Ténart {
6911b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
6921b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
69318e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
69486671abbSAntoine Ténart 	int ret, ring;
6951b44c5a6SAntoine Ténart 
6961eb7b403SOfer Heifetz 	req->needs_inv = false;
6971b44c5a6SAntoine Ténart 
698c4daf4ccSOfer Heifetz 	if (ctx->base.ctxr) {
69953c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv &&
700b98687bbSPascal van Leeuwen 		     /* invalidate for *any* non-XCBC continuation */
701b98687bbSPascal van Leeuwen 		   ((req->not_first && !req->xcbcmac) ||
70241abed7dSPascal van Leeuwen 		     /* invalidate if (i)digest changed */
70341abed7dSPascal van Leeuwen 		     memcmp(ctx->base.ctxr->data, req->state, req->state_sz) ||
70441abed7dSPascal van Leeuwen 		     /* invalidate for HMAC finish with odigest changed */
705a7cf8658SPascal van Leeuwen 		     (req->finish && req->hmac &&
70641abed7dSPascal van Leeuwen 		      memcmp(ctx->base.ctxr->data + (req->state_sz>>2),
70778cf1c8bSHerbert Xu 			     &ctx->base.opad, req->state_sz))))
70841abed7dSPascal van Leeuwen 			/*
70941abed7dSPascal van Leeuwen 			 * We're still setting needs_inv here, even though it is
710c4daf4ccSOfer Heifetz 			 * cleared right away, because the needs_inv flag can be
711c4daf4ccSOfer Heifetz 			 * set in other functions and we want to keep the same
712c4daf4ccSOfer Heifetz 			 * logic.
713c4daf4ccSOfer Heifetz 			 */
71441abed7dSPascal van Leeuwen 			ctx->base.needs_inv = true;
7151b44c5a6SAntoine Ténart 
7161eb7b403SOfer Heifetz 		if (ctx->base.needs_inv) {
7171eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
7181eb7b403SOfer Heifetz 			req->needs_inv = true;
7191eb7b403SOfer Heifetz 		}
7201b44c5a6SAntoine Ténart 	} else {
7211b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
7221b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
7231b44c5a6SAntoine Ténart 						 EIP197_GFP_FLAGS(areq->base),
7241b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
7251b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
7261b44c5a6SAntoine Ténart 			return -ENOMEM;
7271b44c5a6SAntoine Ténart 	}
728b98687bbSPascal van Leeuwen 	req->not_first = true;
7291b44c5a6SAntoine Ténart 
73086671abbSAntoine Ténart 	ring = ctx->base.ring;
7311b44c5a6SAntoine Ténart 
73286671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
73386671abbSAntoine Ténart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base);
73486671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
73586671abbSAntoine Ténart 
7368472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
7378472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
7381b44c5a6SAntoine Ténart 
7391b44c5a6SAntoine Ténart 	return ret;
7401b44c5a6SAntoine Ténart }
7411b44c5a6SAntoine Ténart 
7421b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq)
7431b44c5a6SAntoine Ténart {
7441b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
74541abed7dSPascal van Leeuwen 	int ret;
7461b44c5a6SAntoine Ténart 
7471b44c5a6SAntoine Ténart 	/* If the request is 0 length, do nothing */
7481b44c5a6SAntoine Ténart 	if (!areq->nbytes)
7491b44c5a6SAntoine Ténart 		return 0;
7501b44c5a6SAntoine Ténart 
75141abed7dSPascal van Leeuwen 	/* Add request to the cache if it fits */
75241abed7dSPascal van Leeuwen 	ret = safexcel_ahash_cache(areq);
75341abed7dSPascal van Leeuwen 
75441abed7dSPascal van Leeuwen 	/* Update total request length */
75531fb084cSPascal van Leeuwen 	req->len += areq->nbytes;
7561b44c5a6SAntoine Ténart 
75741abed7dSPascal van Leeuwen 	/* If not all data could fit into the cache, go process the excess.
75841abed7dSPascal van Leeuwen 	 * Also go process immediately for an HMAC IV precompute, which
75941abed7dSPascal van Leeuwen 	 * will never be finished at all, but needs to be processed anyway.
7601b44c5a6SAntoine Ténart 	 */
76141abed7dSPascal van Leeuwen 	if ((ret && !req->finish) || req->last_req)
7621b44c5a6SAntoine Ténart 		return safexcel_ahash_enqueue(areq);
7631b44c5a6SAntoine Ténart 
7641b44c5a6SAntoine Ténart 	return 0;
7651b44c5a6SAntoine Ténart }
7661b44c5a6SAntoine Ténart 
7671b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq)
7681b44c5a6SAntoine Ténart {
7691b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
7701b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
7711b44c5a6SAntoine Ténart 
7721b44c5a6SAntoine Ténart 	req->finish = true;
7731b44c5a6SAntoine Ténart 
77431fb084cSPascal van Leeuwen 	if (unlikely(!req->len && !areq->nbytes)) {
77585695b09SPascal van Leeuwen 		/*
77685695b09SPascal van Leeuwen 		 * If we have an overall 0 length *hash* request:
77785695b09SPascal van Leeuwen 		 * The HW cannot do 0 length hash, so we provide the correct
77885695b09SPascal van Leeuwen 		 * result directly here.
77985695b09SPascal van Leeuwen 		 */
780293f89cfSOfer Heifetz 		if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5)
781293f89cfSOfer Heifetz 			memcpy(areq->result, md5_zero_message_hash,
782293f89cfSOfer Heifetz 			       MD5_DIGEST_SIZE);
783293f89cfSOfer Heifetz 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1)
7841b44c5a6SAntoine Ténart 			memcpy(areq->result, sha1_zero_message_hash,
7851b44c5a6SAntoine Ténart 			       SHA1_DIGEST_SIZE);
7861b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224)
7871b44c5a6SAntoine Ténart 			memcpy(areq->result, sha224_zero_message_hash,
7881b44c5a6SAntoine Ténart 			       SHA224_DIGEST_SIZE);
7891b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256)
7901b44c5a6SAntoine Ténart 			memcpy(areq->result, sha256_zero_message_hash,
7911b44c5a6SAntoine Ténart 			       SHA256_DIGEST_SIZE);
7929e46eafdSAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384)
7939e46eafdSAntoine Tenart 			memcpy(areq->result, sha384_zero_message_hash,
7949e46eafdSAntoine Tenart 			       SHA384_DIGEST_SIZE);
795b460edb6SAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512)
796b460edb6SAntoine Tenart 			memcpy(areq->result, sha512_zero_message_hash,
797b460edb6SAntoine Tenart 			       SHA512_DIGEST_SIZE);
7980f2bc131SPascal van Leeuwen 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) {
7990f2bc131SPascal van Leeuwen 			memcpy(areq->result,
8000f2bc131SPascal van Leeuwen 			       EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE);
8010f2bc131SPascal van Leeuwen 		}
8021b44c5a6SAntoine Ténart 
8031b44c5a6SAntoine Ténart 		return 0;
804a7cf8658SPascal van Leeuwen 	} else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM &&
805a7cf8658SPascal van Leeuwen 			    ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 &&
806a7cf8658SPascal van Leeuwen 			    req->len == sizeof(u32) && !areq->nbytes)) {
807a7cf8658SPascal van Leeuwen 		/* Zero length CRC32 */
80878cf1c8bSHerbert Xu 		memcpy(areq->result, &ctx->base.ipad, sizeof(u32));
809a7cf8658SPascal van Leeuwen 		return 0;
81038f21b4bSPascal van Leeuwen 	} else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE &&
811b98687bbSPascal van Leeuwen 			    !areq->nbytes)) {
812b98687bbSPascal van Leeuwen 		/* Zero length CBC MAC */
813b98687bbSPascal van Leeuwen 		memset(areq->result, 0, AES_BLOCK_SIZE);
814b98687bbSPascal van Leeuwen 		return 0;
81538f21b4bSPascal van Leeuwen 	} else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE &&
81638f21b4bSPascal van Leeuwen 			    !areq->nbytes)) {
81738f21b4bSPascal van Leeuwen 		/* Zero length (X)CBC/CMAC */
81838f21b4bSPascal van Leeuwen 		int i;
81938f21b4bSPascal van Leeuwen 
82078cf1c8bSHerbert Xu 		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) {
82178cf1c8bSHerbert Xu 			u32 *result = (void *)areq->result;
82278cf1c8bSHerbert Xu 
82378cf1c8bSHerbert Xu 			/* K3 */
82466459340SPeter Harliman Liem 			result[i] = swab32(ctx->base.ipad.word[i + 4]);
82578cf1c8bSHerbert Xu 		}
82638f21b4bSPascal van Leeuwen 		areq->result[0] ^= 0x80;			// 10- padding
827*320406cbSPeter Harliman Liem 		aes_encrypt(ctx->aes, areq->result, areq->result);
82838f21b4bSPascal van Leeuwen 		return 0;
82931fb084cSPascal van Leeuwen 	} else if (unlikely(req->hmac &&
83031fb084cSPascal van Leeuwen 			    (req->len == req->block_sz) &&
83141abed7dSPascal van Leeuwen 			    !areq->nbytes)) {
83285b36ee8SPascal van Leeuwen 		/*
83385b36ee8SPascal van Leeuwen 		 * If we have an overall 0 length *HMAC* request:
83485b36ee8SPascal van Leeuwen 		 * For HMAC, we need to finalize the inner digest
83585b36ee8SPascal van Leeuwen 		 * and then perform the outer hash.
83685b36ee8SPascal van Leeuwen 		 */
83785b36ee8SPascal van Leeuwen 
83885b36ee8SPascal van Leeuwen 		/* generate pad block in the cache */
83985b36ee8SPascal van Leeuwen 		/* start with a hash block of all zeroes */
84085b36ee8SPascal van Leeuwen 		memset(req->cache, 0, req->block_sz);
84185b36ee8SPascal van Leeuwen 		/* set the first byte to 0x80 to 'append a 1 bit' */
84285b36ee8SPascal van Leeuwen 		req->cache[0] = 0x80;
84385b36ee8SPascal van Leeuwen 		/* add the length in bits in the last 2 bytes */
84485b36ee8SPascal van Leeuwen 		if (req->len_is_le) {
84585b36ee8SPascal van Leeuwen 			/* Little endian length word (e.g. MD5) */
84685b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-8] = (req->block_sz << 3) &
84785b36ee8SPascal van Leeuwen 						      255;
84885b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-7] = (req->block_sz >> 5);
84985b36ee8SPascal van Leeuwen 		} else {
85085b36ee8SPascal van Leeuwen 			/* Big endian length word (e.g. any SHA) */
85185b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-2] = (req->block_sz >> 5);
85285b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-1] = (req->block_sz << 3) &
85385b36ee8SPascal van Leeuwen 						      255;
85485b36ee8SPascal van Leeuwen 		}
85585b36ee8SPascal van Leeuwen 
85631fb084cSPascal van Leeuwen 		req->len += req->block_sz; /* plus 1 hash block */
85785b36ee8SPascal van Leeuwen 
85885b36ee8SPascal van Leeuwen 		/* Set special zero-length HMAC flag */
85985b36ee8SPascal van Leeuwen 		req->hmac_zlen = true;
86085b36ee8SPascal van Leeuwen 
86185b36ee8SPascal van Leeuwen 		/* Finalize HMAC */
86285b36ee8SPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
86341abed7dSPascal van Leeuwen 	} else if (req->hmac) {
86441abed7dSPascal van Leeuwen 		/* Finalize HMAC */
86541abed7dSPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
8661b44c5a6SAntoine Ténart 	}
8671b44c5a6SAntoine Ténart 
8681b44c5a6SAntoine Ténart 	return safexcel_ahash_enqueue(areq);
8691b44c5a6SAntoine Ténart }
8701b44c5a6SAntoine Ténart 
8711b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq)
8721b44c5a6SAntoine Ténart {
8731b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8741b44c5a6SAntoine Ténart 
8751b44c5a6SAntoine Ténart 	req->finish = true;
8761b44c5a6SAntoine Ténart 
8771b44c5a6SAntoine Ténart 	safexcel_ahash_update(areq);
8781b44c5a6SAntoine Ténart 	return safexcel_ahash_final(areq);
8791b44c5a6SAntoine Ténart }
8801b44c5a6SAntoine Ténart 
8811b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out)
8821b44c5a6SAntoine Ténart {
8831b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8841b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state *export = out;
8851b44c5a6SAntoine Ténart 
88631fb084cSPascal van Leeuwen 	export->len = req->len;
88731fb084cSPascal van Leeuwen 	export->processed = req->processed;
8881b44c5a6SAntoine Ténart 
889b869648cSAntoine Tenart 	export->digest = req->digest;
890b869648cSAntoine Tenart 
8911b44c5a6SAntoine Ténart 	memcpy(export->state, req->state, req->state_sz);
89241abed7dSPascal van Leeuwen 	memcpy(export->cache, req->cache, HASH_CACHE_SIZE);
8931b44c5a6SAntoine Ténart 
8941b44c5a6SAntoine Ténart 	return 0;
8951b44c5a6SAntoine Ténart }
8961b44c5a6SAntoine Ténart 
8971b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in)
8981b44c5a6SAntoine Ténart {
8991b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
9001b44c5a6SAntoine Ténart 	const struct safexcel_ahash_export_state *export = in;
9011b44c5a6SAntoine Ténart 	int ret;
9021b44c5a6SAntoine Ténart 
9031b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
9041b44c5a6SAntoine Ténart 	if (ret)
9051b44c5a6SAntoine Ténart 		return ret;
9061b44c5a6SAntoine Ténart 
90731fb084cSPascal van Leeuwen 	req->len = export->len;
90831fb084cSPascal van Leeuwen 	req->processed = export->processed;
9091b44c5a6SAntoine Ténart 
910b869648cSAntoine Tenart 	req->digest = export->digest;
911b869648cSAntoine Tenart 
91241abed7dSPascal van Leeuwen 	memcpy(req->cache, export->cache, HASH_CACHE_SIZE);
9131b44c5a6SAntoine Ténart 	memcpy(req->state, export->state, req->state_sz);
9141b44c5a6SAntoine Ténart 
9151b44c5a6SAntoine Ténart 	return 0;
9161b44c5a6SAntoine Ténart }
9171b44c5a6SAntoine Ténart 
9181b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm)
9191b44c5a6SAntoine Ténart {
9201b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
9211b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
9221b44c5a6SAntoine Ténart 		container_of(__crypto_ahash_alg(tfm->__crt_alg),
9231b44c5a6SAntoine Ténart 			     struct safexcel_alg_template, alg.ahash);
9241b44c5a6SAntoine Ténart 
92518e51895SHerbert Xu 	ctx->base.priv = tmpl->priv;
9261eb7b403SOfer Heifetz 	ctx->base.send = safexcel_ahash_send;
9271eb7b403SOfer Heifetz 	ctx->base.handle_result = safexcel_handle_result;
9286c1c09b3SPascal van Leeuwen 	ctx->fb_do_setkey = false;
9291b44c5a6SAntoine Ténart 
9301b44c5a6SAntoine Ténart 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
9311b44c5a6SAntoine Ténart 				 sizeof(struct safexcel_ahash_req));
9321b44c5a6SAntoine Ténart 	return 0;
9331b44c5a6SAntoine Ténart }
9341b44c5a6SAntoine Ténart 
9351b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq)
9361b44c5a6SAntoine Ténart {
9371b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
9381b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
9391b44c5a6SAntoine Ténart 
9401b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
9411b44c5a6SAntoine Ténart 
9421b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
943b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
9441b44c5a6SAntoine Ténart 	req->state_sz = SHA1_DIGEST_SIZE;
9456c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA1_DIGEST_SIZE;
94641abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
9471b44c5a6SAntoine Ténart 
9481b44c5a6SAntoine Ténart 	return 0;
9491b44c5a6SAntoine Ténart }
9501b44c5a6SAntoine Ténart 
9511b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq)
9521b44c5a6SAntoine Ténart {
9531b44c5a6SAntoine Ténart 	int ret = safexcel_sha1_init(areq);
9541b44c5a6SAntoine Ténart 
9551b44c5a6SAntoine Ténart 	if (ret)
9561b44c5a6SAntoine Ténart 		return ret;
9571b44c5a6SAntoine Ténart 
9581b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
9591b44c5a6SAntoine Ténart }
9601b44c5a6SAntoine Ténart 
9611b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm)
9621b44c5a6SAntoine Ténart {
9631b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
96418e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
9651b44c5a6SAntoine Ténart 	int ret;
9661b44c5a6SAntoine Ténart 
9671b44c5a6SAntoine Ténart 	/* context not allocated, skip invalidation */
9681b44c5a6SAntoine Ténart 	if (!ctx->base.ctxr)
9691b44c5a6SAntoine Ténart 		return;
9701b44c5a6SAntoine Ténart 
97153c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
9721b44c5a6SAntoine Ténart 		ret = safexcel_ahash_exit_inv(tfm);
9731b44c5a6SAntoine Ténart 		if (ret)
9741b44c5a6SAntoine Ténart 			dev_warn(priv->dev, "hash: invalidation error %d\n", ret);
975871df319SAntoine Ténart 	} else {
976871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
977871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
978871df319SAntoine Ténart 	}
9791b44c5a6SAntoine Ténart }
9801b44c5a6SAntoine Ténart 
9811b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = {
9821b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
983062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
9841b44c5a6SAntoine Ténart 	.alg.ahash = {
9851b44c5a6SAntoine Ténart 		.init = safexcel_sha1_init,
9861b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
9871b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
9881b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
9891b44c5a6SAntoine Ténart 		.digest = safexcel_sha1_digest,
9901b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
9911b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
9921b44c5a6SAntoine Ténart 		.halg = {
9931b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
9941b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
9951b44c5a6SAntoine Ténart 			.base = {
9961b44c5a6SAntoine Ténart 				.cra_name = "sha1",
9971b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha1",
998aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
9991b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1000b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
10011b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
10021b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
10031b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
10041b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
10051b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
10061b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
10071b44c5a6SAntoine Ténart 			},
10081b44c5a6SAntoine Ténart 		},
10091b44c5a6SAntoine Ténart 	},
10101b44c5a6SAntoine Ténart };
10111b44c5a6SAntoine Ténart 
10121b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq)
10131b44c5a6SAntoine Ténart {
101441abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1015b869648cSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
10161b44c5a6SAntoine Ténart 
101741abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
101841abed7dSPascal van Leeuwen 
101941abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
102078cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA1_DIGEST_SIZE);
102141abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
102231fb084cSPascal van Leeuwen 	req->len	= SHA1_BLOCK_SIZE;
102331fb084cSPascal van Leeuwen 	req->processed	= SHA1_BLOCK_SIZE;
102441abed7dSPascal van Leeuwen 
102541abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
102641abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
102741abed7dSPascal van Leeuwen 	req->state_sz = SHA1_DIGEST_SIZE;
10286c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA1_DIGEST_SIZE;
102941abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
103041abed7dSPascal van Leeuwen 	req->hmac = true;
103141abed7dSPascal van Leeuwen 
10321b44c5a6SAntoine Ténart 	return 0;
10331b44c5a6SAntoine Ténart }
10341b44c5a6SAntoine Ténart 
10351b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq)
10361b44c5a6SAntoine Ténart {
10371b44c5a6SAntoine Ténart 	int ret = safexcel_hmac_sha1_init(areq);
10381b44c5a6SAntoine Ténart 
10391b44c5a6SAntoine Ténart 	if (ret)
10401b44c5a6SAntoine Ténart 		return ret;
10411b44c5a6SAntoine Ténart 
10421b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
10431b44c5a6SAntoine Ténart }
10441b44c5a6SAntoine Ténart 
10451b44c5a6SAntoine Ténart struct safexcel_ahash_result {
10461b44c5a6SAntoine Ténart 	struct completion completion;
10471b44c5a6SAntoine Ténart 	int error;
10481b44c5a6SAntoine Ténart };
10491b44c5a6SAntoine Ténart 
10501b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error)
10511b44c5a6SAntoine Ténart {
10521b44c5a6SAntoine Ténart 	struct safexcel_ahash_result *result = req->data;
10531b44c5a6SAntoine Ténart 
10541b44c5a6SAntoine Ténart 	if (error == -EINPROGRESS)
10551b44c5a6SAntoine Ténart 		return;
10561b44c5a6SAntoine Ténart 
10571b44c5a6SAntoine Ténart 	result->error = error;
10581b44c5a6SAntoine Ténart 	complete(&result->completion);
10591b44c5a6SAntoine Ténart }
10601b44c5a6SAntoine Ténart 
10611b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq,
10621b44c5a6SAntoine Ténart 				  unsigned int blocksize, const u8 *key,
10631b44c5a6SAntoine Ténart 				  unsigned int keylen, u8 *ipad, u8 *opad)
10641b44c5a6SAntoine Ténart {
10651b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
10661b44c5a6SAntoine Ténart 	struct scatterlist sg;
10671b44c5a6SAntoine Ténart 	int ret, i;
10681b44c5a6SAntoine Ténart 	u8 *keydup;
10691b44c5a6SAntoine Ténart 
10701b44c5a6SAntoine Ténart 	if (keylen <= blocksize) {
10711b44c5a6SAntoine Ténart 		memcpy(ipad, key, keylen);
10721b44c5a6SAntoine Ténart 	} else {
10731b44c5a6SAntoine Ténart 		keydup = kmemdup(key, keylen, GFP_KERNEL);
10741b44c5a6SAntoine Ténart 		if (!keydup)
10751b44c5a6SAntoine Ténart 			return -ENOMEM;
10761b44c5a6SAntoine Ténart 
10771b44c5a6SAntoine Ténart 		ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
10781b44c5a6SAntoine Ténart 					   safexcel_ahash_complete, &result);
10791b44c5a6SAntoine Ténart 		sg_init_one(&sg, keydup, keylen);
10801b44c5a6SAntoine Ténart 		ahash_request_set_crypt(areq, &sg, ipad, keylen);
10811b44c5a6SAntoine Ténart 		init_completion(&result.completion);
10821b44c5a6SAntoine Ténart 
10831b44c5a6SAntoine Ténart 		ret = crypto_ahash_digest(areq);
10844dc5475aSAntoine Tenart 		if (ret == -EINPROGRESS || ret == -EBUSY) {
10851b44c5a6SAntoine Ténart 			wait_for_completion_interruptible(&result.completion);
10861b44c5a6SAntoine Ténart 			ret = result.error;
10871b44c5a6SAntoine Ténart 		}
10881b44c5a6SAntoine Ténart 
10891b44c5a6SAntoine Ténart 		/* Avoid leaking */
109057059185SDenis Efremov 		kfree_sensitive(keydup);
10911b44c5a6SAntoine Ténart 
10921b44c5a6SAntoine Ténart 		if (ret)
10931b44c5a6SAntoine Ténart 			return ret;
10941b44c5a6SAntoine Ténart 
10951b44c5a6SAntoine Ténart 		keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq));
10961b44c5a6SAntoine Ténart 	}
10971b44c5a6SAntoine Ténart 
10981b44c5a6SAntoine Ténart 	memset(ipad + keylen, 0, blocksize - keylen);
10991b44c5a6SAntoine Ténart 	memcpy(opad, ipad, blocksize);
11001b44c5a6SAntoine Ténart 
11011b44c5a6SAntoine Ténart 	for (i = 0; i < blocksize; i++) {
1102aed3731eSAntoine Ténart 		ipad[i] ^= HMAC_IPAD_VALUE;
1103aed3731eSAntoine Ténart 		opad[i] ^= HMAC_OPAD_VALUE;
11041b44c5a6SAntoine Ténart 	}
11051b44c5a6SAntoine Ténart 
11061b44c5a6SAntoine Ténart 	return 0;
11071b44c5a6SAntoine Ténart }
11081b44c5a6SAntoine Ténart 
11091b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq,
11101b44c5a6SAntoine Ténart 				 unsigned int blocksize, u8 *pad, void *state)
11111b44c5a6SAntoine Ténart {
11121b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
11131b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req;
11141b44c5a6SAntoine Ténart 	struct scatterlist sg;
11151b44c5a6SAntoine Ténart 	int ret;
11161b44c5a6SAntoine Ténart 
11171b44c5a6SAntoine Ténart 	ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
11181b44c5a6SAntoine Ténart 				   safexcel_ahash_complete, &result);
11191b44c5a6SAntoine Ténart 	sg_init_one(&sg, pad, blocksize);
11201b44c5a6SAntoine Ténart 	ahash_request_set_crypt(areq, &sg, pad, blocksize);
11211b44c5a6SAntoine Ténart 	init_completion(&result.completion);
11221b44c5a6SAntoine Ténart 
11231b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
11241b44c5a6SAntoine Ténart 	if (ret)
11251b44c5a6SAntoine Ténart 		return ret;
11261b44c5a6SAntoine Ténart 
11271b44c5a6SAntoine Ténart 	req = ahash_request_ctx(areq);
11281b44c5a6SAntoine Ténart 	req->hmac = true;
11291b44c5a6SAntoine Ténart 	req->last_req = true;
11301b44c5a6SAntoine Ténart 
11311b44c5a6SAntoine Ténart 	ret = crypto_ahash_update(areq);
113212bf4142SOfer Heifetz 	if (ret && ret != -EINPROGRESS && ret != -EBUSY)
11331b44c5a6SAntoine Ténart 		return ret;
11341b44c5a6SAntoine Ténart 
11351b44c5a6SAntoine Ténart 	wait_for_completion_interruptible(&result.completion);
11361b44c5a6SAntoine Ténart 	if (result.error)
11371b44c5a6SAntoine Ténart 		return result.error;
11381b44c5a6SAntoine Ténart 
11391b44c5a6SAntoine Ténart 	return crypto_ahash_export(areq, state);
11401b44c5a6SAntoine Ténart }
11411b44c5a6SAntoine Ténart 
114263cdd870SHerbert Xu static int __safexcel_hmac_setkey(const char *alg, const u8 *key,
114363cdd870SHerbert Xu 				  unsigned int keylen,
1144f6beaea3SAntoine Tenart 				  void *istate, void *ostate)
11451b44c5a6SAntoine Ténart {
11461b44c5a6SAntoine Ténart 	struct ahash_request *areq;
11471b44c5a6SAntoine Ténart 	struct crypto_ahash *tfm;
11481b44c5a6SAntoine Ténart 	unsigned int blocksize;
11491b44c5a6SAntoine Ténart 	u8 *ipad, *opad;
11501b44c5a6SAntoine Ténart 	int ret;
11511b44c5a6SAntoine Ténart 
115285d7311fSEric Biggers 	tfm = crypto_alloc_ahash(alg, 0, 0);
11531b44c5a6SAntoine Ténart 	if (IS_ERR(tfm))
11541b44c5a6SAntoine Ténart 		return PTR_ERR(tfm);
11551b44c5a6SAntoine Ténart 
11561b44c5a6SAntoine Ténart 	areq = ahash_request_alloc(tfm, GFP_KERNEL);
11571b44c5a6SAntoine Ténart 	if (!areq) {
11581b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11591b44c5a6SAntoine Ténart 		goto free_ahash;
11601b44c5a6SAntoine Ténart 	}
11611b44c5a6SAntoine Ténart 
11621b44c5a6SAntoine Ténart 	crypto_ahash_clear_flags(tfm, ~0);
11631b44c5a6SAntoine Ténart 	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
11641b44c5a6SAntoine Ténart 
11656396bb22SKees Cook 	ipad = kcalloc(2, blocksize, GFP_KERNEL);
11661b44c5a6SAntoine Ténart 	if (!ipad) {
11671b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11681b44c5a6SAntoine Ténart 		goto free_request;
11691b44c5a6SAntoine Ténart 	}
11701b44c5a6SAntoine Ténart 
11711b44c5a6SAntoine Ténart 	opad = ipad + blocksize;
11721b44c5a6SAntoine Ténart 
11731b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad);
11741b44c5a6SAntoine Ténart 	if (ret)
11751b44c5a6SAntoine Ténart 		goto free_ipad;
11761b44c5a6SAntoine Ténart 
11771b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate);
11781b44c5a6SAntoine Ténart 	if (ret)
11791b44c5a6SAntoine Ténart 		goto free_ipad;
11801b44c5a6SAntoine Ténart 
11811b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate);
11821b44c5a6SAntoine Ténart 
11831b44c5a6SAntoine Ténart free_ipad:
11841b44c5a6SAntoine Ténart 	kfree(ipad);
11851b44c5a6SAntoine Ténart free_request:
11861b44c5a6SAntoine Ténart 	ahash_request_free(areq);
11871b44c5a6SAntoine Ténart free_ahash:
11881b44c5a6SAntoine Ténart 	crypto_free_ahash(tfm);
11891b44c5a6SAntoine Ténart 
11901b44c5a6SAntoine Ténart 	return ret;
11911b44c5a6SAntoine Ténart }
11921b44c5a6SAntoine Ténart 
119363cdd870SHerbert Xu int safexcel_hmac_setkey(struct safexcel_context *base, const u8 *key,
119463cdd870SHerbert Xu 			 unsigned int keylen, const char *alg,
119563cdd870SHerbert Xu 			 unsigned int state_sz)
119663cdd870SHerbert Xu {
119763cdd870SHerbert Xu 	struct safexcel_crypto_priv *priv = base->priv;
119863cdd870SHerbert Xu 	struct safexcel_ahash_export_state istate, ostate;
119963cdd870SHerbert Xu 	int ret;
120063cdd870SHerbert Xu 
120163cdd870SHerbert Xu 	ret = __safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate);
120263cdd870SHerbert Xu 	if (ret)
120363cdd870SHerbert Xu 		return ret;
120463cdd870SHerbert Xu 
120563cdd870SHerbert Xu 	if (priv->flags & EIP197_TRC_CACHE && base->ctxr &&
120663cdd870SHerbert Xu 	    (memcmp(&base->ipad, istate.state, state_sz) ||
120763cdd870SHerbert Xu 	     memcmp(&base->opad, ostate.state, state_sz)))
120863cdd870SHerbert Xu 		base->needs_inv = true;
120963cdd870SHerbert Xu 
121063cdd870SHerbert Xu 	memcpy(&base->ipad, &istate.state, state_sz);
121163cdd870SHerbert Xu 	memcpy(&base->opad, &ostate.state, state_sz);
121263cdd870SHerbert Xu 
121363cdd870SHerbert Xu 	return 0;
121463cdd870SHerbert Xu }
121563cdd870SHerbert Xu 
121673f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key,
121773f36ea7SAntoine Tenart 				    unsigned int keylen, const char *alg,
121873f36ea7SAntoine Tenart 				    unsigned int state_sz)
12191b44c5a6SAntoine Ténart {
122063cdd870SHerbert Xu 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
12211b44c5a6SAntoine Ténart 
122263cdd870SHerbert Xu 	return safexcel_hmac_setkey(&ctx->base, key, keylen, alg, state_sz);
12231b44c5a6SAntoine Ténart }
12241b44c5a6SAntoine Ténart 
122573f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
122673f36ea7SAntoine Tenart 				     unsigned int keylen)
122773f36ea7SAntoine Tenart {
122873f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1",
122973f36ea7SAntoine Tenart 					SHA1_DIGEST_SIZE);
123073f36ea7SAntoine Tenart }
123173f36ea7SAntoine Tenart 
12321b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = {
12331b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1234062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
12351b44c5a6SAntoine Ténart 	.alg.ahash = {
12361b44c5a6SAntoine Ténart 		.init = safexcel_hmac_sha1_init,
12371b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12381b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12391b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12401b44c5a6SAntoine Ténart 		.digest = safexcel_hmac_sha1_digest,
12411b44c5a6SAntoine Ténart 		.setkey = safexcel_hmac_sha1_setkey,
12421b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12431b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12441b44c5a6SAntoine Ténart 		.halg = {
12451b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
12461b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12471b44c5a6SAntoine Ténart 			.base = {
12481b44c5a6SAntoine Ténart 				.cra_name = "hmac(sha1)",
12491b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-hmac-sha1",
1250aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12511b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1252b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
12531b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12541b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
12551b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12561b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
12571b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
12581b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
12591b44c5a6SAntoine Ténart 			},
12601b44c5a6SAntoine Ténart 		},
12611b44c5a6SAntoine Ténart 	},
12621b44c5a6SAntoine Ténart };
12631b44c5a6SAntoine Ténart 
12641b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq)
12651b44c5a6SAntoine Ténart {
12661b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
12671b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
12681b44c5a6SAntoine Ténart 
12691b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
12701b44c5a6SAntoine Ténart 
12711b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1272b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
12731b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
12746c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
127541abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
12761b44c5a6SAntoine Ténart 
12771b44c5a6SAntoine Ténart 	return 0;
12781b44c5a6SAntoine Ténart }
12791b44c5a6SAntoine Ténart 
12801b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq)
12811b44c5a6SAntoine Ténart {
12821b44c5a6SAntoine Ténart 	int ret = safexcel_sha256_init(areq);
12831b44c5a6SAntoine Ténart 
12841b44c5a6SAntoine Ténart 	if (ret)
12851b44c5a6SAntoine Ténart 		return ret;
12861b44c5a6SAntoine Ténart 
12871b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
12881b44c5a6SAntoine Ténart }
12891b44c5a6SAntoine Ténart 
12901b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = {
12911b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1292062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
12931b44c5a6SAntoine Ténart 	.alg.ahash = {
12941b44c5a6SAntoine Ténart 		.init = safexcel_sha256_init,
12951b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12961b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12971b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12981b44c5a6SAntoine Ténart 		.digest = safexcel_sha256_digest,
12991b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
13001b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
13011b44c5a6SAntoine Ténart 		.halg = {
13021b44c5a6SAntoine Ténart 			.digestsize = SHA256_DIGEST_SIZE,
13031b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
13041b44c5a6SAntoine Ténart 			.base = {
13051b44c5a6SAntoine Ténart 				.cra_name = "sha256",
13061b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha256",
1307aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
13081b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1309b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
13101b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
13111b44c5a6SAntoine Ténart 				.cra_blocksize = SHA256_BLOCK_SIZE,
13121b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
13131b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
13141b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
13151b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
13161b44c5a6SAntoine Ténart 			},
13171b44c5a6SAntoine Ténart 		},
13181b44c5a6SAntoine Ténart 	},
13191b44c5a6SAntoine Ténart };
13201b44c5a6SAntoine Ténart 
13211b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq)
13221b44c5a6SAntoine Ténart {
13231b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
13241b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
13251b44c5a6SAntoine Ténart 
13261b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
13271b44c5a6SAntoine Ténart 
13281b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1329b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
13301b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
13316c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
133241abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
13331b44c5a6SAntoine Ténart 
13341b44c5a6SAntoine Ténart 	return 0;
13351b44c5a6SAntoine Ténart }
13361b44c5a6SAntoine Ténart 
13371b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq)
13381b44c5a6SAntoine Ténart {
13391b44c5a6SAntoine Ténart 	int ret = safexcel_sha224_init(areq);
13401b44c5a6SAntoine Ténart 
13411b44c5a6SAntoine Ténart 	if (ret)
13421b44c5a6SAntoine Ténart 		return ret;
13431b44c5a6SAntoine Ténart 
13441b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
13451b44c5a6SAntoine Ténart }
13461b44c5a6SAntoine Ténart 
13471b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = {
13481b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1349062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
13501b44c5a6SAntoine Ténart 	.alg.ahash = {
13511b44c5a6SAntoine Ténart 		.init = safexcel_sha224_init,
13521b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
13531b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
13541b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
13551b44c5a6SAntoine Ténart 		.digest = safexcel_sha224_digest,
13561b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
13571b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
13581b44c5a6SAntoine Ténart 		.halg = {
13591b44c5a6SAntoine Ténart 			.digestsize = SHA224_DIGEST_SIZE,
13601b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
13611b44c5a6SAntoine Ténart 			.base = {
13621b44c5a6SAntoine Ténart 				.cra_name = "sha224",
13631b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha224",
1364aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
13651b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1366b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
13671b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
13681b44c5a6SAntoine Ténart 				.cra_blocksize = SHA224_BLOCK_SIZE,
13691b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
13701b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
13711b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
13721b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
13731b44c5a6SAntoine Ténart 			},
13741b44c5a6SAntoine Ténart 		},
13751b44c5a6SAntoine Ténart 	},
13761b44c5a6SAntoine Ténart };
137773f36ea7SAntoine Tenart 
13783ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key,
13793ad618d8SAntoine Tenart 				       unsigned int keylen)
13803ad618d8SAntoine Tenart {
13813ad618d8SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224",
13823ad618d8SAntoine Tenart 					SHA256_DIGEST_SIZE);
13833ad618d8SAntoine Tenart }
13843ad618d8SAntoine Tenart 
13853ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq)
13863ad618d8SAntoine Tenart {
138741abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
13883ad618d8SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
13893ad618d8SAntoine Tenart 
139041abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
139141abed7dSPascal van Leeuwen 
139241abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
139378cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE);
139441abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
139531fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
139631fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
139741abed7dSPascal van Leeuwen 
139841abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
139941abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
140041abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
14016c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
140241abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
140341abed7dSPascal van Leeuwen 	req->hmac = true;
140441abed7dSPascal van Leeuwen 
14053ad618d8SAntoine Tenart 	return 0;
14063ad618d8SAntoine Tenart }
14073ad618d8SAntoine Tenart 
14083ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq)
14093ad618d8SAntoine Tenart {
14103ad618d8SAntoine Tenart 	int ret = safexcel_hmac_sha224_init(areq);
14113ad618d8SAntoine Tenart 
14123ad618d8SAntoine Tenart 	if (ret)
14133ad618d8SAntoine Tenart 		return ret;
14143ad618d8SAntoine Tenart 
14153ad618d8SAntoine Tenart 	return safexcel_ahash_finup(areq);
14163ad618d8SAntoine Tenart }
14173ad618d8SAntoine Tenart 
14183ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = {
14193ad618d8SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1420062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
14213ad618d8SAntoine Tenart 	.alg.ahash = {
14223ad618d8SAntoine Tenart 		.init = safexcel_hmac_sha224_init,
14233ad618d8SAntoine Tenart 		.update = safexcel_ahash_update,
14243ad618d8SAntoine Tenart 		.final = safexcel_ahash_final,
14253ad618d8SAntoine Tenart 		.finup = safexcel_ahash_finup,
14263ad618d8SAntoine Tenart 		.digest = safexcel_hmac_sha224_digest,
14273ad618d8SAntoine Tenart 		.setkey = safexcel_hmac_sha224_setkey,
14283ad618d8SAntoine Tenart 		.export = safexcel_ahash_export,
14293ad618d8SAntoine Tenart 		.import = safexcel_ahash_import,
14303ad618d8SAntoine Tenart 		.halg = {
14313ad618d8SAntoine Tenart 			.digestsize = SHA224_DIGEST_SIZE,
14323ad618d8SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
14333ad618d8SAntoine Tenart 			.base = {
14343ad618d8SAntoine Tenart 				.cra_name = "hmac(sha224)",
14353ad618d8SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha224",
1436aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
14373ad618d8SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1438b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
14393ad618d8SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
14403ad618d8SAntoine Tenart 				.cra_blocksize = SHA224_BLOCK_SIZE,
14413ad618d8SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
14423ad618d8SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
14433ad618d8SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
14443ad618d8SAntoine Tenart 				.cra_module = THIS_MODULE,
14453ad618d8SAntoine Tenart 			},
14463ad618d8SAntoine Tenart 		},
14473ad618d8SAntoine Tenart 	},
14483ad618d8SAntoine Tenart };
14493ad618d8SAntoine Tenart 
145073f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
145173f36ea7SAntoine Tenart 				     unsigned int keylen)
145273f36ea7SAntoine Tenart {
145373f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256",
145473f36ea7SAntoine Tenart 					SHA256_DIGEST_SIZE);
145573f36ea7SAntoine Tenart }
145673f36ea7SAntoine Tenart 
145773f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq)
145873f36ea7SAntoine Tenart {
145941abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
146073f36ea7SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
146173f36ea7SAntoine Tenart 
146241abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
146341abed7dSPascal van Leeuwen 
146441abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
146578cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE);
146641abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
146731fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
146831fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
146941abed7dSPascal van Leeuwen 
147041abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
147141abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
147241abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
14736c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
147441abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
147541abed7dSPascal van Leeuwen 	req->hmac = true;
147641abed7dSPascal van Leeuwen 
147773f36ea7SAntoine Tenart 	return 0;
147873f36ea7SAntoine Tenart }
147973f36ea7SAntoine Tenart 
148073f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq)
148173f36ea7SAntoine Tenart {
148273f36ea7SAntoine Tenart 	int ret = safexcel_hmac_sha256_init(areq);
148373f36ea7SAntoine Tenart 
148473f36ea7SAntoine Tenart 	if (ret)
148573f36ea7SAntoine Tenart 		return ret;
148673f36ea7SAntoine Tenart 
148773f36ea7SAntoine Tenart 	return safexcel_ahash_finup(areq);
148873f36ea7SAntoine Tenart }
148973f36ea7SAntoine Tenart 
149073f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = {
149173f36ea7SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1492062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
149373f36ea7SAntoine Tenart 	.alg.ahash = {
149473f36ea7SAntoine Tenart 		.init = safexcel_hmac_sha256_init,
149573f36ea7SAntoine Tenart 		.update = safexcel_ahash_update,
149673f36ea7SAntoine Tenart 		.final = safexcel_ahash_final,
149773f36ea7SAntoine Tenart 		.finup = safexcel_ahash_finup,
149873f36ea7SAntoine Tenart 		.digest = safexcel_hmac_sha256_digest,
149973f36ea7SAntoine Tenart 		.setkey = safexcel_hmac_sha256_setkey,
150073f36ea7SAntoine Tenart 		.export = safexcel_ahash_export,
150173f36ea7SAntoine Tenart 		.import = safexcel_ahash_import,
150273f36ea7SAntoine Tenart 		.halg = {
150373f36ea7SAntoine Tenart 			.digestsize = SHA256_DIGEST_SIZE,
150473f36ea7SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
150573f36ea7SAntoine Tenart 			.base = {
150673f36ea7SAntoine Tenart 				.cra_name = "hmac(sha256)",
150773f36ea7SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha256",
1508aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
150973f36ea7SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1510b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
151173f36ea7SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
151273f36ea7SAntoine Tenart 				.cra_blocksize = SHA256_BLOCK_SIZE,
151373f36ea7SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
151473f36ea7SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
151573f36ea7SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
151673f36ea7SAntoine Tenart 				.cra_module = THIS_MODULE,
151773f36ea7SAntoine Tenart 			},
151873f36ea7SAntoine Tenart 		},
151973f36ea7SAntoine Tenart 	},
152073f36ea7SAntoine Tenart };
1521b460edb6SAntoine Tenart 
1522b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq)
1523b460edb6SAntoine Tenart {
1524b460edb6SAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1525b460edb6SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1526b460edb6SAntoine Tenart 
1527b460edb6SAntoine Tenart 	memset(req, 0, sizeof(*req));
1528b460edb6SAntoine Tenart 
1529b460edb6SAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
1530b460edb6SAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1531b460edb6SAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
15326c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
153341abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
1534b460edb6SAntoine Tenart 
1535b460edb6SAntoine Tenart 	return 0;
1536b460edb6SAntoine Tenart }
1537b460edb6SAntoine Tenart 
1538b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq)
1539b460edb6SAntoine Tenart {
1540b460edb6SAntoine Tenart 	int ret = safexcel_sha512_init(areq);
1541b460edb6SAntoine Tenart 
1542b460edb6SAntoine Tenart 	if (ret)
1543b460edb6SAntoine Tenart 		return ret;
1544b460edb6SAntoine Tenart 
1545b460edb6SAntoine Tenart 	return safexcel_ahash_finup(areq);
1546b460edb6SAntoine Tenart }
1547b460edb6SAntoine Tenart 
1548b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = {
1549b460edb6SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1550062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
1551b460edb6SAntoine Tenart 	.alg.ahash = {
1552b460edb6SAntoine Tenart 		.init = safexcel_sha512_init,
1553b460edb6SAntoine Tenart 		.update = safexcel_ahash_update,
1554b460edb6SAntoine Tenart 		.final = safexcel_ahash_final,
1555b460edb6SAntoine Tenart 		.finup = safexcel_ahash_finup,
1556b460edb6SAntoine Tenart 		.digest = safexcel_sha512_digest,
1557b460edb6SAntoine Tenart 		.export = safexcel_ahash_export,
1558b460edb6SAntoine Tenart 		.import = safexcel_ahash_import,
1559b460edb6SAntoine Tenart 		.halg = {
1560b460edb6SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
1561b460edb6SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
1562b460edb6SAntoine Tenart 			.base = {
1563b460edb6SAntoine Tenart 				.cra_name = "sha512",
1564b460edb6SAntoine Tenart 				.cra_driver_name = "safexcel-sha512",
1565aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1566b460edb6SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1567b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1568b460edb6SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1569b460edb6SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
1570b460edb6SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1571b460edb6SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
1572b460edb6SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
1573b460edb6SAntoine Tenart 				.cra_module = THIS_MODULE,
1574b460edb6SAntoine Tenart 			},
1575b460edb6SAntoine Tenart 		},
1576b460edb6SAntoine Tenart 	},
1577b460edb6SAntoine Tenart };
15780de54fb1SAntoine Tenart 
15799e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq)
15809e46eafdSAntoine Tenart {
15819e46eafdSAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
15829e46eafdSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
15839e46eafdSAntoine Tenart 
15849e46eafdSAntoine Tenart 	memset(req, 0, sizeof(*req));
15859e46eafdSAntoine Tenart 
15869e46eafdSAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
15879e46eafdSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
15889e46eafdSAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
15896c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
159041abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
15919e46eafdSAntoine Tenart 
15929e46eafdSAntoine Tenart 	return 0;
15939e46eafdSAntoine Tenart }
15949e46eafdSAntoine Tenart 
15959e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq)
15969e46eafdSAntoine Tenart {
15979e46eafdSAntoine Tenart 	int ret = safexcel_sha384_init(areq);
15989e46eafdSAntoine Tenart 
15999e46eafdSAntoine Tenart 	if (ret)
16009e46eafdSAntoine Tenart 		return ret;
16019e46eafdSAntoine Tenart 
16029e46eafdSAntoine Tenart 	return safexcel_ahash_finup(areq);
16039e46eafdSAntoine Tenart }
16049e46eafdSAntoine Tenart 
16059e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = {
16069e46eafdSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1607062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
16089e46eafdSAntoine Tenart 	.alg.ahash = {
16099e46eafdSAntoine Tenart 		.init = safexcel_sha384_init,
16109e46eafdSAntoine Tenart 		.update = safexcel_ahash_update,
16119e46eafdSAntoine Tenart 		.final = safexcel_ahash_final,
16129e46eafdSAntoine Tenart 		.finup = safexcel_ahash_finup,
16139e46eafdSAntoine Tenart 		.digest = safexcel_sha384_digest,
16149e46eafdSAntoine Tenart 		.export = safexcel_ahash_export,
16159e46eafdSAntoine Tenart 		.import = safexcel_ahash_import,
16169e46eafdSAntoine Tenart 		.halg = {
16179e46eafdSAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
16189e46eafdSAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
16199e46eafdSAntoine Tenart 			.base = {
16209e46eafdSAntoine Tenart 				.cra_name = "sha384",
16219e46eafdSAntoine Tenart 				.cra_driver_name = "safexcel-sha384",
1622aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
16239e46eafdSAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1624b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
16259e46eafdSAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16269e46eafdSAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
16279e46eafdSAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
16289e46eafdSAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
16299e46eafdSAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
16309e46eafdSAntoine Tenart 				.cra_module = THIS_MODULE,
16319e46eafdSAntoine Tenart 			},
16329e46eafdSAntoine Tenart 		},
16339e46eafdSAntoine Tenart 	},
16349e46eafdSAntoine Tenart };
16359e46eafdSAntoine Tenart 
16360de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key,
16370de54fb1SAntoine Tenart 				       unsigned int keylen)
16380de54fb1SAntoine Tenart {
16390de54fb1SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512",
16400de54fb1SAntoine Tenart 					SHA512_DIGEST_SIZE);
16410de54fb1SAntoine Tenart }
16420de54fb1SAntoine Tenart 
16430de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq)
16440de54fb1SAntoine Tenart {
164541abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
16460de54fb1SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
16470de54fb1SAntoine Tenart 
164841abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
164941abed7dSPascal van Leeuwen 
165041abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
165178cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE);
165241abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
165331fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
165431fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
165541abed7dSPascal van Leeuwen 
165641abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
165741abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
165841abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
16596c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
166041abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
166141abed7dSPascal van Leeuwen 	req->hmac = true;
166241abed7dSPascal van Leeuwen 
16630de54fb1SAntoine Tenart 	return 0;
16640de54fb1SAntoine Tenart }
16650de54fb1SAntoine Tenart 
16660de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq)
16670de54fb1SAntoine Tenart {
16680de54fb1SAntoine Tenart 	int ret = safexcel_hmac_sha512_init(areq);
16690de54fb1SAntoine Tenart 
16700de54fb1SAntoine Tenart 	if (ret)
16710de54fb1SAntoine Tenart 		return ret;
16720de54fb1SAntoine Tenart 
16730de54fb1SAntoine Tenart 	return safexcel_ahash_finup(areq);
16740de54fb1SAntoine Tenart }
16750de54fb1SAntoine Tenart 
16760de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = {
16770de54fb1SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1678062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
16790de54fb1SAntoine Tenart 	.alg.ahash = {
16800de54fb1SAntoine Tenart 		.init = safexcel_hmac_sha512_init,
16810de54fb1SAntoine Tenart 		.update = safexcel_ahash_update,
16820de54fb1SAntoine Tenart 		.final = safexcel_ahash_final,
16830de54fb1SAntoine Tenart 		.finup = safexcel_ahash_finup,
16840de54fb1SAntoine Tenart 		.digest = safexcel_hmac_sha512_digest,
16850de54fb1SAntoine Tenart 		.setkey = safexcel_hmac_sha512_setkey,
16860de54fb1SAntoine Tenart 		.export = safexcel_ahash_export,
16870de54fb1SAntoine Tenart 		.import = safexcel_ahash_import,
16880de54fb1SAntoine Tenart 		.halg = {
16890de54fb1SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
16900de54fb1SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
16910de54fb1SAntoine Tenart 			.base = {
16920de54fb1SAntoine Tenart 				.cra_name = "hmac(sha512)",
16930de54fb1SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha512",
1694aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
16950de54fb1SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1696b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
16970de54fb1SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16980de54fb1SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
16990de54fb1SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
17000de54fb1SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
17010de54fb1SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
17020de54fb1SAntoine Tenart 				.cra_module = THIS_MODULE,
17030de54fb1SAntoine Tenart 			},
17040de54fb1SAntoine Tenart 		},
17050de54fb1SAntoine Tenart 	},
17060de54fb1SAntoine Tenart };
17071f5d5d98SAntoine Tenart 
17081f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key,
17091f5d5d98SAntoine Tenart 				       unsigned int keylen)
17101f5d5d98SAntoine Tenart {
17111f5d5d98SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384",
17121f5d5d98SAntoine Tenart 					SHA512_DIGEST_SIZE);
17131f5d5d98SAntoine Tenart }
17141f5d5d98SAntoine Tenart 
17151f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq)
17161f5d5d98SAntoine Tenart {
171741abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
17181f5d5d98SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
17191f5d5d98SAntoine Tenart 
172041abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
172141abed7dSPascal van Leeuwen 
172241abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
172378cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE);
172441abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
172531fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
172631fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
172741abed7dSPascal van Leeuwen 
172841abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
172941abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
173041abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
17316c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
173241abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
173341abed7dSPascal van Leeuwen 	req->hmac = true;
173441abed7dSPascal van Leeuwen 
17351f5d5d98SAntoine Tenart 	return 0;
17361f5d5d98SAntoine Tenart }
17371f5d5d98SAntoine Tenart 
17381f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq)
17391f5d5d98SAntoine Tenart {
17401f5d5d98SAntoine Tenart 	int ret = safexcel_hmac_sha384_init(areq);
17411f5d5d98SAntoine Tenart 
17421f5d5d98SAntoine Tenart 	if (ret)
17431f5d5d98SAntoine Tenart 		return ret;
17441f5d5d98SAntoine Tenart 
17451f5d5d98SAntoine Tenart 	return safexcel_ahash_finup(areq);
17461f5d5d98SAntoine Tenart }
17471f5d5d98SAntoine Tenart 
17481f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = {
17491f5d5d98SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1750062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
17511f5d5d98SAntoine Tenart 	.alg.ahash = {
17521f5d5d98SAntoine Tenart 		.init = safexcel_hmac_sha384_init,
17531f5d5d98SAntoine Tenart 		.update = safexcel_ahash_update,
17541f5d5d98SAntoine Tenart 		.final = safexcel_ahash_final,
17551f5d5d98SAntoine Tenart 		.finup = safexcel_ahash_finup,
17561f5d5d98SAntoine Tenart 		.digest = safexcel_hmac_sha384_digest,
17571f5d5d98SAntoine Tenart 		.setkey = safexcel_hmac_sha384_setkey,
17581f5d5d98SAntoine Tenart 		.export = safexcel_ahash_export,
17591f5d5d98SAntoine Tenart 		.import = safexcel_ahash_import,
17601f5d5d98SAntoine Tenart 		.halg = {
17611f5d5d98SAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
17621f5d5d98SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
17631f5d5d98SAntoine Tenart 			.base = {
17641f5d5d98SAntoine Tenart 				.cra_name = "hmac(sha384)",
17651f5d5d98SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha384",
1766aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
17671f5d5d98SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1768b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
17691f5d5d98SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
17701f5d5d98SAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
17711f5d5d98SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
17721f5d5d98SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
17731f5d5d98SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
17741f5d5d98SAntoine Tenart 				.cra_module = THIS_MODULE,
17751f5d5d98SAntoine Tenart 			},
17761f5d5d98SAntoine Tenart 		},
17771f5d5d98SAntoine Tenart 	},
17781f5d5d98SAntoine Tenart };
1779293f89cfSOfer Heifetz 
1780293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq)
1781293f89cfSOfer Heifetz {
1782293f89cfSOfer Heifetz 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1783293f89cfSOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1784293f89cfSOfer Heifetz 
1785293f89cfSOfer Heifetz 	memset(req, 0, sizeof(*req));
1786293f89cfSOfer Heifetz 
1787293f89cfSOfer Heifetz 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
1788293f89cfSOfer Heifetz 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1789293f89cfSOfer Heifetz 	req->state_sz = MD5_DIGEST_SIZE;
17906c1c09b3SPascal van Leeuwen 	req->digest_sz = MD5_DIGEST_SIZE;
179141abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
1792293f89cfSOfer Heifetz 
1793293f89cfSOfer Heifetz 	return 0;
1794293f89cfSOfer Heifetz }
1795293f89cfSOfer Heifetz 
1796293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq)
1797293f89cfSOfer Heifetz {
1798293f89cfSOfer Heifetz 	int ret = safexcel_md5_init(areq);
1799293f89cfSOfer Heifetz 
1800293f89cfSOfer Heifetz 	if (ret)
1801293f89cfSOfer Heifetz 		return ret;
1802293f89cfSOfer Heifetz 
1803293f89cfSOfer Heifetz 	return safexcel_ahash_finup(areq);
1804293f89cfSOfer Heifetz }
1805293f89cfSOfer Heifetz 
1806293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = {
1807293f89cfSOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1808062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1809293f89cfSOfer Heifetz 	.alg.ahash = {
1810293f89cfSOfer Heifetz 		.init = safexcel_md5_init,
1811293f89cfSOfer Heifetz 		.update = safexcel_ahash_update,
1812293f89cfSOfer Heifetz 		.final = safexcel_ahash_final,
1813293f89cfSOfer Heifetz 		.finup = safexcel_ahash_finup,
1814293f89cfSOfer Heifetz 		.digest = safexcel_md5_digest,
1815293f89cfSOfer Heifetz 		.export = safexcel_ahash_export,
1816293f89cfSOfer Heifetz 		.import = safexcel_ahash_import,
1817293f89cfSOfer Heifetz 		.halg = {
1818293f89cfSOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1819293f89cfSOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1820293f89cfSOfer Heifetz 			.base = {
1821293f89cfSOfer Heifetz 				.cra_name = "md5",
1822293f89cfSOfer Heifetz 				.cra_driver_name = "safexcel-md5",
1823aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1824293f89cfSOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1825b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1826293f89cfSOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1827293f89cfSOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1828293f89cfSOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1829293f89cfSOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1830293f89cfSOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1831293f89cfSOfer Heifetz 				.cra_module = THIS_MODULE,
1832293f89cfSOfer Heifetz 			},
1833293f89cfSOfer Heifetz 		},
1834293f89cfSOfer Heifetz 	},
1835293f89cfSOfer Heifetz };
1836b471e4b9SOfer Heifetz 
1837b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq)
1838b471e4b9SOfer Heifetz {
183941abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1840b471e4b9SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1841b471e4b9SOfer Heifetz 
184241abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
184341abed7dSPascal van Leeuwen 
184441abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
184578cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, MD5_DIGEST_SIZE);
184641abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
184731fb084cSPascal van Leeuwen 	req->len	= MD5_HMAC_BLOCK_SIZE;
184831fb084cSPascal van Leeuwen 	req->processed	= MD5_HMAC_BLOCK_SIZE;
184941abed7dSPascal van Leeuwen 
185041abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
185141abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
185241abed7dSPascal van Leeuwen 	req->state_sz = MD5_DIGEST_SIZE;
18536c1c09b3SPascal van Leeuwen 	req->digest_sz = MD5_DIGEST_SIZE;
185441abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
185585b36ee8SPascal van Leeuwen 	req->len_is_le = true; /* MD5 is little endian! ... */
185641abed7dSPascal van Leeuwen 	req->hmac = true;
185741abed7dSPascal van Leeuwen 
1858b471e4b9SOfer Heifetz 	return 0;
1859b471e4b9SOfer Heifetz }
1860b471e4b9SOfer Heifetz 
1861b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key,
1862b471e4b9SOfer Heifetz 				     unsigned int keylen)
1863b471e4b9SOfer Heifetz {
1864b471e4b9SOfer Heifetz 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5",
1865b471e4b9SOfer Heifetz 					MD5_DIGEST_SIZE);
1866b471e4b9SOfer Heifetz }
1867b471e4b9SOfer Heifetz 
1868b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq)
1869b471e4b9SOfer Heifetz {
1870b471e4b9SOfer Heifetz 	int ret = safexcel_hmac_md5_init(areq);
1871b471e4b9SOfer Heifetz 
1872b471e4b9SOfer Heifetz 	if (ret)
1873b471e4b9SOfer Heifetz 		return ret;
1874b471e4b9SOfer Heifetz 
1875b471e4b9SOfer Heifetz 	return safexcel_ahash_finup(areq);
1876b471e4b9SOfer Heifetz }
1877b471e4b9SOfer Heifetz 
1878b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = {
1879b471e4b9SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1880062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1881b471e4b9SOfer Heifetz 	.alg.ahash = {
1882b471e4b9SOfer Heifetz 		.init = safexcel_hmac_md5_init,
1883b471e4b9SOfer Heifetz 		.update = safexcel_ahash_update,
1884b471e4b9SOfer Heifetz 		.final = safexcel_ahash_final,
1885b471e4b9SOfer Heifetz 		.finup = safexcel_ahash_finup,
1886b471e4b9SOfer Heifetz 		.digest = safexcel_hmac_md5_digest,
1887b471e4b9SOfer Heifetz 		.setkey = safexcel_hmac_md5_setkey,
1888b471e4b9SOfer Heifetz 		.export = safexcel_ahash_export,
1889b471e4b9SOfer Heifetz 		.import = safexcel_ahash_import,
1890b471e4b9SOfer Heifetz 		.halg = {
1891b471e4b9SOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1892b471e4b9SOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1893b471e4b9SOfer Heifetz 			.base = {
1894b471e4b9SOfer Heifetz 				.cra_name = "hmac(md5)",
1895b471e4b9SOfer Heifetz 				.cra_driver_name = "safexcel-hmac-md5",
1896aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1897b471e4b9SOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1898b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1899b471e4b9SOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1900b471e4b9SOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1901b471e4b9SOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1902b471e4b9SOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1903b471e4b9SOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1904b471e4b9SOfer Heifetz 				.cra_module = THIS_MODULE,
1905b471e4b9SOfer Heifetz 			},
1906b471e4b9SOfer Heifetz 		},
1907b471e4b9SOfer Heifetz 	},
1908b471e4b9SOfer Heifetz };
1909a7cf8658SPascal van Leeuwen 
1910a7cf8658SPascal van Leeuwen static int safexcel_crc32_cra_init(struct crypto_tfm *tfm)
1911a7cf8658SPascal van Leeuwen {
1912a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
1913a7cf8658SPascal van Leeuwen 	int ret = safexcel_ahash_cra_init(tfm);
1914a7cf8658SPascal van Leeuwen 
1915a7cf8658SPascal van Leeuwen 	/* Default 'key' is all zeroes */
191678cf1c8bSHerbert Xu 	memset(&ctx->base.ipad, 0, sizeof(u32));
1917a7cf8658SPascal van Leeuwen 	return ret;
1918a7cf8658SPascal van Leeuwen }
1919a7cf8658SPascal van Leeuwen 
1920a7cf8658SPascal van Leeuwen static int safexcel_crc32_init(struct ahash_request *areq)
1921a7cf8658SPascal van Leeuwen {
1922a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1923a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1924a7cf8658SPascal van Leeuwen 
1925a7cf8658SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1926a7cf8658SPascal van Leeuwen 
1927a7cf8658SPascal van Leeuwen 	/* Start from loaded key */
192878cf1c8bSHerbert Xu 	req->state[0]	= cpu_to_le32(~ctx->base.ipad.word[0]);
1929a7cf8658SPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
1930a7cf8658SPascal van Leeuwen 	req->len	= sizeof(u32);
1931a7cf8658SPascal van Leeuwen 	req->processed	= sizeof(u32);
1932a7cf8658SPascal van Leeuwen 
1933a7cf8658SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32;
1934a7cf8658SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_XCM;
1935a7cf8658SPascal van Leeuwen 	req->state_sz = sizeof(u32);
19366c1c09b3SPascal van Leeuwen 	req->digest_sz = sizeof(u32);
1937a7cf8658SPascal van Leeuwen 	req->block_sz = sizeof(u32);
1938a7cf8658SPascal van Leeuwen 
1939a7cf8658SPascal van Leeuwen 	return 0;
1940a7cf8658SPascal van Leeuwen }
1941a7cf8658SPascal van Leeuwen 
1942a7cf8658SPascal van Leeuwen static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key,
1943a7cf8658SPascal van Leeuwen 				 unsigned int keylen)
1944a7cf8658SPascal van Leeuwen {
1945a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1946a7cf8658SPascal van Leeuwen 
1947674f368aSEric Biggers 	if (keylen != sizeof(u32))
1948a7cf8658SPascal van Leeuwen 		return -EINVAL;
1949a7cf8658SPascal van Leeuwen 
195078cf1c8bSHerbert Xu 	memcpy(&ctx->base.ipad, key, sizeof(u32));
1951a7cf8658SPascal van Leeuwen 	return 0;
1952a7cf8658SPascal van Leeuwen }
1953a7cf8658SPascal van Leeuwen 
1954a7cf8658SPascal van Leeuwen static int safexcel_crc32_digest(struct ahash_request *areq)
1955a7cf8658SPascal van Leeuwen {
1956a7cf8658SPascal van Leeuwen 	return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq);
1957a7cf8658SPascal van Leeuwen }
1958a7cf8658SPascal van Leeuwen 
1959a7cf8658SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_crc32 = {
1960a7cf8658SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1961a7cf8658SPascal van Leeuwen 	.algo_mask = 0,
1962a7cf8658SPascal van Leeuwen 	.alg.ahash = {
1963a7cf8658SPascal van Leeuwen 		.init = safexcel_crc32_init,
1964a7cf8658SPascal van Leeuwen 		.update = safexcel_ahash_update,
1965a7cf8658SPascal van Leeuwen 		.final = safexcel_ahash_final,
1966a7cf8658SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
1967a7cf8658SPascal van Leeuwen 		.digest = safexcel_crc32_digest,
1968a7cf8658SPascal van Leeuwen 		.setkey = safexcel_crc32_setkey,
1969a7cf8658SPascal van Leeuwen 		.export = safexcel_ahash_export,
1970a7cf8658SPascal van Leeuwen 		.import = safexcel_ahash_import,
1971a7cf8658SPascal van Leeuwen 		.halg = {
1972a7cf8658SPascal van Leeuwen 			.digestsize = sizeof(u32),
1973a7cf8658SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
1974a7cf8658SPascal van Leeuwen 			.base = {
1975a7cf8658SPascal van Leeuwen 				.cra_name = "crc32",
1976a7cf8658SPascal van Leeuwen 				.cra_driver_name = "safexcel-crc32",
1977a7cf8658SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1978a7cf8658SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_OPTIONAL_KEY |
1979a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_ASYNC |
1980b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1981a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1982a7cf8658SPascal van Leeuwen 				.cra_blocksize = 1,
1983a7cf8658SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1984a7cf8658SPascal van Leeuwen 				.cra_init = safexcel_crc32_cra_init,
1985a7cf8658SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
1986a7cf8658SPascal van Leeuwen 				.cra_module = THIS_MODULE,
1987a7cf8658SPascal van Leeuwen 			},
1988a7cf8658SPascal van Leeuwen 		},
1989a7cf8658SPascal van Leeuwen 	},
1990a7cf8658SPascal van Leeuwen };
1991b98687bbSPascal van Leeuwen 
1992b98687bbSPascal van Leeuwen static int safexcel_cbcmac_init(struct ahash_request *areq)
1993b98687bbSPascal van Leeuwen {
1994b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1995b98687bbSPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1996b98687bbSPascal van Leeuwen 
1997b98687bbSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1998b98687bbSPascal van Leeuwen 
1999b98687bbSPascal van Leeuwen 	/* Start from loaded keys */
200078cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, ctx->key_sz);
2001b98687bbSPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
2002b98687bbSPascal van Leeuwen 	req->len	= AES_BLOCK_SIZE;
2003b98687bbSPascal van Leeuwen 	req->processed	= AES_BLOCK_SIZE;
2004b98687bbSPascal van Leeuwen 
2005b98687bbSPascal van Leeuwen 	req->digest   = CONTEXT_CONTROL_DIGEST_XCM;
2006b98687bbSPascal van Leeuwen 	req->state_sz = ctx->key_sz;
20076c1c09b3SPascal van Leeuwen 	req->digest_sz = AES_BLOCK_SIZE;
2008b98687bbSPascal van Leeuwen 	req->block_sz = AES_BLOCK_SIZE;
2009b98687bbSPascal van Leeuwen 	req->xcbcmac  = true;
2010b98687bbSPascal van Leeuwen 
2011b98687bbSPascal van Leeuwen 	return 0;
2012b98687bbSPascal van Leeuwen }
2013b98687bbSPascal van Leeuwen 
2014b98687bbSPascal van Leeuwen static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
2015b98687bbSPascal van Leeuwen 				 unsigned int len)
2016b98687bbSPascal van Leeuwen {
2017b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
2018b98687bbSPascal van Leeuwen 	struct crypto_aes_ctx aes;
2019b98687bbSPascal van Leeuwen 	int ret, i;
2020b98687bbSPascal van Leeuwen 
2021b98687bbSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
2022674f368aSEric Biggers 	if (ret)
2023b98687bbSPascal van Leeuwen 		return ret;
2024b98687bbSPascal van Leeuwen 
202578cf1c8bSHerbert Xu 	memset(&ctx->base.ipad, 0, 2 * AES_BLOCK_SIZE);
2026b98687bbSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
202778cf1c8bSHerbert Xu 		ctx->base.ipad.be[i + 8] = cpu_to_be32(aes.key_enc[i]);
2028b98687bbSPascal van Leeuwen 
2029b98687bbSPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
2030b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
2031b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2032b98687bbSPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
2033b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
2034b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2035b98687bbSPascal van Leeuwen 	} else {
2036b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
2037b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2038b98687bbSPascal van Leeuwen 	}
203938f21b4bSPascal van Leeuwen 	ctx->cbcmac  = true;
2040b98687bbSPascal van Leeuwen 
2041b98687bbSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
2042b98687bbSPascal van Leeuwen 	return 0;
2043b98687bbSPascal van Leeuwen }
2044b98687bbSPascal van Leeuwen 
2045b98687bbSPascal van Leeuwen static int safexcel_cbcmac_digest(struct ahash_request *areq)
2046b98687bbSPascal van Leeuwen {
2047b98687bbSPascal van Leeuwen 	return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq);
2048b98687bbSPascal van Leeuwen }
2049b98687bbSPascal van Leeuwen 
2050b98687bbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbcmac = {
2051b98687bbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2052b98687bbSPascal van Leeuwen 	.algo_mask = 0,
2053b98687bbSPascal van Leeuwen 	.alg.ahash = {
2054b98687bbSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
2055b98687bbSPascal van Leeuwen 		.update = safexcel_ahash_update,
2056b98687bbSPascal van Leeuwen 		.final = safexcel_ahash_final,
2057b98687bbSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
2058b98687bbSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
2059b98687bbSPascal van Leeuwen 		.setkey = safexcel_cbcmac_setkey,
2060b98687bbSPascal van Leeuwen 		.export = safexcel_ahash_export,
2061b98687bbSPascal van Leeuwen 		.import = safexcel_ahash_import,
2062b98687bbSPascal van Leeuwen 		.halg = {
2063b98687bbSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
2064b98687bbSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2065b98687bbSPascal van Leeuwen 			.base = {
2066b98687bbSPascal van Leeuwen 				.cra_name = "cbcmac(aes)",
2067b98687bbSPascal van Leeuwen 				.cra_driver_name = "safexcel-cbcmac-aes",
2068b98687bbSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2069b98687bbSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2070b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
2071b98687bbSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
2072b98687bbSPascal van Leeuwen 				.cra_blocksize = 1,
2073b98687bbSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2074b98687bbSPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
2075b98687bbSPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
2076b98687bbSPascal van Leeuwen 				.cra_module = THIS_MODULE,
2077b98687bbSPascal van Leeuwen 			},
2078b98687bbSPascal van Leeuwen 		},
2079b98687bbSPascal van Leeuwen 	},
2080b98687bbSPascal van Leeuwen };
208138f21b4bSPascal van Leeuwen 
208238f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
208338f21b4bSPascal van Leeuwen 				 unsigned int len)
208438f21b4bSPascal van Leeuwen {
208538f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
208638f21b4bSPascal van Leeuwen 	u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)];
208738f21b4bSPascal van Leeuwen 	int ret, i;
208838f21b4bSPascal van Leeuwen 
2089*320406cbSPeter Harliman Liem 	ret = aes_expandkey(ctx->aes, key, len);
2090674f368aSEric Biggers 	if (ret)
209138f21b4bSPascal van Leeuwen 		return ret;
209238f21b4bSPascal van Leeuwen 
209338f21b4bSPascal van Leeuwen 	/* precompute the XCBC key material */
2094*320406cbSPeter Harliman Liem 	aes_encrypt(ctx->aes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
209538f21b4bSPascal van Leeuwen 		    "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1");
2096*320406cbSPeter Harliman Liem 	aes_encrypt(ctx->aes, (u8 *)key_tmp,
209738f21b4bSPascal van Leeuwen 		    "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2");
2098*320406cbSPeter Harliman Liem 	aes_encrypt(ctx->aes, (u8 *)key_tmp + AES_BLOCK_SIZE,
209938f21b4bSPascal van Leeuwen 		    "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3");
210038f21b4bSPascal van Leeuwen 	for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++)
210166459340SPeter Harliman Liem 		ctx->base.ipad.word[i] = swab32(key_tmp[i]);
210238f21b4bSPascal van Leeuwen 
2103*320406cbSPeter Harliman Liem 	ret = aes_expandkey(ctx->aes,
210438f21b4bSPascal van Leeuwen 			    (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
210538f21b4bSPascal van Leeuwen 			    AES_MIN_KEY_SIZE);
210638f21b4bSPascal van Leeuwen 	if (ret)
210738f21b4bSPascal van Leeuwen 		return ret;
210838f21b4bSPascal van Leeuwen 
210938f21b4bSPascal van Leeuwen 	ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
211038f21b4bSPascal van Leeuwen 	ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
211138f21b4bSPascal van Leeuwen 	ctx->cbcmac = false;
211238f21b4bSPascal van Leeuwen 
211338f21b4bSPascal van Leeuwen 	return 0;
211438f21b4bSPascal van Leeuwen }
211538f21b4bSPascal van Leeuwen 
211638f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm)
211738f21b4bSPascal van Leeuwen {
211838f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
211938f21b4bSPascal van Leeuwen 
212038f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_init(tfm);
2121*320406cbSPeter Harliman Liem 	ctx->aes = kmalloc(sizeof(*ctx->aes), GFP_KERNEL);
2122*320406cbSPeter Harliman Liem 	return PTR_ERR_OR_ZERO(ctx->aes);
212338f21b4bSPascal van Leeuwen }
212438f21b4bSPascal van Leeuwen 
212538f21b4bSPascal van Leeuwen static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm)
212638f21b4bSPascal van Leeuwen {
212738f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
212838f21b4bSPascal van Leeuwen 
2129*320406cbSPeter Harliman Liem 	kfree(ctx->aes);
213038f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
213138f21b4bSPascal van Leeuwen }
213238f21b4bSPascal van Leeuwen 
213338f21b4bSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xcbcmac = {
213438f21b4bSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
213538f21b4bSPascal van Leeuwen 	.algo_mask = 0,
213638f21b4bSPascal van Leeuwen 	.alg.ahash = {
213738f21b4bSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
213838f21b4bSPascal van Leeuwen 		.update = safexcel_ahash_update,
213938f21b4bSPascal van Leeuwen 		.final = safexcel_ahash_final,
214038f21b4bSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
214138f21b4bSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
214238f21b4bSPascal van Leeuwen 		.setkey = safexcel_xcbcmac_setkey,
214338f21b4bSPascal van Leeuwen 		.export = safexcel_ahash_export,
214438f21b4bSPascal van Leeuwen 		.import = safexcel_ahash_import,
214538f21b4bSPascal van Leeuwen 		.halg = {
214638f21b4bSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
214738f21b4bSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
214838f21b4bSPascal van Leeuwen 			.base = {
214938f21b4bSPascal van Leeuwen 				.cra_name = "xcbc(aes)",
215038f21b4bSPascal van Leeuwen 				.cra_driver_name = "safexcel-xcbc-aes",
215138f21b4bSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
215238f21b4bSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2153b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
215438f21b4bSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
215538f21b4bSPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
215638f21b4bSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
215738f21b4bSPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
215838f21b4bSPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
215938f21b4bSPascal van Leeuwen 				.cra_module = THIS_MODULE,
216038f21b4bSPascal van Leeuwen 			},
216138f21b4bSPascal van Leeuwen 		},
216238f21b4bSPascal van Leeuwen 	},
216338f21b4bSPascal van Leeuwen };
21647a627db9SPascal van Leeuwen 
21657a627db9SPascal van Leeuwen static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
21667a627db9SPascal van Leeuwen 				unsigned int len)
21677a627db9SPascal van Leeuwen {
21687a627db9SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
21697a627db9SPascal van Leeuwen 	__be64 consts[4];
21707a627db9SPascal van Leeuwen 	u64 _const[2];
21717a627db9SPascal van Leeuwen 	u8 msb_mask, gfmask;
21727a627db9SPascal van Leeuwen 	int ret, i;
21737a627db9SPascal van Leeuwen 
2174*320406cbSPeter Harliman Liem 	/* precompute the CMAC key material */
2175*320406cbSPeter Harliman Liem 	ret = aes_expandkey(ctx->aes, key, len);
2176674f368aSEric Biggers 	if (ret)
21777a627db9SPascal van Leeuwen 		return ret;
21787a627db9SPascal van Leeuwen 
21797a627db9SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
2180*320406cbSPeter Harliman Liem 		ctx->base.ipad.word[i + 8] = swab32(ctx->aes->key_enc[i]);
21817a627db9SPascal van Leeuwen 
21827a627db9SPascal van Leeuwen 	/* code below borrowed from crypto/cmac.c */
21837a627db9SPascal van Leeuwen 	/* encrypt the zero block */
21847a627db9SPascal van Leeuwen 	memset(consts, 0, AES_BLOCK_SIZE);
2185*320406cbSPeter Harliman Liem 	aes_encrypt(ctx->aes, (u8 *)consts, (u8 *)consts);
21867a627db9SPascal van Leeuwen 
21877a627db9SPascal van Leeuwen 	gfmask = 0x87;
21887a627db9SPascal van Leeuwen 	_const[0] = be64_to_cpu(consts[1]);
21897a627db9SPascal van Leeuwen 	_const[1] = be64_to_cpu(consts[0]);
21907a627db9SPascal van Leeuwen 
21917a627db9SPascal van Leeuwen 	/* gf(2^128) multiply zero-ciphertext with u and u^2 */
21927a627db9SPascal van Leeuwen 	for (i = 0; i < 4; i += 2) {
21937a627db9SPascal van Leeuwen 		msb_mask = ((s64)_const[1] >> 63) & gfmask;
21947a627db9SPascal van Leeuwen 		_const[1] = (_const[1] << 1) | (_const[0] >> 63);
21957a627db9SPascal van Leeuwen 		_const[0] = (_const[0] << 1) ^ msb_mask;
21967a627db9SPascal van Leeuwen 
21977a627db9SPascal van Leeuwen 		consts[i + 0] = cpu_to_be64(_const[1]);
21987a627db9SPascal van Leeuwen 		consts[i + 1] = cpu_to_be64(_const[0]);
21997a627db9SPascal van Leeuwen 	}
22007a627db9SPascal van Leeuwen 	/* end of code borrowed from crypto/cmac.c */
22017a627db9SPascal van Leeuwen 
22027a627db9SPascal van Leeuwen 	for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++)
220378cf1c8bSHerbert Xu 		ctx->base.ipad.be[i] = cpu_to_be32(((u32 *)consts)[i]);
22047a627db9SPascal van Leeuwen 
22057a627db9SPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
22067a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
22077a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
22087a627db9SPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
22097a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
22107a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
22117a627db9SPascal van Leeuwen 	} else {
22127a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
22137a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
22147a627db9SPascal van Leeuwen 	}
22157a627db9SPascal van Leeuwen 	ctx->cbcmac = false;
22167a627db9SPascal van Leeuwen 
22177a627db9SPascal van Leeuwen 	return 0;
22187a627db9SPascal van Leeuwen }
22197a627db9SPascal van Leeuwen 
22207a627db9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cmac = {
22217a627db9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
22227a627db9SPascal van Leeuwen 	.algo_mask = 0,
22237a627db9SPascal van Leeuwen 	.alg.ahash = {
22247a627db9SPascal van Leeuwen 		.init = safexcel_cbcmac_init,
22257a627db9SPascal van Leeuwen 		.update = safexcel_ahash_update,
22267a627db9SPascal van Leeuwen 		.final = safexcel_ahash_final,
22277a627db9SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22287a627db9SPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
22297a627db9SPascal van Leeuwen 		.setkey = safexcel_cmac_setkey,
22307a627db9SPascal van Leeuwen 		.export = safexcel_ahash_export,
22317a627db9SPascal van Leeuwen 		.import = safexcel_ahash_import,
22327a627db9SPascal van Leeuwen 		.halg = {
22337a627db9SPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
22347a627db9SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
22357a627db9SPascal van Leeuwen 			.base = {
22367a627db9SPascal van Leeuwen 				.cra_name = "cmac(aes)",
22377a627db9SPascal van Leeuwen 				.cra_driver_name = "safexcel-cmac-aes",
22387a627db9SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
22397a627db9SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2240b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
22417a627db9SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
22427a627db9SPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
22437a627db9SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
22447a627db9SPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
22457a627db9SPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
22467a627db9SPascal van Leeuwen 				.cra_module = THIS_MODULE,
22477a627db9SPascal van Leeuwen 			},
22487a627db9SPascal van Leeuwen 		},
22497a627db9SPascal van Leeuwen 	},
22507a627db9SPascal van Leeuwen };
22510f2bc131SPascal van Leeuwen 
22520f2bc131SPascal van Leeuwen static int safexcel_sm3_init(struct ahash_request *areq)
22530f2bc131SPascal van Leeuwen {
22540f2bc131SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
22550f2bc131SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
22560f2bc131SPascal van Leeuwen 
22570f2bc131SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
22580f2bc131SPascal van Leeuwen 
22590f2bc131SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
22600f2bc131SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
22610f2bc131SPascal van Leeuwen 	req->state_sz = SM3_DIGEST_SIZE;
22626c1c09b3SPascal van Leeuwen 	req->digest_sz = SM3_DIGEST_SIZE;
22630f2bc131SPascal van Leeuwen 	req->block_sz = SM3_BLOCK_SIZE;
22640f2bc131SPascal van Leeuwen 
22650f2bc131SPascal van Leeuwen 	return 0;
22660f2bc131SPascal van Leeuwen }
22670f2bc131SPascal van Leeuwen 
22680f2bc131SPascal van Leeuwen static int safexcel_sm3_digest(struct ahash_request *areq)
22690f2bc131SPascal van Leeuwen {
22700f2bc131SPascal van Leeuwen 	int ret = safexcel_sm3_init(areq);
22710f2bc131SPascal van Leeuwen 
22720f2bc131SPascal van Leeuwen 	if (ret)
22730f2bc131SPascal van Leeuwen 		return ret;
22740f2bc131SPascal van Leeuwen 
22750f2bc131SPascal van Leeuwen 	return safexcel_ahash_finup(areq);
22760f2bc131SPascal van Leeuwen }
22770f2bc131SPascal van Leeuwen 
22780f2bc131SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sm3 = {
22790f2bc131SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
22800f2bc131SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM3,
22810f2bc131SPascal van Leeuwen 	.alg.ahash = {
22820f2bc131SPascal van Leeuwen 		.init = safexcel_sm3_init,
22830f2bc131SPascal van Leeuwen 		.update = safexcel_ahash_update,
22840f2bc131SPascal van Leeuwen 		.final = safexcel_ahash_final,
22850f2bc131SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22860f2bc131SPascal van Leeuwen 		.digest = safexcel_sm3_digest,
22870f2bc131SPascal van Leeuwen 		.export = safexcel_ahash_export,
22880f2bc131SPascal van Leeuwen 		.import = safexcel_ahash_import,
22890f2bc131SPascal van Leeuwen 		.halg = {
22900f2bc131SPascal van Leeuwen 			.digestsize = SM3_DIGEST_SIZE,
22910f2bc131SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
22920f2bc131SPascal van Leeuwen 			.base = {
22930f2bc131SPascal van Leeuwen 				.cra_name = "sm3",
22940f2bc131SPascal van Leeuwen 				.cra_driver_name = "safexcel-sm3",
22950f2bc131SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
22960f2bc131SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2297b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
22980f2bc131SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
22990f2bc131SPascal van Leeuwen 				.cra_blocksize = SM3_BLOCK_SIZE,
23000f2bc131SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
23010f2bc131SPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
23020f2bc131SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
23030f2bc131SPascal van Leeuwen 				.cra_module = THIS_MODULE,
23040f2bc131SPascal van Leeuwen 			},
23050f2bc131SPascal van Leeuwen 		},
23060f2bc131SPascal van Leeuwen 	},
23070f2bc131SPascal van Leeuwen };
2308aa3a43e6SPascal van Leeuwen 
2309aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key,
2310aa3a43e6SPascal van Leeuwen 				    unsigned int keylen)
2311aa3a43e6SPascal van Leeuwen {
2312aa3a43e6SPascal van Leeuwen 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3",
2313aa3a43e6SPascal van Leeuwen 					SM3_DIGEST_SIZE);
2314aa3a43e6SPascal van Leeuwen }
2315aa3a43e6SPascal van Leeuwen 
2316aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_init(struct ahash_request *areq)
2317aa3a43e6SPascal van Leeuwen {
2318aa3a43e6SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
2319aa3a43e6SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2320aa3a43e6SPascal van Leeuwen 
2321aa3a43e6SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2322aa3a43e6SPascal van Leeuwen 
2323aa3a43e6SPascal van Leeuwen 	/* Start from ipad precompute */
232478cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SM3_DIGEST_SIZE);
2325aa3a43e6SPascal van Leeuwen 	/* Already processed the key^ipad part now! */
2326aa3a43e6SPascal van Leeuwen 	req->len	= SM3_BLOCK_SIZE;
2327aa3a43e6SPascal van Leeuwen 	req->processed	= SM3_BLOCK_SIZE;
2328aa3a43e6SPascal van Leeuwen 
2329aa3a43e6SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
2330aa3a43e6SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
2331aa3a43e6SPascal van Leeuwen 	req->state_sz = SM3_DIGEST_SIZE;
23326c1c09b3SPascal van Leeuwen 	req->digest_sz = SM3_DIGEST_SIZE;
2333aa3a43e6SPascal van Leeuwen 	req->block_sz = SM3_BLOCK_SIZE;
2334aa3a43e6SPascal van Leeuwen 	req->hmac = true;
2335aa3a43e6SPascal van Leeuwen 
2336aa3a43e6SPascal van Leeuwen 	return 0;
2337aa3a43e6SPascal van Leeuwen }
2338aa3a43e6SPascal van Leeuwen 
2339aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_digest(struct ahash_request *areq)
2340aa3a43e6SPascal van Leeuwen {
2341aa3a43e6SPascal van Leeuwen 	int ret = safexcel_hmac_sm3_init(areq);
2342aa3a43e6SPascal van Leeuwen 
2343aa3a43e6SPascal van Leeuwen 	if (ret)
2344aa3a43e6SPascal van Leeuwen 		return ret;
2345aa3a43e6SPascal van Leeuwen 
2346aa3a43e6SPascal van Leeuwen 	return safexcel_ahash_finup(areq);
2347aa3a43e6SPascal van Leeuwen }
2348aa3a43e6SPascal van Leeuwen 
2349aa3a43e6SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sm3 = {
2350aa3a43e6SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2351aa3a43e6SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM3,
2352aa3a43e6SPascal van Leeuwen 	.alg.ahash = {
2353aa3a43e6SPascal van Leeuwen 		.init = safexcel_hmac_sm3_init,
2354aa3a43e6SPascal van Leeuwen 		.update = safexcel_ahash_update,
2355aa3a43e6SPascal van Leeuwen 		.final = safexcel_ahash_final,
2356aa3a43e6SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
2357aa3a43e6SPascal van Leeuwen 		.digest = safexcel_hmac_sm3_digest,
2358aa3a43e6SPascal van Leeuwen 		.setkey = safexcel_hmac_sm3_setkey,
2359aa3a43e6SPascal van Leeuwen 		.export = safexcel_ahash_export,
2360aa3a43e6SPascal van Leeuwen 		.import = safexcel_ahash_import,
2361aa3a43e6SPascal van Leeuwen 		.halg = {
2362aa3a43e6SPascal van Leeuwen 			.digestsize = SM3_DIGEST_SIZE,
2363aa3a43e6SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2364aa3a43e6SPascal van Leeuwen 			.base = {
2365aa3a43e6SPascal van Leeuwen 				.cra_name = "hmac(sm3)",
2366aa3a43e6SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sm3",
2367aa3a43e6SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2368aa3a43e6SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2369b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
2370aa3a43e6SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
2371aa3a43e6SPascal van Leeuwen 				.cra_blocksize = SM3_BLOCK_SIZE,
2372aa3a43e6SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2373aa3a43e6SPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
2374aa3a43e6SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
2375aa3a43e6SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2376aa3a43e6SPascal van Leeuwen 			},
2377aa3a43e6SPascal van Leeuwen 		},
2378aa3a43e6SPascal van Leeuwen 	},
2379aa3a43e6SPascal van Leeuwen };
2380aaf5a383SPascal van Leeuwen 
2381aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_init(struct ahash_request *areq)
2382aaf5a383SPascal van Leeuwen {
2383aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2384aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2385aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2386aaf5a383SPascal van Leeuwen 
2387aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2388aaf5a383SPascal van Leeuwen 
2389aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
2390aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2391aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_224_DIGEST_SIZE;
23926c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_224_DIGEST_SIZE;
2393aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_224_BLOCK_SIZE;
2394aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2395aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2396aaf5a383SPascal van Leeuwen 	return 0;
2397aaf5a383SPascal van Leeuwen }
2398aaf5a383SPascal van Leeuwen 
2399aaf5a383SPascal van Leeuwen static int safexcel_sha3_fbcheck(struct ahash_request *req)
2400aaf5a383SPascal van Leeuwen {
2401aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2402aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2403aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2404aaf5a383SPascal van Leeuwen 	int ret = 0;
2405aaf5a383SPascal van Leeuwen 
2406aaf5a383SPascal van Leeuwen 	if (ctx->do_fallback) {
2407aaf5a383SPascal van Leeuwen 		ahash_request_set_tfm(subreq, ctx->fback);
2408aaf5a383SPascal van Leeuwen 		ahash_request_set_callback(subreq, req->base.flags,
2409aaf5a383SPascal van Leeuwen 					   req->base.complete, req->base.data);
2410aaf5a383SPascal van Leeuwen 		ahash_request_set_crypt(subreq, req->src, req->result,
2411aaf5a383SPascal van Leeuwen 					req->nbytes);
2412aaf5a383SPascal van Leeuwen 		if (!ctx->fb_init_done) {
24136c1c09b3SPascal van Leeuwen 			if (ctx->fb_do_setkey) {
24146c1c09b3SPascal van Leeuwen 				/* Set fallback cipher HMAC key */
24156c1c09b3SPascal van Leeuwen 				u8 key[SHA3_224_BLOCK_SIZE];
24166c1c09b3SPascal van Leeuwen 
241778cf1c8bSHerbert Xu 				memcpy(key, &ctx->base.ipad,
24186c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2);
24196c1c09b3SPascal van Leeuwen 				memcpy(key +
24206c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2,
242178cf1c8bSHerbert Xu 				       &ctx->base.opad,
24226c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2);
24236c1c09b3SPascal van Leeuwen 				ret = crypto_ahash_setkey(ctx->fback, key,
24246c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(ctx->fback));
24256c1c09b3SPascal van Leeuwen 				memzero_explicit(key,
24266c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(ctx->fback));
24276c1c09b3SPascal van Leeuwen 				ctx->fb_do_setkey = false;
24286c1c09b3SPascal van Leeuwen 			}
24296c1c09b3SPascal van Leeuwen 			ret = ret ?: crypto_ahash_init(subreq);
2430aaf5a383SPascal van Leeuwen 			ctx->fb_init_done = true;
2431aaf5a383SPascal van Leeuwen 		}
2432aaf5a383SPascal van Leeuwen 	}
2433aaf5a383SPascal van Leeuwen 	return ret;
2434aaf5a383SPascal van Leeuwen }
2435aaf5a383SPascal van Leeuwen 
2436aaf5a383SPascal van Leeuwen static int safexcel_sha3_update(struct ahash_request *req)
2437aaf5a383SPascal van Leeuwen {
2438aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2439aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2440aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2441aaf5a383SPascal van Leeuwen 
2442aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2443aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq);
2444aaf5a383SPascal van Leeuwen }
2445aaf5a383SPascal van Leeuwen 
2446aaf5a383SPascal van Leeuwen static int safexcel_sha3_final(struct ahash_request *req)
2447aaf5a383SPascal van Leeuwen {
2448aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2449aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2450aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2451aaf5a383SPascal van Leeuwen 
2452aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2453aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq);
2454aaf5a383SPascal van Leeuwen }
2455aaf5a383SPascal van Leeuwen 
2456aaf5a383SPascal van Leeuwen static int safexcel_sha3_finup(struct ahash_request *req)
2457aaf5a383SPascal van Leeuwen {
2458aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2459aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2460aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2461aaf5a383SPascal van Leeuwen 
2462aaf5a383SPascal van Leeuwen 	ctx->do_fallback |= !req->nbytes;
2463aaf5a383SPascal van Leeuwen 	if (ctx->do_fallback)
2464aaf5a383SPascal van Leeuwen 		/* Update or ex/import happened or len 0, cannot use the HW */
2465aaf5a383SPascal van Leeuwen 		return safexcel_sha3_fbcheck(req) ?:
2466aaf5a383SPascal van Leeuwen 		       crypto_ahash_finup(subreq);
2467aaf5a383SPascal van Leeuwen 	else
2468aaf5a383SPascal van Leeuwen 		return safexcel_ahash_finup(req);
2469aaf5a383SPascal van Leeuwen }
2470aaf5a383SPascal van Leeuwen 
2471aaf5a383SPascal van Leeuwen static int safexcel_sha3_digest_fallback(struct ahash_request *req)
2472aaf5a383SPascal van Leeuwen {
2473aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2474aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2475aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2476aaf5a383SPascal van Leeuwen 
2477aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2478aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2479aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq);
2480aaf5a383SPascal van Leeuwen }
2481aaf5a383SPascal van Leeuwen 
2482aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_digest(struct ahash_request *req)
2483aaf5a383SPascal van Leeuwen {
2484aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2485aaf5a383SPascal van Leeuwen 		return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req);
2486aaf5a383SPascal van Leeuwen 
2487aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2488aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2489aaf5a383SPascal van Leeuwen }
2490aaf5a383SPascal van Leeuwen 
2491aaf5a383SPascal van Leeuwen static int safexcel_sha3_export(struct ahash_request *req, void *out)
2492aaf5a383SPascal van Leeuwen {
2493aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2494aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2495aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2496aaf5a383SPascal van Leeuwen 
2497aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2498aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out);
2499aaf5a383SPascal van Leeuwen }
2500aaf5a383SPascal van Leeuwen 
2501aaf5a383SPascal van Leeuwen static int safexcel_sha3_import(struct ahash_request *req, const void *in)
2502aaf5a383SPascal van Leeuwen {
2503aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2504aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2505aaf5a383SPascal van Leeuwen 	struct ahash_request *subreq = ahash_request_ctx(req);
2506aaf5a383SPascal van Leeuwen 
2507aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2508aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in);
2509aaf5a383SPascal van Leeuwen 	// return safexcel_ahash_import(req, in);
2510aaf5a383SPascal van Leeuwen }
2511aaf5a383SPascal van Leeuwen 
2512aaf5a383SPascal van Leeuwen static int safexcel_sha3_cra_init(struct crypto_tfm *tfm)
2513aaf5a383SPascal van Leeuwen {
2514aaf5a383SPascal van Leeuwen 	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
2515aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
2516aaf5a383SPascal van Leeuwen 
2517aaf5a383SPascal van Leeuwen 	safexcel_ahash_cra_init(tfm);
2518aaf5a383SPascal van Leeuwen 
2519aaf5a383SPascal van Leeuwen 	/* Allocate fallback implementation */
2520aaf5a383SPascal van Leeuwen 	ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0,
2521aaf5a383SPascal van Leeuwen 					CRYPTO_ALG_ASYNC |
2522aaf5a383SPascal van Leeuwen 					CRYPTO_ALG_NEED_FALLBACK);
2523aaf5a383SPascal van Leeuwen 	if (IS_ERR(ctx->fback))
2524aaf5a383SPascal van Leeuwen 		return PTR_ERR(ctx->fback);
2525aaf5a383SPascal van Leeuwen 
2526aaf5a383SPascal van Leeuwen 	/* Update statesize from fallback algorithm! */
2527aaf5a383SPascal van Leeuwen 	crypto_hash_alg_common(ahash)->statesize =
2528aaf5a383SPascal van Leeuwen 		crypto_ahash_statesize(ctx->fback);
2529aaf5a383SPascal van Leeuwen 	crypto_ahash_set_reqsize(ahash, max(sizeof(struct safexcel_ahash_req),
2530aaf5a383SPascal van Leeuwen 					    sizeof(struct ahash_request) +
2531aaf5a383SPascal van Leeuwen 					    crypto_ahash_reqsize(ctx->fback)));
2532aaf5a383SPascal van Leeuwen 	return 0;
2533aaf5a383SPascal van Leeuwen }
2534aaf5a383SPascal van Leeuwen 
2535aaf5a383SPascal van Leeuwen static void safexcel_sha3_cra_exit(struct crypto_tfm *tfm)
2536aaf5a383SPascal van Leeuwen {
2537aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
2538aaf5a383SPascal van Leeuwen 
2539aaf5a383SPascal van Leeuwen 	crypto_free_ahash(ctx->fback);
2540aaf5a383SPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
2541aaf5a383SPascal van Leeuwen }
2542aaf5a383SPascal van Leeuwen 
2543aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_224 = {
2544aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2545aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2546aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2547aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_224_init,
2548aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2549aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2550aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2551aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_224_digest,
2552aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2553aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2554aaf5a383SPascal van Leeuwen 		.halg = {
2555aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_224_DIGEST_SIZE,
2556aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2557aaf5a383SPascal van Leeuwen 			.base = {
2558aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-224",
2559aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-224",
2560aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2561aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2562aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2563aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2564aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_224_BLOCK_SIZE,
2565aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2566aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2567aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2568aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2569aaf5a383SPascal van Leeuwen 			},
2570aaf5a383SPascal van Leeuwen 		},
2571aaf5a383SPascal van Leeuwen 	},
2572aaf5a383SPascal van Leeuwen };
2573aaf5a383SPascal van Leeuwen 
2574aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_init(struct ahash_request *areq)
2575aaf5a383SPascal van Leeuwen {
2576aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2577aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2578aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2579aaf5a383SPascal van Leeuwen 
2580aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2581aaf5a383SPascal van Leeuwen 
2582aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
2583aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2584aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_256_DIGEST_SIZE;
25856c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_256_DIGEST_SIZE;
2586aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_256_BLOCK_SIZE;
2587aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2588aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2589aaf5a383SPascal van Leeuwen 	return 0;
2590aaf5a383SPascal van Leeuwen }
2591aaf5a383SPascal van Leeuwen 
2592aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_digest(struct ahash_request *req)
2593aaf5a383SPascal van Leeuwen {
2594aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2595aaf5a383SPascal van Leeuwen 		return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req);
2596aaf5a383SPascal van Leeuwen 
2597aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2598aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2599aaf5a383SPascal van Leeuwen }
2600aaf5a383SPascal van Leeuwen 
2601aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_256 = {
2602aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2603aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2604aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2605aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_256_init,
2606aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2607aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2608aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2609aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_256_digest,
2610aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2611aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2612aaf5a383SPascal van Leeuwen 		.halg = {
2613aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_256_DIGEST_SIZE,
2614aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2615aaf5a383SPascal van Leeuwen 			.base = {
2616aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-256",
2617aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-256",
2618aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2619aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2620aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2621aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2622aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_256_BLOCK_SIZE,
2623aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2624aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2625aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2626aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2627aaf5a383SPascal van Leeuwen 			},
2628aaf5a383SPascal van Leeuwen 		},
2629aaf5a383SPascal van Leeuwen 	},
2630aaf5a383SPascal van Leeuwen };
2631aaf5a383SPascal van Leeuwen 
2632aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_init(struct ahash_request *areq)
2633aaf5a383SPascal van Leeuwen {
2634aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2635aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2636aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2637aaf5a383SPascal van Leeuwen 
2638aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2639aaf5a383SPascal van Leeuwen 
2640aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
2641aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2642aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_384_DIGEST_SIZE;
26436c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_384_DIGEST_SIZE;
2644aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_384_BLOCK_SIZE;
2645aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2646aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2647aaf5a383SPascal van Leeuwen 	return 0;
2648aaf5a383SPascal van Leeuwen }
2649aaf5a383SPascal van Leeuwen 
2650aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_digest(struct ahash_request *req)
2651aaf5a383SPascal van Leeuwen {
2652aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2653aaf5a383SPascal van Leeuwen 		return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req);
2654aaf5a383SPascal van Leeuwen 
2655aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2656aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2657aaf5a383SPascal van Leeuwen }
2658aaf5a383SPascal van Leeuwen 
2659aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_384 = {
2660aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2661aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2662aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2663aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_384_init,
2664aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2665aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2666aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2667aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_384_digest,
2668aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2669aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2670aaf5a383SPascal van Leeuwen 		.halg = {
2671aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_384_DIGEST_SIZE,
2672aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2673aaf5a383SPascal van Leeuwen 			.base = {
2674aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-384",
2675aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-384",
2676aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2677aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2678aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2679aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2680aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_384_BLOCK_SIZE,
2681aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2682aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2683aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2684aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2685aaf5a383SPascal van Leeuwen 			},
2686aaf5a383SPascal van Leeuwen 		},
2687aaf5a383SPascal van Leeuwen 	},
2688aaf5a383SPascal van Leeuwen };
2689aaf5a383SPascal van Leeuwen 
2690aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_init(struct ahash_request *areq)
2691aaf5a383SPascal van Leeuwen {
2692aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2693aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2694aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2695aaf5a383SPascal van Leeuwen 
2696aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2697aaf5a383SPascal van Leeuwen 
2698aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
2699aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2700aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_512_DIGEST_SIZE;
27016c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_512_DIGEST_SIZE;
2702aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_512_BLOCK_SIZE;
2703aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2704aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2705aaf5a383SPascal van Leeuwen 	return 0;
2706aaf5a383SPascal van Leeuwen }
2707aaf5a383SPascal van Leeuwen 
2708aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_digest(struct ahash_request *req)
2709aaf5a383SPascal van Leeuwen {
2710aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2711aaf5a383SPascal van Leeuwen 		return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req);
2712aaf5a383SPascal van Leeuwen 
2713aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2714aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2715aaf5a383SPascal van Leeuwen }
2716aaf5a383SPascal van Leeuwen 
2717aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_512 = {
2718aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2719aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2720aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2721aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_512_init,
2722aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2723aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2724aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2725aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_512_digest,
2726aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2727aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2728aaf5a383SPascal van Leeuwen 		.halg = {
2729aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_512_DIGEST_SIZE,
2730aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2731aaf5a383SPascal van Leeuwen 			.base = {
2732aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-512",
2733aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-512",
2734aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2735aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2736aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2737aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2738aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_512_BLOCK_SIZE,
2739aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2740aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2741aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2742aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2743aaf5a383SPascal van Leeuwen 			},
2744aaf5a383SPascal van Leeuwen 		},
2745aaf5a383SPascal van Leeuwen 	},
2746aaf5a383SPascal van Leeuwen };
27476c1c09b3SPascal van Leeuwen 
27486c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg)
27496c1c09b3SPascal van Leeuwen {
27506c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
27516c1c09b3SPascal van Leeuwen 	int ret;
27526c1c09b3SPascal van Leeuwen 
27536c1c09b3SPascal van Leeuwen 	ret = safexcel_sha3_cra_init(tfm);
27546c1c09b3SPascal van Leeuwen 	if (ret)
27556c1c09b3SPascal van Leeuwen 		return ret;
27566c1c09b3SPascal van Leeuwen 
27576c1c09b3SPascal van Leeuwen 	/* Allocate precalc basic digest implementation */
27586c1c09b3SPascal van Leeuwen 	ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
27596c1c09b3SPascal van Leeuwen 	if (IS_ERR(ctx->shpre))
27606c1c09b3SPascal van Leeuwen 		return PTR_ERR(ctx->shpre);
27616c1c09b3SPascal van Leeuwen 
27626c1c09b3SPascal van Leeuwen 	ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) +
27636c1c09b3SPascal van Leeuwen 			      crypto_shash_descsize(ctx->shpre), GFP_KERNEL);
27646c1c09b3SPascal van Leeuwen 	if (!ctx->shdesc) {
27656c1c09b3SPascal van Leeuwen 		crypto_free_shash(ctx->shpre);
27666c1c09b3SPascal van Leeuwen 		return -ENOMEM;
27676c1c09b3SPascal van Leeuwen 	}
27686c1c09b3SPascal van Leeuwen 	ctx->shdesc->tfm = ctx->shpre;
27696c1c09b3SPascal van Leeuwen 	return 0;
27706c1c09b3SPascal van Leeuwen }
27716c1c09b3SPascal van Leeuwen 
27726c1c09b3SPascal van Leeuwen static void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm)
27736c1c09b3SPascal van Leeuwen {
27746c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
27756c1c09b3SPascal van Leeuwen 
27766c1c09b3SPascal van Leeuwen 	crypto_free_ahash(ctx->fback);
27776c1c09b3SPascal van Leeuwen 	crypto_free_shash(ctx->shpre);
27786c1c09b3SPascal van Leeuwen 	kfree(ctx->shdesc);
27796c1c09b3SPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
27806c1c09b3SPascal van Leeuwen }
27816c1c09b3SPascal van Leeuwen 
27826c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key,
27836c1c09b3SPascal van Leeuwen 				     unsigned int keylen)
27846c1c09b3SPascal van Leeuwen {
27856c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
27866c1c09b3SPascal van Leeuwen 	int ret = 0;
27876c1c09b3SPascal van Leeuwen 
27886c1c09b3SPascal van Leeuwen 	if (keylen > crypto_ahash_blocksize(tfm)) {
27896c1c09b3SPascal van Leeuwen 		/*
27906c1c09b3SPascal van Leeuwen 		 * If the key is larger than the blocksize, then hash it
27916c1c09b3SPascal van Leeuwen 		 * first using our fallback cipher
27926c1c09b3SPascal van Leeuwen 		 */
27936c1c09b3SPascal van Leeuwen 		ret = crypto_shash_digest(ctx->shdesc, key, keylen,
279478cf1c8bSHerbert Xu 					  ctx->base.ipad.byte);
27956c1c09b3SPascal van Leeuwen 		keylen = crypto_shash_digestsize(ctx->shpre);
27966c1c09b3SPascal van Leeuwen 
27976c1c09b3SPascal van Leeuwen 		/*
27986c1c09b3SPascal van Leeuwen 		 * If the digest is larger than half the blocksize, we need to
27996c1c09b3SPascal van Leeuwen 		 * move the rest to opad due to the way our HMAC infra works.
28006c1c09b3SPascal van Leeuwen 		 */
28016c1c09b3SPascal van Leeuwen 		if (keylen > crypto_ahash_blocksize(tfm) / 2)
28026c1c09b3SPascal van Leeuwen 			/* Buffers overlap, need to use memmove iso memcpy! */
280378cf1c8bSHerbert Xu 			memmove(&ctx->base.opad,
280478cf1c8bSHerbert Xu 				ctx->base.ipad.byte +
28056c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(tfm) / 2,
28066c1c09b3SPascal van Leeuwen 				keylen - crypto_ahash_blocksize(tfm) / 2);
28076c1c09b3SPascal van Leeuwen 	} else {
28086c1c09b3SPascal van Leeuwen 		/*
28096c1c09b3SPascal van Leeuwen 		 * Copy the key to our ipad & opad buffers
28106c1c09b3SPascal van Leeuwen 		 * Note that ipad and opad each contain one half of the key,
28116c1c09b3SPascal van Leeuwen 		 * to match the existing HMAC driver infrastructure.
28126c1c09b3SPascal van Leeuwen 		 */
28136c1c09b3SPascal van Leeuwen 		if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
281478cf1c8bSHerbert Xu 			memcpy(&ctx->base.ipad, key, keylen);
28156c1c09b3SPascal van Leeuwen 		} else {
281678cf1c8bSHerbert Xu 			memcpy(&ctx->base.ipad, key,
28176c1c09b3SPascal van Leeuwen 			       crypto_ahash_blocksize(tfm) / 2);
281878cf1c8bSHerbert Xu 			memcpy(&ctx->base.opad,
28196c1c09b3SPascal van Leeuwen 			       key + crypto_ahash_blocksize(tfm) / 2,
28206c1c09b3SPascal van Leeuwen 			       keylen - crypto_ahash_blocksize(tfm) / 2);
28216c1c09b3SPascal van Leeuwen 		}
28226c1c09b3SPascal van Leeuwen 	}
28236c1c09b3SPascal van Leeuwen 
28246c1c09b3SPascal van Leeuwen 	/* Pad key with zeroes */
28256c1c09b3SPascal van Leeuwen 	if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
282678cf1c8bSHerbert Xu 		memset(ctx->base.ipad.byte + keylen, 0,
28276c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) / 2 - keylen);
282878cf1c8bSHerbert Xu 		memset(&ctx->base.opad, 0, crypto_ahash_blocksize(tfm) / 2);
28296c1c09b3SPascal van Leeuwen 	} else {
283078cf1c8bSHerbert Xu 		memset(ctx->base.opad.byte + keylen -
28316c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) / 2, 0,
28326c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) - keylen);
28336c1c09b3SPascal van Leeuwen 	}
28346c1c09b3SPascal van Leeuwen 
28356c1c09b3SPascal van Leeuwen 	/* If doing fallback, still need to set the new key! */
28366c1c09b3SPascal van Leeuwen 	ctx->fb_do_setkey = true;
28376c1c09b3SPascal van Leeuwen 	return ret;
28386c1c09b3SPascal van Leeuwen }
28396c1c09b3SPascal van Leeuwen 
28406c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_init(struct ahash_request *areq)
28416c1c09b3SPascal van Leeuwen {
28426c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
28436c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
28446c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
28456c1c09b3SPascal van Leeuwen 
28466c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
28476c1c09b3SPascal van Leeuwen 
28486c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
284978cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA3_224_BLOCK_SIZE / 2);
28506c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
28516c1c09b3SPascal van Leeuwen 	req->len	= SHA3_224_BLOCK_SIZE;
28526c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_224_BLOCK_SIZE;
28536c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
28546c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
28556c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_224_BLOCK_SIZE / 2;
28566c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_224_DIGEST_SIZE;
28576c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_224_BLOCK_SIZE;
28586c1c09b3SPascal van Leeuwen 	req->hmac = true;
28596c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
28606c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
28616c1c09b3SPascal van Leeuwen 	return 0;
28626c1c09b3SPascal van Leeuwen }
28636c1c09b3SPascal van Leeuwen 
28646c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_digest(struct ahash_request *req)
28656c1c09b3SPascal van Leeuwen {
28666c1c09b3SPascal van Leeuwen 	if (req->nbytes)
28676c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_224_init(req) ?:
28686c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
28696c1c09b3SPascal van Leeuwen 
28706c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
28716c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
28726c1c09b3SPascal van Leeuwen }
28736c1c09b3SPascal van Leeuwen 
28746c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm)
28756c1c09b3SPascal van Leeuwen {
28766c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-224");
28776c1c09b3SPascal van Leeuwen }
28786c1c09b3SPascal van Leeuwen 
28796c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_224 = {
28806c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
28816c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
28826c1c09b3SPascal van Leeuwen 	.alg.ahash = {
28836c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_224_init,
28846c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
28856c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
28866c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
28876c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_224_digest,
28886c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
28896c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
28906c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
28916c1c09b3SPascal van Leeuwen 		.halg = {
28926c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_224_DIGEST_SIZE,
28936c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
28946c1c09b3SPascal van Leeuwen 			.base = {
28956c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-224)",
28966c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-224",
28976c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
28986c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
28996c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
29006c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
29016c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_224_BLOCK_SIZE,
29026c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
29036c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_224_cra_init,
29046c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
29056c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
29066c1c09b3SPascal van Leeuwen 			},
29076c1c09b3SPascal van Leeuwen 		},
29086c1c09b3SPascal van Leeuwen 	},
29096c1c09b3SPascal van Leeuwen };
29106c1c09b3SPascal van Leeuwen 
29116c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_init(struct ahash_request *areq)
29126c1c09b3SPascal van Leeuwen {
29136c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
29146c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
29156c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
29166c1c09b3SPascal van Leeuwen 
29176c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
29186c1c09b3SPascal van Leeuwen 
29196c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
292078cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA3_256_BLOCK_SIZE / 2);
29216c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
29226c1c09b3SPascal van Leeuwen 	req->len	= SHA3_256_BLOCK_SIZE;
29236c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_256_BLOCK_SIZE;
29246c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
29256c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
29266c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_256_BLOCK_SIZE / 2;
29276c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_256_DIGEST_SIZE;
29286c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_256_BLOCK_SIZE;
29296c1c09b3SPascal van Leeuwen 	req->hmac = true;
29306c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
29316c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
29326c1c09b3SPascal van Leeuwen 	return 0;
29336c1c09b3SPascal van Leeuwen }
29346c1c09b3SPascal van Leeuwen 
29356c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_digest(struct ahash_request *req)
29366c1c09b3SPascal van Leeuwen {
29376c1c09b3SPascal van Leeuwen 	if (req->nbytes)
29386c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_256_init(req) ?:
29396c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
29406c1c09b3SPascal van Leeuwen 
29416c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
29426c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
29436c1c09b3SPascal van Leeuwen }
29446c1c09b3SPascal van Leeuwen 
29456c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm)
29466c1c09b3SPascal van Leeuwen {
29476c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-256");
29486c1c09b3SPascal van Leeuwen }
29496c1c09b3SPascal van Leeuwen 
29506c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_256 = {
29516c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
29526c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
29536c1c09b3SPascal van Leeuwen 	.alg.ahash = {
29546c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_256_init,
29556c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
29566c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
29576c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
29586c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_256_digest,
29596c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
29606c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
29616c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
29626c1c09b3SPascal van Leeuwen 		.halg = {
29636c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_256_DIGEST_SIZE,
29646c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
29656c1c09b3SPascal van Leeuwen 			.base = {
29666c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-256)",
29676c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-256",
29686c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
29696c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
29706c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
29716c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
29726c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_256_BLOCK_SIZE,
29736c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
29746c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_256_cra_init,
29756c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
29766c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
29776c1c09b3SPascal van Leeuwen 			},
29786c1c09b3SPascal van Leeuwen 		},
29796c1c09b3SPascal van Leeuwen 	},
29806c1c09b3SPascal van Leeuwen };
29816c1c09b3SPascal van Leeuwen 
29826c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_init(struct ahash_request *areq)
29836c1c09b3SPascal van Leeuwen {
29846c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
29856c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
29866c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
29876c1c09b3SPascal van Leeuwen 
29886c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
29896c1c09b3SPascal van Leeuwen 
29906c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
299178cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA3_384_BLOCK_SIZE / 2);
29926c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
29936c1c09b3SPascal van Leeuwen 	req->len	= SHA3_384_BLOCK_SIZE;
29946c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_384_BLOCK_SIZE;
29956c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
29966c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
29976c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_384_BLOCK_SIZE / 2;
29986c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_384_DIGEST_SIZE;
29996c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_384_BLOCK_SIZE;
30006c1c09b3SPascal van Leeuwen 	req->hmac = true;
30016c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
30026c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
30036c1c09b3SPascal van Leeuwen 	return 0;
30046c1c09b3SPascal van Leeuwen }
30056c1c09b3SPascal van Leeuwen 
30066c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_digest(struct ahash_request *req)
30076c1c09b3SPascal van Leeuwen {
30086c1c09b3SPascal van Leeuwen 	if (req->nbytes)
30096c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_384_init(req) ?:
30106c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
30116c1c09b3SPascal van Leeuwen 
30126c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
30136c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
30146c1c09b3SPascal van Leeuwen }
30156c1c09b3SPascal van Leeuwen 
30166c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm)
30176c1c09b3SPascal van Leeuwen {
30186c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-384");
30196c1c09b3SPascal van Leeuwen }
30206c1c09b3SPascal van Leeuwen 
30216c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_384 = {
30226c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
30236c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
30246c1c09b3SPascal van Leeuwen 	.alg.ahash = {
30256c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_384_init,
30266c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
30276c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
30286c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
30296c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_384_digest,
30306c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
30316c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
30326c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
30336c1c09b3SPascal van Leeuwen 		.halg = {
30346c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_384_DIGEST_SIZE,
30356c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
30366c1c09b3SPascal van Leeuwen 			.base = {
30376c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-384)",
30386c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-384",
30396c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
30406c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
30416c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
30426c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
30436c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_384_BLOCK_SIZE,
30446c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
30456c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_384_cra_init,
30466c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
30476c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
30486c1c09b3SPascal van Leeuwen 			},
30496c1c09b3SPascal van Leeuwen 		},
30506c1c09b3SPascal van Leeuwen 	},
30516c1c09b3SPascal van Leeuwen };
30526c1c09b3SPascal van Leeuwen 
30536c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_init(struct ahash_request *areq)
30546c1c09b3SPascal van Leeuwen {
30556c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
30566c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
30576c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
30586c1c09b3SPascal van Leeuwen 
30596c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
30606c1c09b3SPascal van Leeuwen 
30616c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
306278cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA3_512_BLOCK_SIZE / 2);
30636c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
30646c1c09b3SPascal van Leeuwen 	req->len	= SHA3_512_BLOCK_SIZE;
30656c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_512_BLOCK_SIZE;
30666c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
30676c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
30686c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_512_BLOCK_SIZE / 2;
30696c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_512_DIGEST_SIZE;
30706c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_512_BLOCK_SIZE;
30716c1c09b3SPascal van Leeuwen 	req->hmac = true;
30726c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
30736c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
30746c1c09b3SPascal van Leeuwen 	return 0;
30756c1c09b3SPascal van Leeuwen }
30766c1c09b3SPascal van Leeuwen 
30776c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_digest(struct ahash_request *req)
30786c1c09b3SPascal van Leeuwen {
30796c1c09b3SPascal van Leeuwen 	if (req->nbytes)
30806c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_512_init(req) ?:
30816c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
30826c1c09b3SPascal van Leeuwen 
30836c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
30846c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
30856c1c09b3SPascal van Leeuwen }
30866c1c09b3SPascal van Leeuwen 
30876c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm)
30886c1c09b3SPascal van Leeuwen {
30896c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-512");
30906c1c09b3SPascal van Leeuwen }
30916c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_512 = {
30926c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
30936c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
30946c1c09b3SPascal van Leeuwen 	.alg.ahash = {
30956c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_512_init,
30966c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
30976c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
30986c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
30996c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_512_digest,
31006c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
31016c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
31026c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
31036c1c09b3SPascal van Leeuwen 		.halg = {
31046c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_512_DIGEST_SIZE,
31056c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
31066c1c09b3SPascal van Leeuwen 			.base = {
31076c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-512)",
31086c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-512",
31096c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
31106c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
31116c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
31126c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
31136c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_512_BLOCK_SIZE,
31146c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
31156c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_512_cra_init,
31166c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
31176c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
31186c1c09b3SPascal van Leeuwen 			},
31196c1c09b3SPascal van Leeuwen 		},
31206c1c09b3SPascal van Leeuwen 	},
31216c1c09b3SPascal van Leeuwen };
3122