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 
33320406cbSPeter 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 
safexcel_queued_len(struct safexcel_ahash_req * req)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 
safexcel_hash_token(struct safexcel_command_desc * cdesc,u32 input_length,u32 result_length,bool cbcmac)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 
safexcel_context_control(struct safexcel_ahash_ctx * ctx,struct safexcel_ahash_req * req,struct safexcel_command_desc * cdesc)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 
safexcel_handle_req_result(struct safexcel_crypto_priv * priv,int ring,struct crypto_async_request * async,bool * should_complete,int * ret)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);
234b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *sreq = ahash_request_ctx_dma(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 
safexcel_ahash_send_req(struct crypto_async_request * async,int ring,int * commands,int * results)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);
315b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_handle_inv_result(struct safexcel_crypto_priv * priv,int ring,struct crypto_async_request * async,bool * should_complete,int * ret)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 
safexcel_handle_result(struct safexcel_crypto_priv * priv,int ring,struct crypto_async_request * async,bool * should_complete,int * ret)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);
572b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_ahash_send_inv(struct crypto_async_request * async,int ring,int * commands,int * results)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 
safexcel_ahash_send(struct crypto_async_request * async,int ring,int * commands,int * results)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);
611b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_ahash_exit_inv(struct crypto_tfm * tfm)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);
627b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *rctx = ahash_request_ctx_dma(req);
628*acc3f550SHerbert Xu 	DECLARE_CRYPTO_WAIT(result);
62986671abbSAntoine Ténart 	int ring = ctx->base.ring;
630*acc3f550SHerbert Xu 	int err;
6311b44c5a6SAntoine Ténart 
632b926213dSAntoine Tenart 	memset(req, 0, EIP197_AHASH_REQ_SIZE);
6331b44c5a6SAntoine Ténart 
6341b44c5a6SAntoine Ténart 	/* create invalidation request */
6351b44c5a6SAntoine Ténart 	init_completion(&result.completion);
6367cad2fabSAntoine Ténart 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
637*acc3f550SHerbert Xu 				   crypto_req_done, &result);
6381b44c5a6SAntoine Ténart 
6397cad2fabSAntoine Ténart 	ahash_request_set_tfm(req, __crypto_ahash_cast(tfm));
6407cad2fabSAntoine Ténart 	ctx = crypto_tfm_ctx(req->base.tfm);
6411b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
6421eb7b403SOfer Heifetz 	rctx->needs_inv = true;
6431b44c5a6SAntoine Ténart 
64486671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
6457cad2fabSAntoine Ténart 	crypto_enqueue_request(&priv->ring[ring].queue, &req->base);
64686671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
6471b44c5a6SAntoine Ténart 
6488472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
6498472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
6501b44c5a6SAntoine Ténart 
651*acc3f550SHerbert Xu 	err = crypto_wait_req(-EINPROGRESS, &result);
6521b44c5a6SAntoine Ténart 
653*acc3f550SHerbert Xu 	if (err) {
654*acc3f550SHerbert Xu 		dev_warn(priv->dev, "hash: completion error (%d)\n", err);
655*acc3f550SHerbert Xu 		return err;
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  */
safexcel_ahash_cache(struct ahash_request * areq)66441abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq)
6651b44c5a6SAntoine Ténart {
666b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_ahash_enqueue(struct ahash_request * areq)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));
692b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_ahash_update(struct ahash_request * areq)7421b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq)
7431b44c5a6SAntoine Ténart {
744b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_ahash_final(struct ahash_request * areq)7671b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq)
7681b44c5a6SAntoine Ténart {
769b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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
827320406cbSPeter 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 
safexcel_ahash_finup(struct ahash_request * areq)8711b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq)
8721b44c5a6SAntoine Ténart {
873b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_ahash_export(struct ahash_request * areq,void * out)8811b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out)
8821b44c5a6SAntoine Ténart {
883b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_ahash_import(struct ahash_request * areq,const void * in)8971b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in)
8981b44c5a6SAntoine Ténart {
899b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_ahash_cra_init(struct crypto_tfm * tfm)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 
930b2e2e2daSHerbert Xu 	crypto_ahash_set_reqsize_dma(__crypto_ahash_cast(tfm),
9311b44c5a6SAntoine Ténart 				     sizeof(struct safexcel_ahash_req));
9321b44c5a6SAntoine Ténart 	return 0;
9331b44c5a6SAntoine Ténart }
9341b44c5a6SAntoine Ténart 
safexcel_sha1_init(struct ahash_request * areq)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));
938b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_sha1_digest(struct ahash_request * areq)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 
safexcel_ahash_cra_exit(struct crypto_tfm * tfm)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 
safexcel_hmac_sha1_init(struct ahash_request * areq)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));
1015b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(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 
safexcel_hmac_sha1_digest(struct ahash_request * areq)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 
safexcel_hmac_init_pad(struct ahash_request * areq,unsigned int blocksize,const u8 * key,unsigned int keylen,u8 * ipad,u8 * opad)10451b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq,
10461b44c5a6SAntoine Ténart 				  unsigned int blocksize, const u8 *key,
10471b44c5a6SAntoine Ténart 				  unsigned int keylen, u8 *ipad, u8 *opad)
10481b44c5a6SAntoine Ténart {
1049*acc3f550SHerbert Xu 	DECLARE_CRYPTO_WAIT(result);
10501b44c5a6SAntoine Ténart 	struct scatterlist sg;
10511b44c5a6SAntoine Ténart 	int ret, i;
10521b44c5a6SAntoine Ténart 	u8 *keydup;
10531b44c5a6SAntoine Ténart 
10541b44c5a6SAntoine Ténart 	if (keylen <= blocksize) {
10551b44c5a6SAntoine Ténart 		memcpy(ipad, key, keylen);
10561b44c5a6SAntoine Ténart 	} else {
10571b44c5a6SAntoine Ténart 		keydup = kmemdup(key, keylen, GFP_KERNEL);
10581b44c5a6SAntoine Ténart 		if (!keydup)
10591b44c5a6SAntoine Ténart 			return -ENOMEM;
10601b44c5a6SAntoine Ténart 
10611b44c5a6SAntoine Ténart 		ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
1062*acc3f550SHerbert Xu 					   crypto_req_done, &result);
10631b44c5a6SAntoine Ténart 		sg_init_one(&sg, keydup, keylen);
10641b44c5a6SAntoine Ténart 		ahash_request_set_crypt(areq, &sg, ipad, keylen);
10651b44c5a6SAntoine Ténart 
10661b44c5a6SAntoine Ténart 		ret = crypto_ahash_digest(areq);
1067*acc3f550SHerbert Xu 		ret = crypto_wait_req(ret, &result);
10681b44c5a6SAntoine Ténart 
10691b44c5a6SAntoine Ténart 		/* Avoid leaking */
107057059185SDenis Efremov 		kfree_sensitive(keydup);
10711b44c5a6SAntoine Ténart 
10721b44c5a6SAntoine Ténart 		if (ret)
10731b44c5a6SAntoine Ténart 			return ret;
10741b44c5a6SAntoine Ténart 
10751b44c5a6SAntoine Ténart 		keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq));
10761b44c5a6SAntoine Ténart 	}
10771b44c5a6SAntoine Ténart 
10781b44c5a6SAntoine Ténart 	memset(ipad + keylen, 0, blocksize - keylen);
10791b44c5a6SAntoine Ténart 	memcpy(opad, ipad, blocksize);
10801b44c5a6SAntoine Ténart 
10811b44c5a6SAntoine Ténart 	for (i = 0; i < blocksize; i++) {
1082aed3731eSAntoine Ténart 		ipad[i] ^= HMAC_IPAD_VALUE;
1083aed3731eSAntoine Ténart 		opad[i] ^= HMAC_OPAD_VALUE;
10841b44c5a6SAntoine Ténart 	}
10851b44c5a6SAntoine Ténart 
10861b44c5a6SAntoine Ténart 	return 0;
10871b44c5a6SAntoine Ténart }
10881b44c5a6SAntoine Ténart 
safexcel_hmac_init_iv(struct ahash_request * areq,unsigned int blocksize,u8 * pad,void * state)10891b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq,
10901b44c5a6SAntoine Ténart 				 unsigned int blocksize, u8 *pad, void *state)
10911b44c5a6SAntoine Ténart {
10921b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req;
1093*acc3f550SHerbert Xu 	DECLARE_CRYPTO_WAIT(result);
10941b44c5a6SAntoine Ténart 	struct scatterlist sg;
10951b44c5a6SAntoine Ténart 	int ret;
10961b44c5a6SAntoine Ténart 
10971b44c5a6SAntoine Ténart 	ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
1098*acc3f550SHerbert Xu 				   crypto_req_done, &result);
10991b44c5a6SAntoine Ténart 	sg_init_one(&sg, pad, blocksize);
11001b44c5a6SAntoine Ténart 	ahash_request_set_crypt(areq, &sg, pad, blocksize);
11011b44c5a6SAntoine Ténart 
11021b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
11031b44c5a6SAntoine Ténart 	if (ret)
11041b44c5a6SAntoine Ténart 		return ret;
11051b44c5a6SAntoine Ténart 
1106b2e2e2daSHerbert Xu 	req = ahash_request_ctx_dma(areq);
11071b44c5a6SAntoine Ténart 	req->hmac = true;
11081b44c5a6SAntoine Ténart 	req->last_req = true;
11091b44c5a6SAntoine Ténart 
11101b44c5a6SAntoine Ténart 	ret = crypto_ahash_update(areq);
1111*acc3f550SHerbert Xu 	ret = crypto_wait_req(ret, &result);
11121b44c5a6SAntoine Ténart 
1113*acc3f550SHerbert Xu 	return ret ?: crypto_ahash_export(areq, state);
11141b44c5a6SAntoine Ténart }
11151b44c5a6SAntoine Ténart 
__safexcel_hmac_setkey(const char * alg,const u8 * key,unsigned int keylen,void * istate,void * ostate)111663cdd870SHerbert Xu static int __safexcel_hmac_setkey(const char *alg, const u8 *key,
111763cdd870SHerbert Xu 				  unsigned int keylen,
1118f6beaea3SAntoine Tenart 				  void *istate, void *ostate)
11191b44c5a6SAntoine Ténart {
11201b44c5a6SAntoine Ténart 	struct ahash_request *areq;
11211b44c5a6SAntoine Ténart 	struct crypto_ahash *tfm;
11221b44c5a6SAntoine Ténart 	unsigned int blocksize;
11231b44c5a6SAntoine Ténart 	u8 *ipad, *opad;
11241b44c5a6SAntoine Ténart 	int ret;
11251b44c5a6SAntoine Ténart 
112685d7311fSEric Biggers 	tfm = crypto_alloc_ahash(alg, 0, 0);
11271b44c5a6SAntoine Ténart 	if (IS_ERR(tfm))
11281b44c5a6SAntoine Ténart 		return PTR_ERR(tfm);
11291b44c5a6SAntoine Ténart 
11301b44c5a6SAntoine Ténart 	areq = ahash_request_alloc(tfm, GFP_KERNEL);
11311b44c5a6SAntoine Ténart 	if (!areq) {
11321b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11331b44c5a6SAntoine Ténart 		goto free_ahash;
11341b44c5a6SAntoine Ténart 	}
11351b44c5a6SAntoine Ténart 
11361b44c5a6SAntoine Ténart 	crypto_ahash_clear_flags(tfm, ~0);
11371b44c5a6SAntoine Ténart 	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
11381b44c5a6SAntoine Ténart 
11396396bb22SKees Cook 	ipad = kcalloc(2, blocksize, GFP_KERNEL);
11401b44c5a6SAntoine Ténart 	if (!ipad) {
11411b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11421b44c5a6SAntoine Ténart 		goto free_request;
11431b44c5a6SAntoine Ténart 	}
11441b44c5a6SAntoine Ténart 
11451b44c5a6SAntoine Ténart 	opad = ipad + blocksize;
11461b44c5a6SAntoine Ténart 
11471b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad);
11481b44c5a6SAntoine Ténart 	if (ret)
11491b44c5a6SAntoine Ténart 		goto free_ipad;
11501b44c5a6SAntoine Ténart 
11511b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate);
11521b44c5a6SAntoine Ténart 	if (ret)
11531b44c5a6SAntoine Ténart 		goto free_ipad;
11541b44c5a6SAntoine Ténart 
11551b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate);
11561b44c5a6SAntoine Ténart 
11571b44c5a6SAntoine Ténart free_ipad:
11581b44c5a6SAntoine Ténart 	kfree(ipad);
11591b44c5a6SAntoine Ténart free_request:
11601b44c5a6SAntoine Ténart 	ahash_request_free(areq);
11611b44c5a6SAntoine Ténart free_ahash:
11621b44c5a6SAntoine Ténart 	crypto_free_ahash(tfm);
11631b44c5a6SAntoine Ténart 
11641b44c5a6SAntoine Ténart 	return ret;
11651b44c5a6SAntoine Ténart }
11661b44c5a6SAntoine Ténart 
safexcel_hmac_setkey(struct safexcel_context * base,const u8 * key,unsigned int keylen,const char * alg,unsigned int state_sz)116763cdd870SHerbert Xu int safexcel_hmac_setkey(struct safexcel_context *base, const u8 *key,
116863cdd870SHerbert Xu 			 unsigned int keylen, const char *alg,
116963cdd870SHerbert Xu 			 unsigned int state_sz)
117063cdd870SHerbert Xu {
117163cdd870SHerbert Xu 	struct safexcel_crypto_priv *priv = base->priv;
117263cdd870SHerbert Xu 	struct safexcel_ahash_export_state istate, ostate;
117363cdd870SHerbert Xu 	int ret;
117463cdd870SHerbert Xu 
117563cdd870SHerbert Xu 	ret = __safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate);
117663cdd870SHerbert Xu 	if (ret)
117763cdd870SHerbert Xu 		return ret;
117863cdd870SHerbert Xu 
117963cdd870SHerbert Xu 	if (priv->flags & EIP197_TRC_CACHE && base->ctxr &&
118063cdd870SHerbert Xu 	    (memcmp(&base->ipad, istate.state, state_sz) ||
118163cdd870SHerbert Xu 	     memcmp(&base->opad, ostate.state, state_sz)))
118263cdd870SHerbert Xu 		base->needs_inv = true;
118363cdd870SHerbert Xu 
118463cdd870SHerbert Xu 	memcpy(&base->ipad, &istate.state, state_sz);
118563cdd870SHerbert Xu 	memcpy(&base->opad, &ostate.state, state_sz);
118663cdd870SHerbert Xu 
118763cdd870SHerbert Xu 	return 0;
118863cdd870SHerbert Xu }
118963cdd870SHerbert Xu 
safexcel_hmac_alg_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen,const char * alg,unsigned int state_sz)119073f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key,
119173f36ea7SAntoine Tenart 				    unsigned int keylen, const char *alg,
119273f36ea7SAntoine Tenart 				    unsigned int state_sz)
11931b44c5a6SAntoine Ténart {
119463cdd870SHerbert Xu 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
11951b44c5a6SAntoine Ténart 
119663cdd870SHerbert Xu 	return safexcel_hmac_setkey(&ctx->base, key, keylen, alg, state_sz);
11971b44c5a6SAntoine Ténart }
11981b44c5a6SAntoine Ténart 
safexcel_hmac_sha1_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)119973f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
120073f36ea7SAntoine Tenart 				     unsigned int keylen)
120173f36ea7SAntoine Tenart {
120273f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1",
120373f36ea7SAntoine Tenart 					SHA1_DIGEST_SIZE);
120473f36ea7SAntoine Tenart }
120573f36ea7SAntoine Tenart 
12061b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = {
12071b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1208062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
12091b44c5a6SAntoine Ténart 	.alg.ahash = {
12101b44c5a6SAntoine Ténart 		.init = safexcel_hmac_sha1_init,
12111b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12121b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12131b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12141b44c5a6SAntoine Ténart 		.digest = safexcel_hmac_sha1_digest,
12151b44c5a6SAntoine Ténart 		.setkey = safexcel_hmac_sha1_setkey,
12161b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12171b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12181b44c5a6SAntoine Ténart 		.halg = {
12191b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
12201b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12211b44c5a6SAntoine Ténart 			.base = {
12221b44c5a6SAntoine Ténart 				.cra_name = "hmac(sha1)",
12231b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-hmac-sha1",
1224aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12251b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1226b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
12271b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12281b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
12291b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12301b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
12311b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
12321b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
12331b44c5a6SAntoine Ténart 			},
12341b44c5a6SAntoine Ténart 		},
12351b44c5a6SAntoine Ténart 	},
12361b44c5a6SAntoine Ténart };
12371b44c5a6SAntoine Ténart 
safexcel_sha256_init(struct ahash_request * areq)12381b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq)
12391b44c5a6SAntoine Ténart {
12401b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1241b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
12421b44c5a6SAntoine Ténart 
12431b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
12441b44c5a6SAntoine Ténart 
12451b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1246b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
12471b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
12486c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
124941abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
12501b44c5a6SAntoine Ténart 
12511b44c5a6SAntoine Ténart 	return 0;
12521b44c5a6SAntoine Ténart }
12531b44c5a6SAntoine Ténart 
safexcel_sha256_digest(struct ahash_request * areq)12541b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq)
12551b44c5a6SAntoine Ténart {
12561b44c5a6SAntoine Ténart 	int ret = safexcel_sha256_init(areq);
12571b44c5a6SAntoine Ténart 
12581b44c5a6SAntoine Ténart 	if (ret)
12591b44c5a6SAntoine Ténart 		return ret;
12601b44c5a6SAntoine Ténart 
12611b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
12621b44c5a6SAntoine Ténart }
12631b44c5a6SAntoine Ténart 
12641b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = {
12651b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1266062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
12671b44c5a6SAntoine Ténart 	.alg.ahash = {
12681b44c5a6SAntoine Ténart 		.init = safexcel_sha256_init,
12691b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12701b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12711b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12721b44c5a6SAntoine Ténart 		.digest = safexcel_sha256_digest,
12731b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12741b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12751b44c5a6SAntoine Ténart 		.halg = {
12761b44c5a6SAntoine Ténart 			.digestsize = SHA256_DIGEST_SIZE,
12771b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12781b44c5a6SAntoine Ténart 			.base = {
12791b44c5a6SAntoine Ténart 				.cra_name = "sha256",
12801b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha256",
1281aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12821b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1283b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
12841b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12851b44c5a6SAntoine Ténart 				.cra_blocksize = SHA256_BLOCK_SIZE,
12861b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12871b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
12881b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
12891b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
12901b44c5a6SAntoine Ténart 			},
12911b44c5a6SAntoine Ténart 		},
12921b44c5a6SAntoine Ténart 	},
12931b44c5a6SAntoine Ténart };
12941b44c5a6SAntoine Ténart 
safexcel_sha224_init(struct ahash_request * areq)12951b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq)
12961b44c5a6SAntoine Ténart {
12971b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1298b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
12991b44c5a6SAntoine Ténart 
13001b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
13011b44c5a6SAntoine Ténart 
13021b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1303b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
13041b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
13056c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
130641abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
13071b44c5a6SAntoine Ténart 
13081b44c5a6SAntoine Ténart 	return 0;
13091b44c5a6SAntoine Ténart }
13101b44c5a6SAntoine Ténart 
safexcel_sha224_digest(struct ahash_request * areq)13111b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq)
13121b44c5a6SAntoine Ténart {
13131b44c5a6SAntoine Ténart 	int ret = safexcel_sha224_init(areq);
13141b44c5a6SAntoine Ténart 
13151b44c5a6SAntoine Ténart 	if (ret)
13161b44c5a6SAntoine Ténart 		return ret;
13171b44c5a6SAntoine Ténart 
13181b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
13191b44c5a6SAntoine Ténart }
13201b44c5a6SAntoine Ténart 
13211b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = {
13221b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1323062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
13241b44c5a6SAntoine Ténart 	.alg.ahash = {
13251b44c5a6SAntoine Ténart 		.init = safexcel_sha224_init,
13261b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
13271b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
13281b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
13291b44c5a6SAntoine Ténart 		.digest = safexcel_sha224_digest,
13301b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
13311b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
13321b44c5a6SAntoine Ténart 		.halg = {
13331b44c5a6SAntoine Ténart 			.digestsize = SHA224_DIGEST_SIZE,
13341b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
13351b44c5a6SAntoine Ténart 			.base = {
13361b44c5a6SAntoine Ténart 				.cra_name = "sha224",
13371b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha224",
1338aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
13391b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
1340b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
13411b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
13421b44c5a6SAntoine Ténart 				.cra_blocksize = SHA224_BLOCK_SIZE,
13431b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
13441b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
13451b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
13461b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
13471b44c5a6SAntoine Ténart 			},
13481b44c5a6SAntoine Ténart 		},
13491b44c5a6SAntoine Ténart 	},
13501b44c5a6SAntoine Ténart };
135173f36ea7SAntoine Tenart 
safexcel_hmac_sha224_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)13523ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key,
13533ad618d8SAntoine Tenart 				       unsigned int keylen)
13543ad618d8SAntoine Tenart {
13553ad618d8SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224",
13563ad618d8SAntoine Tenart 					SHA256_DIGEST_SIZE);
13573ad618d8SAntoine Tenart }
13583ad618d8SAntoine Tenart 
safexcel_hmac_sha224_init(struct ahash_request * areq)13593ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq)
13603ad618d8SAntoine Tenart {
136141abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1362b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
13633ad618d8SAntoine Tenart 
136441abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
136541abed7dSPascal van Leeuwen 
136641abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
136778cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE);
136841abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
136931fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
137031fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
137141abed7dSPascal van Leeuwen 
137241abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
137341abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
137441abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
13756c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
137641abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
137741abed7dSPascal van Leeuwen 	req->hmac = true;
137841abed7dSPascal van Leeuwen 
13793ad618d8SAntoine Tenart 	return 0;
13803ad618d8SAntoine Tenart }
13813ad618d8SAntoine Tenart 
safexcel_hmac_sha224_digest(struct ahash_request * areq)13823ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq)
13833ad618d8SAntoine Tenart {
13843ad618d8SAntoine Tenart 	int ret = safexcel_hmac_sha224_init(areq);
13853ad618d8SAntoine Tenart 
13863ad618d8SAntoine Tenart 	if (ret)
13873ad618d8SAntoine Tenart 		return ret;
13883ad618d8SAntoine Tenart 
13893ad618d8SAntoine Tenart 	return safexcel_ahash_finup(areq);
13903ad618d8SAntoine Tenart }
13913ad618d8SAntoine Tenart 
13923ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = {
13933ad618d8SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1394062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
13953ad618d8SAntoine Tenart 	.alg.ahash = {
13963ad618d8SAntoine Tenart 		.init = safexcel_hmac_sha224_init,
13973ad618d8SAntoine Tenart 		.update = safexcel_ahash_update,
13983ad618d8SAntoine Tenart 		.final = safexcel_ahash_final,
13993ad618d8SAntoine Tenart 		.finup = safexcel_ahash_finup,
14003ad618d8SAntoine Tenart 		.digest = safexcel_hmac_sha224_digest,
14013ad618d8SAntoine Tenart 		.setkey = safexcel_hmac_sha224_setkey,
14023ad618d8SAntoine Tenart 		.export = safexcel_ahash_export,
14033ad618d8SAntoine Tenart 		.import = safexcel_ahash_import,
14043ad618d8SAntoine Tenart 		.halg = {
14053ad618d8SAntoine Tenart 			.digestsize = SHA224_DIGEST_SIZE,
14063ad618d8SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
14073ad618d8SAntoine Tenart 			.base = {
14083ad618d8SAntoine Tenart 				.cra_name = "hmac(sha224)",
14093ad618d8SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha224",
1410aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
14113ad618d8SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1412b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
14133ad618d8SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
14143ad618d8SAntoine Tenart 				.cra_blocksize = SHA224_BLOCK_SIZE,
14153ad618d8SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
14163ad618d8SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
14173ad618d8SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
14183ad618d8SAntoine Tenart 				.cra_module = THIS_MODULE,
14193ad618d8SAntoine Tenart 			},
14203ad618d8SAntoine Tenart 		},
14213ad618d8SAntoine Tenart 	},
14223ad618d8SAntoine Tenart };
14233ad618d8SAntoine Tenart 
safexcel_hmac_sha256_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)142473f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
142573f36ea7SAntoine Tenart 				     unsigned int keylen)
142673f36ea7SAntoine Tenart {
142773f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256",
142873f36ea7SAntoine Tenart 					SHA256_DIGEST_SIZE);
142973f36ea7SAntoine Tenart }
143073f36ea7SAntoine Tenart 
safexcel_hmac_sha256_init(struct ahash_request * areq)143173f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq)
143273f36ea7SAntoine Tenart {
143341abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1434b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
143573f36ea7SAntoine Tenart 
143641abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
143741abed7dSPascal van Leeuwen 
143841abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
143978cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE);
144041abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
144131fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
144231fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
144341abed7dSPascal van Leeuwen 
144441abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
144541abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
144641abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
14476c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA256_DIGEST_SIZE;
144841abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
144941abed7dSPascal van Leeuwen 	req->hmac = true;
145041abed7dSPascal van Leeuwen 
145173f36ea7SAntoine Tenart 	return 0;
145273f36ea7SAntoine Tenart }
145373f36ea7SAntoine Tenart 
safexcel_hmac_sha256_digest(struct ahash_request * areq)145473f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq)
145573f36ea7SAntoine Tenart {
145673f36ea7SAntoine Tenart 	int ret = safexcel_hmac_sha256_init(areq);
145773f36ea7SAntoine Tenart 
145873f36ea7SAntoine Tenart 	if (ret)
145973f36ea7SAntoine Tenart 		return ret;
146073f36ea7SAntoine Tenart 
146173f36ea7SAntoine Tenart 	return safexcel_ahash_finup(areq);
146273f36ea7SAntoine Tenart }
146373f36ea7SAntoine Tenart 
146473f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = {
146573f36ea7SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1466062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
146773f36ea7SAntoine Tenart 	.alg.ahash = {
146873f36ea7SAntoine Tenart 		.init = safexcel_hmac_sha256_init,
146973f36ea7SAntoine Tenart 		.update = safexcel_ahash_update,
147073f36ea7SAntoine Tenart 		.final = safexcel_ahash_final,
147173f36ea7SAntoine Tenart 		.finup = safexcel_ahash_finup,
147273f36ea7SAntoine Tenart 		.digest = safexcel_hmac_sha256_digest,
147373f36ea7SAntoine Tenart 		.setkey = safexcel_hmac_sha256_setkey,
147473f36ea7SAntoine Tenart 		.export = safexcel_ahash_export,
147573f36ea7SAntoine Tenart 		.import = safexcel_ahash_import,
147673f36ea7SAntoine Tenart 		.halg = {
147773f36ea7SAntoine Tenart 			.digestsize = SHA256_DIGEST_SIZE,
147873f36ea7SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
147973f36ea7SAntoine Tenart 			.base = {
148073f36ea7SAntoine Tenart 				.cra_name = "hmac(sha256)",
148173f36ea7SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha256",
1482aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
148373f36ea7SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1484b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
148573f36ea7SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
148673f36ea7SAntoine Tenart 				.cra_blocksize = SHA256_BLOCK_SIZE,
148773f36ea7SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
148873f36ea7SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
148973f36ea7SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
149073f36ea7SAntoine Tenart 				.cra_module = THIS_MODULE,
149173f36ea7SAntoine Tenart 			},
149273f36ea7SAntoine Tenart 		},
149373f36ea7SAntoine Tenart 	},
149473f36ea7SAntoine Tenart };
1495b460edb6SAntoine Tenart 
safexcel_sha512_init(struct ahash_request * areq)1496b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq)
1497b460edb6SAntoine Tenart {
1498b460edb6SAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1499b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
1500b460edb6SAntoine Tenart 
1501b460edb6SAntoine Tenart 	memset(req, 0, sizeof(*req));
1502b460edb6SAntoine Tenart 
1503b460edb6SAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
1504b460edb6SAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1505b460edb6SAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
15066c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
150741abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
1508b460edb6SAntoine Tenart 
1509b460edb6SAntoine Tenart 	return 0;
1510b460edb6SAntoine Tenart }
1511b460edb6SAntoine Tenart 
safexcel_sha512_digest(struct ahash_request * areq)1512b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq)
1513b460edb6SAntoine Tenart {
1514b460edb6SAntoine Tenart 	int ret = safexcel_sha512_init(areq);
1515b460edb6SAntoine Tenart 
1516b460edb6SAntoine Tenart 	if (ret)
1517b460edb6SAntoine Tenart 		return ret;
1518b460edb6SAntoine Tenart 
1519b460edb6SAntoine Tenart 	return safexcel_ahash_finup(areq);
1520b460edb6SAntoine Tenart }
1521b460edb6SAntoine Tenart 
1522b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = {
1523b460edb6SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1524062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
1525b460edb6SAntoine Tenart 	.alg.ahash = {
1526b460edb6SAntoine Tenart 		.init = safexcel_sha512_init,
1527b460edb6SAntoine Tenart 		.update = safexcel_ahash_update,
1528b460edb6SAntoine Tenart 		.final = safexcel_ahash_final,
1529b460edb6SAntoine Tenart 		.finup = safexcel_ahash_finup,
1530b460edb6SAntoine Tenart 		.digest = safexcel_sha512_digest,
1531b460edb6SAntoine Tenart 		.export = safexcel_ahash_export,
1532b460edb6SAntoine Tenart 		.import = safexcel_ahash_import,
1533b460edb6SAntoine Tenart 		.halg = {
1534b460edb6SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
1535b460edb6SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
1536b460edb6SAntoine Tenart 			.base = {
1537b460edb6SAntoine Tenart 				.cra_name = "sha512",
1538b460edb6SAntoine Tenart 				.cra_driver_name = "safexcel-sha512",
1539aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1540b460edb6SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1541b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1542b460edb6SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1543b460edb6SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
1544b460edb6SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1545b460edb6SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
1546b460edb6SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
1547b460edb6SAntoine Tenart 				.cra_module = THIS_MODULE,
1548b460edb6SAntoine Tenart 			},
1549b460edb6SAntoine Tenart 		},
1550b460edb6SAntoine Tenart 	},
1551b460edb6SAntoine Tenart };
15520de54fb1SAntoine Tenart 
safexcel_sha384_init(struct ahash_request * areq)15539e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq)
15549e46eafdSAntoine Tenart {
15559e46eafdSAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1556b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
15579e46eafdSAntoine Tenart 
15589e46eafdSAntoine Tenart 	memset(req, 0, sizeof(*req));
15599e46eafdSAntoine Tenart 
15609e46eafdSAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
15619e46eafdSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
15629e46eafdSAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
15636c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
156441abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
15659e46eafdSAntoine Tenart 
15669e46eafdSAntoine Tenart 	return 0;
15679e46eafdSAntoine Tenart }
15689e46eafdSAntoine Tenart 
safexcel_sha384_digest(struct ahash_request * areq)15699e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq)
15709e46eafdSAntoine Tenart {
15719e46eafdSAntoine Tenart 	int ret = safexcel_sha384_init(areq);
15729e46eafdSAntoine Tenart 
15739e46eafdSAntoine Tenart 	if (ret)
15749e46eafdSAntoine Tenart 		return ret;
15759e46eafdSAntoine Tenart 
15769e46eafdSAntoine Tenart 	return safexcel_ahash_finup(areq);
15779e46eafdSAntoine Tenart }
15789e46eafdSAntoine Tenart 
15799e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = {
15809e46eafdSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1581062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
15829e46eafdSAntoine Tenart 	.alg.ahash = {
15839e46eafdSAntoine Tenart 		.init = safexcel_sha384_init,
15849e46eafdSAntoine Tenart 		.update = safexcel_ahash_update,
15859e46eafdSAntoine Tenart 		.final = safexcel_ahash_final,
15869e46eafdSAntoine Tenart 		.finup = safexcel_ahash_finup,
15879e46eafdSAntoine Tenart 		.digest = safexcel_sha384_digest,
15889e46eafdSAntoine Tenart 		.export = safexcel_ahash_export,
15899e46eafdSAntoine Tenart 		.import = safexcel_ahash_import,
15909e46eafdSAntoine Tenart 		.halg = {
15919e46eafdSAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
15929e46eafdSAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
15939e46eafdSAntoine Tenart 			.base = {
15949e46eafdSAntoine Tenart 				.cra_name = "sha384",
15959e46eafdSAntoine Tenart 				.cra_driver_name = "safexcel-sha384",
1596aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
15979e46eafdSAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1598b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
15999e46eafdSAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16009e46eafdSAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
16019e46eafdSAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
16029e46eafdSAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
16039e46eafdSAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
16049e46eafdSAntoine Tenart 				.cra_module = THIS_MODULE,
16059e46eafdSAntoine Tenart 			},
16069e46eafdSAntoine Tenart 		},
16079e46eafdSAntoine Tenart 	},
16089e46eafdSAntoine Tenart };
16099e46eafdSAntoine Tenart 
safexcel_hmac_sha512_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)16100de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key,
16110de54fb1SAntoine Tenart 				       unsigned int keylen)
16120de54fb1SAntoine Tenart {
16130de54fb1SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512",
16140de54fb1SAntoine Tenart 					SHA512_DIGEST_SIZE);
16150de54fb1SAntoine Tenart }
16160de54fb1SAntoine Tenart 
safexcel_hmac_sha512_init(struct ahash_request * areq)16170de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq)
16180de54fb1SAntoine Tenart {
161941abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1620b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
16210de54fb1SAntoine Tenart 
162241abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
162341abed7dSPascal van Leeuwen 
162441abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
162578cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE);
162641abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
162731fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
162831fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
162941abed7dSPascal van Leeuwen 
163041abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
163141abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
163241abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
16336c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
163441abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
163541abed7dSPascal van Leeuwen 	req->hmac = true;
163641abed7dSPascal van Leeuwen 
16370de54fb1SAntoine Tenart 	return 0;
16380de54fb1SAntoine Tenart }
16390de54fb1SAntoine Tenart 
safexcel_hmac_sha512_digest(struct ahash_request * areq)16400de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq)
16410de54fb1SAntoine Tenart {
16420de54fb1SAntoine Tenart 	int ret = safexcel_hmac_sha512_init(areq);
16430de54fb1SAntoine Tenart 
16440de54fb1SAntoine Tenart 	if (ret)
16450de54fb1SAntoine Tenart 		return ret;
16460de54fb1SAntoine Tenart 
16470de54fb1SAntoine Tenart 	return safexcel_ahash_finup(areq);
16480de54fb1SAntoine Tenart }
16490de54fb1SAntoine Tenart 
16500de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = {
16510de54fb1SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1652062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
16530de54fb1SAntoine Tenart 	.alg.ahash = {
16540de54fb1SAntoine Tenart 		.init = safexcel_hmac_sha512_init,
16550de54fb1SAntoine Tenart 		.update = safexcel_ahash_update,
16560de54fb1SAntoine Tenart 		.final = safexcel_ahash_final,
16570de54fb1SAntoine Tenart 		.finup = safexcel_ahash_finup,
16580de54fb1SAntoine Tenart 		.digest = safexcel_hmac_sha512_digest,
16590de54fb1SAntoine Tenart 		.setkey = safexcel_hmac_sha512_setkey,
16600de54fb1SAntoine Tenart 		.export = safexcel_ahash_export,
16610de54fb1SAntoine Tenart 		.import = safexcel_ahash_import,
16620de54fb1SAntoine Tenart 		.halg = {
16630de54fb1SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
16640de54fb1SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
16650de54fb1SAntoine Tenart 			.base = {
16660de54fb1SAntoine Tenart 				.cra_name = "hmac(sha512)",
16670de54fb1SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha512",
1668aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
16690de54fb1SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1670b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
16710de54fb1SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16720de54fb1SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
16730de54fb1SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
16740de54fb1SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
16750de54fb1SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
16760de54fb1SAntoine Tenart 				.cra_module = THIS_MODULE,
16770de54fb1SAntoine Tenart 			},
16780de54fb1SAntoine Tenart 		},
16790de54fb1SAntoine Tenart 	},
16800de54fb1SAntoine Tenart };
16811f5d5d98SAntoine Tenart 
safexcel_hmac_sha384_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)16821f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key,
16831f5d5d98SAntoine Tenart 				       unsigned int keylen)
16841f5d5d98SAntoine Tenart {
16851f5d5d98SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384",
16861f5d5d98SAntoine Tenart 					SHA512_DIGEST_SIZE);
16871f5d5d98SAntoine Tenart }
16881f5d5d98SAntoine Tenart 
safexcel_hmac_sha384_init(struct ahash_request * areq)16891f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq)
16901f5d5d98SAntoine Tenart {
169141abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1692b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
16931f5d5d98SAntoine Tenart 
169441abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
169541abed7dSPascal van Leeuwen 
169641abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
169778cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE);
169841abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
169931fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
170031fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
170141abed7dSPascal van Leeuwen 
170241abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
170341abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
170441abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
17056c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA512_DIGEST_SIZE;
170641abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
170741abed7dSPascal van Leeuwen 	req->hmac = true;
170841abed7dSPascal van Leeuwen 
17091f5d5d98SAntoine Tenart 	return 0;
17101f5d5d98SAntoine Tenart }
17111f5d5d98SAntoine Tenart 
safexcel_hmac_sha384_digest(struct ahash_request * areq)17121f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq)
17131f5d5d98SAntoine Tenart {
17141f5d5d98SAntoine Tenart 	int ret = safexcel_hmac_sha384_init(areq);
17151f5d5d98SAntoine Tenart 
17161f5d5d98SAntoine Tenart 	if (ret)
17171f5d5d98SAntoine Tenart 		return ret;
17181f5d5d98SAntoine Tenart 
17191f5d5d98SAntoine Tenart 	return safexcel_ahash_finup(areq);
17201f5d5d98SAntoine Tenart }
17211f5d5d98SAntoine Tenart 
17221f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = {
17231f5d5d98SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1724062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
17251f5d5d98SAntoine Tenart 	.alg.ahash = {
17261f5d5d98SAntoine Tenart 		.init = safexcel_hmac_sha384_init,
17271f5d5d98SAntoine Tenart 		.update = safexcel_ahash_update,
17281f5d5d98SAntoine Tenart 		.final = safexcel_ahash_final,
17291f5d5d98SAntoine Tenart 		.finup = safexcel_ahash_finup,
17301f5d5d98SAntoine Tenart 		.digest = safexcel_hmac_sha384_digest,
17311f5d5d98SAntoine Tenart 		.setkey = safexcel_hmac_sha384_setkey,
17321f5d5d98SAntoine Tenart 		.export = safexcel_ahash_export,
17331f5d5d98SAntoine Tenart 		.import = safexcel_ahash_import,
17341f5d5d98SAntoine Tenart 		.halg = {
17351f5d5d98SAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
17361f5d5d98SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
17371f5d5d98SAntoine Tenart 			.base = {
17381f5d5d98SAntoine Tenart 				.cra_name = "hmac(sha384)",
17391f5d5d98SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha384",
1740aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
17411f5d5d98SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1742b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
17431f5d5d98SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
17441f5d5d98SAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
17451f5d5d98SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
17461f5d5d98SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
17471f5d5d98SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
17481f5d5d98SAntoine Tenart 				.cra_module = THIS_MODULE,
17491f5d5d98SAntoine Tenart 			},
17501f5d5d98SAntoine Tenart 		},
17511f5d5d98SAntoine Tenart 	},
17521f5d5d98SAntoine Tenart };
1753293f89cfSOfer Heifetz 
safexcel_md5_init(struct ahash_request * areq)1754293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq)
1755293f89cfSOfer Heifetz {
1756293f89cfSOfer Heifetz 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1757b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
1758293f89cfSOfer Heifetz 
1759293f89cfSOfer Heifetz 	memset(req, 0, sizeof(*req));
1760293f89cfSOfer Heifetz 
1761293f89cfSOfer Heifetz 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
1762293f89cfSOfer Heifetz 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1763293f89cfSOfer Heifetz 	req->state_sz = MD5_DIGEST_SIZE;
17646c1c09b3SPascal van Leeuwen 	req->digest_sz = MD5_DIGEST_SIZE;
176541abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
1766293f89cfSOfer Heifetz 
1767293f89cfSOfer Heifetz 	return 0;
1768293f89cfSOfer Heifetz }
1769293f89cfSOfer Heifetz 
safexcel_md5_digest(struct ahash_request * areq)1770293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq)
1771293f89cfSOfer Heifetz {
1772293f89cfSOfer Heifetz 	int ret = safexcel_md5_init(areq);
1773293f89cfSOfer Heifetz 
1774293f89cfSOfer Heifetz 	if (ret)
1775293f89cfSOfer Heifetz 		return ret;
1776293f89cfSOfer Heifetz 
1777293f89cfSOfer Heifetz 	return safexcel_ahash_finup(areq);
1778293f89cfSOfer Heifetz }
1779293f89cfSOfer Heifetz 
1780293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = {
1781293f89cfSOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1782062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1783293f89cfSOfer Heifetz 	.alg.ahash = {
1784293f89cfSOfer Heifetz 		.init = safexcel_md5_init,
1785293f89cfSOfer Heifetz 		.update = safexcel_ahash_update,
1786293f89cfSOfer Heifetz 		.final = safexcel_ahash_final,
1787293f89cfSOfer Heifetz 		.finup = safexcel_ahash_finup,
1788293f89cfSOfer Heifetz 		.digest = safexcel_md5_digest,
1789293f89cfSOfer Heifetz 		.export = safexcel_ahash_export,
1790293f89cfSOfer Heifetz 		.import = safexcel_ahash_import,
1791293f89cfSOfer Heifetz 		.halg = {
1792293f89cfSOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1793293f89cfSOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1794293f89cfSOfer Heifetz 			.base = {
1795293f89cfSOfer Heifetz 				.cra_name = "md5",
1796293f89cfSOfer Heifetz 				.cra_driver_name = "safexcel-md5",
1797aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1798293f89cfSOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1799b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1800293f89cfSOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1801293f89cfSOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1802293f89cfSOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1803293f89cfSOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1804293f89cfSOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1805293f89cfSOfer Heifetz 				.cra_module = THIS_MODULE,
1806293f89cfSOfer Heifetz 			},
1807293f89cfSOfer Heifetz 		},
1808293f89cfSOfer Heifetz 	},
1809293f89cfSOfer Heifetz };
1810b471e4b9SOfer Heifetz 
safexcel_hmac_md5_init(struct ahash_request * areq)1811b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq)
1812b471e4b9SOfer Heifetz {
181341abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1814b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
1815b471e4b9SOfer Heifetz 
181641abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
181741abed7dSPascal van Leeuwen 
181841abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
181978cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, MD5_DIGEST_SIZE);
182041abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
182131fb084cSPascal van Leeuwen 	req->len	= MD5_HMAC_BLOCK_SIZE;
182231fb084cSPascal van Leeuwen 	req->processed	= MD5_HMAC_BLOCK_SIZE;
182341abed7dSPascal van Leeuwen 
182441abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
182541abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
182641abed7dSPascal van Leeuwen 	req->state_sz = MD5_DIGEST_SIZE;
18276c1c09b3SPascal van Leeuwen 	req->digest_sz = MD5_DIGEST_SIZE;
182841abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
182985b36ee8SPascal van Leeuwen 	req->len_is_le = true; /* MD5 is little endian! ... */
183041abed7dSPascal van Leeuwen 	req->hmac = true;
183141abed7dSPascal van Leeuwen 
1832b471e4b9SOfer Heifetz 	return 0;
1833b471e4b9SOfer Heifetz }
1834b471e4b9SOfer Heifetz 
safexcel_hmac_md5_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)1835b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key,
1836b471e4b9SOfer Heifetz 				     unsigned int keylen)
1837b471e4b9SOfer Heifetz {
1838b471e4b9SOfer Heifetz 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5",
1839b471e4b9SOfer Heifetz 					MD5_DIGEST_SIZE);
1840b471e4b9SOfer Heifetz }
1841b471e4b9SOfer Heifetz 
safexcel_hmac_md5_digest(struct ahash_request * areq)1842b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq)
1843b471e4b9SOfer Heifetz {
1844b471e4b9SOfer Heifetz 	int ret = safexcel_hmac_md5_init(areq);
1845b471e4b9SOfer Heifetz 
1846b471e4b9SOfer Heifetz 	if (ret)
1847b471e4b9SOfer Heifetz 		return ret;
1848b471e4b9SOfer Heifetz 
1849b471e4b9SOfer Heifetz 	return safexcel_ahash_finup(areq);
1850b471e4b9SOfer Heifetz }
1851b471e4b9SOfer Heifetz 
1852b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = {
1853b471e4b9SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1854062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1855b471e4b9SOfer Heifetz 	.alg.ahash = {
1856b471e4b9SOfer Heifetz 		.init = safexcel_hmac_md5_init,
1857b471e4b9SOfer Heifetz 		.update = safexcel_ahash_update,
1858b471e4b9SOfer Heifetz 		.final = safexcel_ahash_final,
1859b471e4b9SOfer Heifetz 		.finup = safexcel_ahash_finup,
1860b471e4b9SOfer Heifetz 		.digest = safexcel_hmac_md5_digest,
1861b471e4b9SOfer Heifetz 		.setkey = safexcel_hmac_md5_setkey,
1862b471e4b9SOfer Heifetz 		.export = safexcel_ahash_export,
1863b471e4b9SOfer Heifetz 		.import = safexcel_ahash_import,
1864b471e4b9SOfer Heifetz 		.halg = {
1865b471e4b9SOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1866b471e4b9SOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1867b471e4b9SOfer Heifetz 			.base = {
1868b471e4b9SOfer Heifetz 				.cra_name = "hmac(md5)",
1869b471e4b9SOfer Heifetz 				.cra_driver_name = "safexcel-hmac-md5",
1870aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1871b471e4b9SOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1872b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1873b471e4b9SOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1874b471e4b9SOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1875b471e4b9SOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1876b471e4b9SOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1877b471e4b9SOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1878b471e4b9SOfer Heifetz 				.cra_module = THIS_MODULE,
1879b471e4b9SOfer Heifetz 			},
1880b471e4b9SOfer Heifetz 		},
1881b471e4b9SOfer Heifetz 	},
1882b471e4b9SOfer Heifetz };
1883a7cf8658SPascal van Leeuwen 
safexcel_crc32_cra_init(struct crypto_tfm * tfm)1884a7cf8658SPascal van Leeuwen static int safexcel_crc32_cra_init(struct crypto_tfm *tfm)
1885a7cf8658SPascal van Leeuwen {
1886a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
1887a7cf8658SPascal van Leeuwen 	int ret = safexcel_ahash_cra_init(tfm);
1888a7cf8658SPascal van Leeuwen 
1889a7cf8658SPascal van Leeuwen 	/* Default 'key' is all zeroes */
189078cf1c8bSHerbert Xu 	memset(&ctx->base.ipad, 0, sizeof(u32));
1891a7cf8658SPascal van Leeuwen 	return ret;
1892a7cf8658SPascal van Leeuwen }
1893a7cf8658SPascal van Leeuwen 
safexcel_crc32_init(struct ahash_request * areq)1894a7cf8658SPascal van Leeuwen static int safexcel_crc32_init(struct ahash_request *areq)
1895a7cf8658SPascal van Leeuwen {
1896a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1897b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
1898a7cf8658SPascal van Leeuwen 
1899a7cf8658SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1900a7cf8658SPascal van Leeuwen 
1901a7cf8658SPascal van Leeuwen 	/* Start from loaded key */
190278cf1c8bSHerbert Xu 	req->state[0]	= cpu_to_le32(~ctx->base.ipad.word[0]);
1903a7cf8658SPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
1904a7cf8658SPascal van Leeuwen 	req->len	= sizeof(u32);
1905a7cf8658SPascal van Leeuwen 	req->processed	= sizeof(u32);
1906a7cf8658SPascal van Leeuwen 
1907a7cf8658SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32;
1908a7cf8658SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_XCM;
1909a7cf8658SPascal van Leeuwen 	req->state_sz = sizeof(u32);
19106c1c09b3SPascal van Leeuwen 	req->digest_sz = sizeof(u32);
1911a7cf8658SPascal van Leeuwen 	req->block_sz = sizeof(u32);
1912a7cf8658SPascal van Leeuwen 
1913a7cf8658SPascal van Leeuwen 	return 0;
1914a7cf8658SPascal van Leeuwen }
1915a7cf8658SPascal van Leeuwen 
safexcel_crc32_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)1916a7cf8658SPascal van Leeuwen static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key,
1917a7cf8658SPascal van Leeuwen 				 unsigned int keylen)
1918a7cf8658SPascal van Leeuwen {
1919a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1920a7cf8658SPascal van Leeuwen 
1921674f368aSEric Biggers 	if (keylen != sizeof(u32))
1922a7cf8658SPascal van Leeuwen 		return -EINVAL;
1923a7cf8658SPascal van Leeuwen 
192478cf1c8bSHerbert Xu 	memcpy(&ctx->base.ipad, key, sizeof(u32));
1925a7cf8658SPascal van Leeuwen 	return 0;
1926a7cf8658SPascal van Leeuwen }
1927a7cf8658SPascal van Leeuwen 
safexcel_crc32_digest(struct ahash_request * areq)1928a7cf8658SPascal van Leeuwen static int safexcel_crc32_digest(struct ahash_request *areq)
1929a7cf8658SPascal van Leeuwen {
1930a7cf8658SPascal van Leeuwen 	return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq);
1931a7cf8658SPascal van Leeuwen }
1932a7cf8658SPascal van Leeuwen 
1933a7cf8658SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_crc32 = {
1934a7cf8658SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1935a7cf8658SPascal van Leeuwen 	.algo_mask = 0,
1936a7cf8658SPascal van Leeuwen 	.alg.ahash = {
1937a7cf8658SPascal van Leeuwen 		.init = safexcel_crc32_init,
1938a7cf8658SPascal van Leeuwen 		.update = safexcel_ahash_update,
1939a7cf8658SPascal van Leeuwen 		.final = safexcel_ahash_final,
1940a7cf8658SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
1941a7cf8658SPascal van Leeuwen 		.digest = safexcel_crc32_digest,
1942a7cf8658SPascal van Leeuwen 		.setkey = safexcel_crc32_setkey,
1943a7cf8658SPascal van Leeuwen 		.export = safexcel_ahash_export,
1944a7cf8658SPascal van Leeuwen 		.import = safexcel_ahash_import,
1945a7cf8658SPascal van Leeuwen 		.halg = {
1946a7cf8658SPascal van Leeuwen 			.digestsize = sizeof(u32),
1947a7cf8658SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
1948a7cf8658SPascal van Leeuwen 			.base = {
1949a7cf8658SPascal van Leeuwen 				.cra_name = "crc32",
1950a7cf8658SPascal van Leeuwen 				.cra_driver_name = "safexcel-crc32",
1951a7cf8658SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1952a7cf8658SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_OPTIONAL_KEY |
1953a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_ASYNC |
1954b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
1955a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1956a7cf8658SPascal van Leeuwen 				.cra_blocksize = 1,
1957a7cf8658SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1958a7cf8658SPascal van Leeuwen 				.cra_init = safexcel_crc32_cra_init,
1959a7cf8658SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
1960a7cf8658SPascal van Leeuwen 				.cra_module = THIS_MODULE,
1961a7cf8658SPascal van Leeuwen 			},
1962a7cf8658SPascal van Leeuwen 		},
1963a7cf8658SPascal van Leeuwen 	},
1964a7cf8658SPascal van Leeuwen };
1965b98687bbSPascal van Leeuwen 
safexcel_cbcmac_init(struct ahash_request * areq)1966b98687bbSPascal van Leeuwen static int safexcel_cbcmac_init(struct ahash_request *areq)
1967b98687bbSPascal van Leeuwen {
1968b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1969b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
1970b98687bbSPascal van Leeuwen 
1971b98687bbSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1972b98687bbSPascal van Leeuwen 
1973b98687bbSPascal van Leeuwen 	/* Start from loaded keys */
197478cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, ctx->key_sz);
1975b98687bbSPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
1976b98687bbSPascal van Leeuwen 	req->len	= AES_BLOCK_SIZE;
1977b98687bbSPascal van Leeuwen 	req->processed	= AES_BLOCK_SIZE;
1978b98687bbSPascal van Leeuwen 
1979b98687bbSPascal van Leeuwen 	req->digest   = CONTEXT_CONTROL_DIGEST_XCM;
1980b98687bbSPascal van Leeuwen 	req->state_sz = ctx->key_sz;
19816c1c09b3SPascal van Leeuwen 	req->digest_sz = AES_BLOCK_SIZE;
1982b98687bbSPascal van Leeuwen 	req->block_sz = AES_BLOCK_SIZE;
1983b98687bbSPascal van Leeuwen 	req->xcbcmac  = true;
1984b98687bbSPascal van Leeuwen 
1985b98687bbSPascal van Leeuwen 	return 0;
1986b98687bbSPascal van Leeuwen }
1987b98687bbSPascal van Leeuwen 
safexcel_cbcmac_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int len)1988b98687bbSPascal van Leeuwen static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
1989b98687bbSPascal van Leeuwen 				 unsigned int len)
1990b98687bbSPascal van Leeuwen {
1991b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1992b98687bbSPascal van Leeuwen 	struct crypto_aes_ctx aes;
1993b98687bbSPascal van Leeuwen 	int ret, i;
1994b98687bbSPascal van Leeuwen 
1995b98687bbSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
1996674f368aSEric Biggers 	if (ret)
1997b98687bbSPascal van Leeuwen 		return ret;
1998b98687bbSPascal van Leeuwen 
199978cf1c8bSHerbert Xu 	memset(&ctx->base.ipad, 0, 2 * AES_BLOCK_SIZE);
2000b98687bbSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
200178cf1c8bSHerbert Xu 		ctx->base.ipad.be[i + 8] = cpu_to_be32(aes.key_enc[i]);
2002b98687bbSPascal van Leeuwen 
2003b98687bbSPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
2004b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
2005b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2006b98687bbSPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
2007b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
2008b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2009b98687bbSPascal van Leeuwen 	} else {
2010b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
2011b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
2012b98687bbSPascal van Leeuwen 	}
201338f21b4bSPascal van Leeuwen 	ctx->cbcmac  = true;
2014b98687bbSPascal van Leeuwen 
2015b98687bbSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
2016b98687bbSPascal van Leeuwen 	return 0;
2017b98687bbSPascal van Leeuwen }
2018b98687bbSPascal van Leeuwen 
safexcel_cbcmac_digest(struct ahash_request * areq)2019b98687bbSPascal van Leeuwen static int safexcel_cbcmac_digest(struct ahash_request *areq)
2020b98687bbSPascal van Leeuwen {
2021b98687bbSPascal van Leeuwen 	return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq);
2022b98687bbSPascal van Leeuwen }
2023b98687bbSPascal van Leeuwen 
2024b98687bbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbcmac = {
2025b98687bbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2026b98687bbSPascal van Leeuwen 	.algo_mask = 0,
2027b98687bbSPascal van Leeuwen 	.alg.ahash = {
2028b98687bbSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
2029b98687bbSPascal van Leeuwen 		.update = safexcel_ahash_update,
2030b98687bbSPascal van Leeuwen 		.final = safexcel_ahash_final,
2031b98687bbSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
2032b98687bbSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
2033b98687bbSPascal van Leeuwen 		.setkey = safexcel_cbcmac_setkey,
2034b98687bbSPascal van Leeuwen 		.export = safexcel_ahash_export,
2035b98687bbSPascal van Leeuwen 		.import = safexcel_ahash_import,
2036b98687bbSPascal van Leeuwen 		.halg = {
2037b98687bbSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
2038b98687bbSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2039b98687bbSPascal van Leeuwen 			.base = {
2040b98687bbSPascal van Leeuwen 				.cra_name = "cbcmac(aes)",
2041b98687bbSPascal van Leeuwen 				.cra_driver_name = "safexcel-cbcmac-aes",
2042b98687bbSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2043b98687bbSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2044b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
2045b98687bbSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
2046b98687bbSPascal van Leeuwen 				.cra_blocksize = 1,
2047b98687bbSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2048b98687bbSPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
2049b98687bbSPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
2050b98687bbSPascal van Leeuwen 				.cra_module = THIS_MODULE,
2051b98687bbSPascal van Leeuwen 			},
2052b98687bbSPascal van Leeuwen 		},
2053b98687bbSPascal van Leeuwen 	},
2054b98687bbSPascal van Leeuwen };
205538f21b4bSPascal van Leeuwen 
safexcel_xcbcmac_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int len)205638f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
205738f21b4bSPascal van Leeuwen 				 unsigned int len)
205838f21b4bSPascal van Leeuwen {
205938f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
206038f21b4bSPascal van Leeuwen 	u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)];
206138f21b4bSPascal van Leeuwen 	int ret, i;
206238f21b4bSPascal van Leeuwen 
2063320406cbSPeter Harliman Liem 	ret = aes_expandkey(ctx->aes, key, len);
2064674f368aSEric Biggers 	if (ret)
206538f21b4bSPascal van Leeuwen 		return ret;
206638f21b4bSPascal van Leeuwen 
206738f21b4bSPascal van Leeuwen 	/* precompute the XCBC key material */
2068320406cbSPeter Harliman Liem 	aes_encrypt(ctx->aes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
206938f21b4bSPascal van Leeuwen 		    "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1");
2070320406cbSPeter Harliman Liem 	aes_encrypt(ctx->aes, (u8 *)key_tmp,
207138f21b4bSPascal van Leeuwen 		    "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2");
2072320406cbSPeter Harliman Liem 	aes_encrypt(ctx->aes, (u8 *)key_tmp + AES_BLOCK_SIZE,
207338f21b4bSPascal van Leeuwen 		    "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3");
207438f21b4bSPascal van Leeuwen 	for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++)
207566459340SPeter Harliman Liem 		ctx->base.ipad.word[i] = swab32(key_tmp[i]);
207638f21b4bSPascal van Leeuwen 
2077320406cbSPeter Harliman Liem 	ret = aes_expandkey(ctx->aes,
207838f21b4bSPascal van Leeuwen 			    (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
207938f21b4bSPascal van Leeuwen 			    AES_MIN_KEY_SIZE);
208038f21b4bSPascal van Leeuwen 	if (ret)
208138f21b4bSPascal van Leeuwen 		return ret;
208238f21b4bSPascal van Leeuwen 
208338f21b4bSPascal van Leeuwen 	ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
208438f21b4bSPascal van Leeuwen 	ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
208538f21b4bSPascal van Leeuwen 	ctx->cbcmac = false;
208638f21b4bSPascal van Leeuwen 
208738f21b4bSPascal van Leeuwen 	return 0;
208838f21b4bSPascal van Leeuwen }
208938f21b4bSPascal van Leeuwen 
safexcel_xcbcmac_cra_init(struct crypto_tfm * tfm)209038f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm)
209138f21b4bSPascal van Leeuwen {
209238f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
209338f21b4bSPascal van Leeuwen 
209438f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_init(tfm);
2095320406cbSPeter Harliman Liem 	ctx->aes = kmalloc(sizeof(*ctx->aes), GFP_KERNEL);
2096320406cbSPeter Harliman Liem 	return PTR_ERR_OR_ZERO(ctx->aes);
209738f21b4bSPascal van Leeuwen }
209838f21b4bSPascal van Leeuwen 
safexcel_xcbcmac_cra_exit(struct crypto_tfm * tfm)209938f21b4bSPascal van Leeuwen static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm)
210038f21b4bSPascal van Leeuwen {
210138f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
210238f21b4bSPascal van Leeuwen 
2103320406cbSPeter Harliman Liem 	kfree(ctx->aes);
210438f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
210538f21b4bSPascal van Leeuwen }
210638f21b4bSPascal van Leeuwen 
210738f21b4bSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xcbcmac = {
210838f21b4bSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
210938f21b4bSPascal van Leeuwen 	.algo_mask = 0,
211038f21b4bSPascal van Leeuwen 	.alg.ahash = {
211138f21b4bSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
211238f21b4bSPascal van Leeuwen 		.update = safexcel_ahash_update,
211338f21b4bSPascal van Leeuwen 		.final = safexcel_ahash_final,
211438f21b4bSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
211538f21b4bSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
211638f21b4bSPascal van Leeuwen 		.setkey = safexcel_xcbcmac_setkey,
211738f21b4bSPascal van Leeuwen 		.export = safexcel_ahash_export,
211838f21b4bSPascal van Leeuwen 		.import = safexcel_ahash_import,
211938f21b4bSPascal van Leeuwen 		.halg = {
212038f21b4bSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
212138f21b4bSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
212238f21b4bSPascal van Leeuwen 			.base = {
212338f21b4bSPascal van Leeuwen 				.cra_name = "xcbc(aes)",
212438f21b4bSPascal van Leeuwen 				.cra_driver_name = "safexcel-xcbc-aes",
212538f21b4bSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
212638f21b4bSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2127b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
212838f21b4bSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
212938f21b4bSPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
213038f21b4bSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
213138f21b4bSPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
213238f21b4bSPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
213338f21b4bSPascal van Leeuwen 				.cra_module = THIS_MODULE,
213438f21b4bSPascal van Leeuwen 			},
213538f21b4bSPascal van Leeuwen 		},
213638f21b4bSPascal van Leeuwen 	},
213738f21b4bSPascal van Leeuwen };
21387a627db9SPascal van Leeuwen 
safexcel_cmac_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int len)21397a627db9SPascal van Leeuwen static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
21407a627db9SPascal van Leeuwen 				unsigned int len)
21417a627db9SPascal van Leeuwen {
21427a627db9SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
21437a627db9SPascal van Leeuwen 	__be64 consts[4];
21447a627db9SPascal van Leeuwen 	u64 _const[2];
21457a627db9SPascal van Leeuwen 	u8 msb_mask, gfmask;
21467a627db9SPascal van Leeuwen 	int ret, i;
21477a627db9SPascal van Leeuwen 
2148320406cbSPeter Harliman Liem 	/* precompute the CMAC key material */
2149320406cbSPeter Harliman Liem 	ret = aes_expandkey(ctx->aes, key, len);
2150674f368aSEric Biggers 	if (ret)
21517a627db9SPascal van Leeuwen 		return ret;
21527a627db9SPascal van Leeuwen 
21537a627db9SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
2154320406cbSPeter Harliman Liem 		ctx->base.ipad.word[i + 8] = swab32(ctx->aes->key_enc[i]);
21557a627db9SPascal van Leeuwen 
21567a627db9SPascal van Leeuwen 	/* code below borrowed from crypto/cmac.c */
21577a627db9SPascal van Leeuwen 	/* encrypt the zero block */
21587a627db9SPascal van Leeuwen 	memset(consts, 0, AES_BLOCK_SIZE);
2159320406cbSPeter Harliman Liem 	aes_encrypt(ctx->aes, (u8 *)consts, (u8 *)consts);
21607a627db9SPascal van Leeuwen 
21617a627db9SPascal van Leeuwen 	gfmask = 0x87;
21627a627db9SPascal van Leeuwen 	_const[0] = be64_to_cpu(consts[1]);
21637a627db9SPascal van Leeuwen 	_const[1] = be64_to_cpu(consts[0]);
21647a627db9SPascal van Leeuwen 
21657a627db9SPascal van Leeuwen 	/* gf(2^128) multiply zero-ciphertext with u and u^2 */
21667a627db9SPascal van Leeuwen 	for (i = 0; i < 4; i += 2) {
21677a627db9SPascal van Leeuwen 		msb_mask = ((s64)_const[1] >> 63) & gfmask;
21687a627db9SPascal van Leeuwen 		_const[1] = (_const[1] << 1) | (_const[0] >> 63);
21697a627db9SPascal van Leeuwen 		_const[0] = (_const[0] << 1) ^ msb_mask;
21707a627db9SPascal van Leeuwen 
21717a627db9SPascal van Leeuwen 		consts[i + 0] = cpu_to_be64(_const[1]);
21727a627db9SPascal van Leeuwen 		consts[i + 1] = cpu_to_be64(_const[0]);
21737a627db9SPascal van Leeuwen 	}
21747a627db9SPascal van Leeuwen 	/* end of code borrowed from crypto/cmac.c */
21757a627db9SPascal van Leeuwen 
21767a627db9SPascal van Leeuwen 	for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++)
217778cf1c8bSHerbert Xu 		ctx->base.ipad.be[i] = cpu_to_be32(((u32 *)consts)[i]);
21787a627db9SPascal van Leeuwen 
21797a627db9SPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
21807a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
21817a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
21827a627db9SPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
21837a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
21847a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
21857a627db9SPascal van Leeuwen 	} else {
21867a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
21877a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
21887a627db9SPascal van Leeuwen 	}
21897a627db9SPascal van Leeuwen 	ctx->cbcmac = false;
21907a627db9SPascal van Leeuwen 
21917a627db9SPascal van Leeuwen 	return 0;
21927a627db9SPascal van Leeuwen }
21937a627db9SPascal van Leeuwen 
21947a627db9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cmac = {
21957a627db9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
21967a627db9SPascal van Leeuwen 	.algo_mask = 0,
21977a627db9SPascal van Leeuwen 	.alg.ahash = {
21987a627db9SPascal van Leeuwen 		.init = safexcel_cbcmac_init,
21997a627db9SPascal van Leeuwen 		.update = safexcel_ahash_update,
22007a627db9SPascal van Leeuwen 		.final = safexcel_ahash_final,
22017a627db9SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22027a627db9SPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
22037a627db9SPascal van Leeuwen 		.setkey = safexcel_cmac_setkey,
22047a627db9SPascal van Leeuwen 		.export = safexcel_ahash_export,
22057a627db9SPascal van Leeuwen 		.import = safexcel_ahash_import,
22067a627db9SPascal van Leeuwen 		.halg = {
22077a627db9SPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
22087a627db9SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
22097a627db9SPascal van Leeuwen 			.base = {
22107a627db9SPascal van Leeuwen 				.cra_name = "cmac(aes)",
22117a627db9SPascal van Leeuwen 				.cra_driver_name = "safexcel-cmac-aes",
22127a627db9SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
22137a627db9SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2214b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
22157a627db9SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
22167a627db9SPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
22177a627db9SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
22187a627db9SPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
22197a627db9SPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
22207a627db9SPascal van Leeuwen 				.cra_module = THIS_MODULE,
22217a627db9SPascal van Leeuwen 			},
22227a627db9SPascal van Leeuwen 		},
22237a627db9SPascal van Leeuwen 	},
22247a627db9SPascal van Leeuwen };
22250f2bc131SPascal van Leeuwen 
safexcel_sm3_init(struct ahash_request * areq)22260f2bc131SPascal van Leeuwen static int safexcel_sm3_init(struct ahash_request *areq)
22270f2bc131SPascal van Leeuwen {
22280f2bc131SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
2229b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
22300f2bc131SPascal van Leeuwen 
22310f2bc131SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
22320f2bc131SPascal van Leeuwen 
22330f2bc131SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
22340f2bc131SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
22350f2bc131SPascal van Leeuwen 	req->state_sz = SM3_DIGEST_SIZE;
22366c1c09b3SPascal van Leeuwen 	req->digest_sz = SM3_DIGEST_SIZE;
22370f2bc131SPascal van Leeuwen 	req->block_sz = SM3_BLOCK_SIZE;
22380f2bc131SPascal van Leeuwen 
22390f2bc131SPascal van Leeuwen 	return 0;
22400f2bc131SPascal van Leeuwen }
22410f2bc131SPascal van Leeuwen 
safexcel_sm3_digest(struct ahash_request * areq)22420f2bc131SPascal van Leeuwen static int safexcel_sm3_digest(struct ahash_request *areq)
22430f2bc131SPascal van Leeuwen {
22440f2bc131SPascal van Leeuwen 	int ret = safexcel_sm3_init(areq);
22450f2bc131SPascal van Leeuwen 
22460f2bc131SPascal van Leeuwen 	if (ret)
22470f2bc131SPascal van Leeuwen 		return ret;
22480f2bc131SPascal van Leeuwen 
22490f2bc131SPascal van Leeuwen 	return safexcel_ahash_finup(areq);
22500f2bc131SPascal van Leeuwen }
22510f2bc131SPascal van Leeuwen 
22520f2bc131SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sm3 = {
22530f2bc131SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
22540f2bc131SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM3,
22550f2bc131SPascal van Leeuwen 	.alg.ahash = {
22560f2bc131SPascal van Leeuwen 		.init = safexcel_sm3_init,
22570f2bc131SPascal van Leeuwen 		.update = safexcel_ahash_update,
22580f2bc131SPascal van Leeuwen 		.final = safexcel_ahash_final,
22590f2bc131SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22600f2bc131SPascal van Leeuwen 		.digest = safexcel_sm3_digest,
22610f2bc131SPascal van Leeuwen 		.export = safexcel_ahash_export,
22620f2bc131SPascal van Leeuwen 		.import = safexcel_ahash_import,
22630f2bc131SPascal van Leeuwen 		.halg = {
22640f2bc131SPascal van Leeuwen 			.digestsize = SM3_DIGEST_SIZE,
22650f2bc131SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
22660f2bc131SPascal van Leeuwen 			.base = {
22670f2bc131SPascal van Leeuwen 				.cra_name = "sm3",
22680f2bc131SPascal van Leeuwen 				.cra_driver_name = "safexcel-sm3",
22690f2bc131SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
22700f2bc131SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2271b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
22720f2bc131SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
22730f2bc131SPascal van Leeuwen 				.cra_blocksize = SM3_BLOCK_SIZE,
22740f2bc131SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
22750f2bc131SPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
22760f2bc131SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
22770f2bc131SPascal van Leeuwen 				.cra_module = THIS_MODULE,
22780f2bc131SPascal van Leeuwen 			},
22790f2bc131SPascal van Leeuwen 		},
22800f2bc131SPascal van Leeuwen 	},
22810f2bc131SPascal van Leeuwen };
2282aa3a43e6SPascal van Leeuwen 
safexcel_hmac_sm3_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)2283aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key,
2284aa3a43e6SPascal van Leeuwen 				    unsigned int keylen)
2285aa3a43e6SPascal van Leeuwen {
2286aa3a43e6SPascal van Leeuwen 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3",
2287aa3a43e6SPascal van Leeuwen 					SM3_DIGEST_SIZE);
2288aa3a43e6SPascal van Leeuwen }
2289aa3a43e6SPascal van Leeuwen 
safexcel_hmac_sm3_init(struct ahash_request * areq)2290aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_init(struct ahash_request *areq)
2291aa3a43e6SPascal van Leeuwen {
2292aa3a43e6SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
2293b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
2294aa3a43e6SPascal van Leeuwen 
2295aa3a43e6SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2296aa3a43e6SPascal van Leeuwen 
2297aa3a43e6SPascal van Leeuwen 	/* Start from ipad precompute */
229878cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SM3_DIGEST_SIZE);
2299aa3a43e6SPascal van Leeuwen 	/* Already processed the key^ipad part now! */
2300aa3a43e6SPascal van Leeuwen 	req->len	= SM3_BLOCK_SIZE;
2301aa3a43e6SPascal van Leeuwen 	req->processed	= SM3_BLOCK_SIZE;
2302aa3a43e6SPascal van Leeuwen 
2303aa3a43e6SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
2304aa3a43e6SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
2305aa3a43e6SPascal van Leeuwen 	req->state_sz = SM3_DIGEST_SIZE;
23066c1c09b3SPascal van Leeuwen 	req->digest_sz = SM3_DIGEST_SIZE;
2307aa3a43e6SPascal van Leeuwen 	req->block_sz = SM3_BLOCK_SIZE;
2308aa3a43e6SPascal van Leeuwen 	req->hmac = true;
2309aa3a43e6SPascal van Leeuwen 
2310aa3a43e6SPascal van Leeuwen 	return 0;
2311aa3a43e6SPascal van Leeuwen }
2312aa3a43e6SPascal van Leeuwen 
safexcel_hmac_sm3_digest(struct ahash_request * areq)2313aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_digest(struct ahash_request *areq)
2314aa3a43e6SPascal van Leeuwen {
2315aa3a43e6SPascal van Leeuwen 	int ret = safexcel_hmac_sm3_init(areq);
2316aa3a43e6SPascal van Leeuwen 
2317aa3a43e6SPascal van Leeuwen 	if (ret)
2318aa3a43e6SPascal van Leeuwen 		return ret;
2319aa3a43e6SPascal van Leeuwen 
2320aa3a43e6SPascal van Leeuwen 	return safexcel_ahash_finup(areq);
2321aa3a43e6SPascal van Leeuwen }
2322aa3a43e6SPascal van Leeuwen 
2323aa3a43e6SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sm3 = {
2324aa3a43e6SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2325aa3a43e6SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM3,
2326aa3a43e6SPascal van Leeuwen 	.alg.ahash = {
2327aa3a43e6SPascal van Leeuwen 		.init = safexcel_hmac_sm3_init,
2328aa3a43e6SPascal van Leeuwen 		.update = safexcel_ahash_update,
2329aa3a43e6SPascal van Leeuwen 		.final = safexcel_ahash_final,
2330aa3a43e6SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
2331aa3a43e6SPascal van Leeuwen 		.digest = safexcel_hmac_sm3_digest,
2332aa3a43e6SPascal van Leeuwen 		.setkey = safexcel_hmac_sm3_setkey,
2333aa3a43e6SPascal van Leeuwen 		.export = safexcel_ahash_export,
2334aa3a43e6SPascal van Leeuwen 		.import = safexcel_ahash_import,
2335aa3a43e6SPascal van Leeuwen 		.halg = {
2336aa3a43e6SPascal van Leeuwen 			.digestsize = SM3_DIGEST_SIZE,
2337aa3a43e6SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2338aa3a43e6SPascal van Leeuwen 			.base = {
2339aa3a43e6SPascal van Leeuwen 				.cra_name = "hmac(sm3)",
2340aa3a43e6SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sm3",
2341aa3a43e6SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2342aa3a43e6SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2343b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY |
2344aa3a43e6SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
2345aa3a43e6SPascal van Leeuwen 				.cra_blocksize = SM3_BLOCK_SIZE,
2346aa3a43e6SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2347aa3a43e6SPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
2348aa3a43e6SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
2349aa3a43e6SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2350aa3a43e6SPascal van Leeuwen 			},
2351aa3a43e6SPascal van Leeuwen 		},
2352aa3a43e6SPascal van Leeuwen 	},
2353aa3a43e6SPascal van Leeuwen };
2354aaf5a383SPascal van Leeuwen 
safexcel_sha3_224_init(struct ahash_request * areq)2355aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_init(struct ahash_request *areq)
2356aaf5a383SPascal van Leeuwen {
2357aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2358aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2359b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
2360aaf5a383SPascal van Leeuwen 
2361aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2362aaf5a383SPascal van Leeuwen 
2363aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
2364aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2365aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_224_DIGEST_SIZE;
23666c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_224_DIGEST_SIZE;
2367aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_224_BLOCK_SIZE;
2368aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2369aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2370aaf5a383SPascal van Leeuwen 	return 0;
2371aaf5a383SPascal van Leeuwen }
2372aaf5a383SPascal van Leeuwen 
safexcel_sha3_fbcheck(struct ahash_request * req)2373aaf5a383SPascal van Leeuwen static int safexcel_sha3_fbcheck(struct ahash_request *req)
2374aaf5a383SPascal van Leeuwen {
2375aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2376aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2377b2e2e2daSHerbert Xu 	struct ahash_request *subreq = ahash_request_ctx_dma(req);
2378aaf5a383SPascal van Leeuwen 	int ret = 0;
2379aaf5a383SPascal van Leeuwen 
2380aaf5a383SPascal van Leeuwen 	if (ctx->do_fallback) {
2381aaf5a383SPascal van Leeuwen 		ahash_request_set_tfm(subreq, ctx->fback);
2382aaf5a383SPascal van Leeuwen 		ahash_request_set_callback(subreq, req->base.flags,
2383aaf5a383SPascal van Leeuwen 					   req->base.complete, req->base.data);
2384aaf5a383SPascal van Leeuwen 		ahash_request_set_crypt(subreq, req->src, req->result,
2385aaf5a383SPascal van Leeuwen 					req->nbytes);
2386aaf5a383SPascal van Leeuwen 		if (!ctx->fb_init_done) {
23876c1c09b3SPascal van Leeuwen 			if (ctx->fb_do_setkey) {
23886c1c09b3SPascal van Leeuwen 				/* Set fallback cipher HMAC key */
23896c1c09b3SPascal van Leeuwen 				u8 key[SHA3_224_BLOCK_SIZE];
23906c1c09b3SPascal van Leeuwen 
239178cf1c8bSHerbert Xu 				memcpy(key, &ctx->base.ipad,
23926c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2);
23936c1c09b3SPascal van Leeuwen 				memcpy(key +
23946c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2,
239578cf1c8bSHerbert Xu 				       &ctx->base.opad,
23966c1c09b3SPascal van Leeuwen 				       crypto_ahash_blocksize(ctx->fback) / 2);
23976c1c09b3SPascal van Leeuwen 				ret = crypto_ahash_setkey(ctx->fback, key,
23986c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(ctx->fback));
23996c1c09b3SPascal van Leeuwen 				memzero_explicit(key,
24006c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(ctx->fback));
24016c1c09b3SPascal van Leeuwen 				ctx->fb_do_setkey = false;
24026c1c09b3SPascal van Leeuwen 			}
24036c1c09b3SPascal van Leeuwen 			ret = ret ?: crypto_ahash_init(subreq);
2404aaf5a383SPascal van Leeuwen 			ctx->fb_init_done = true;
2405aaf5a383SPascal van Leeuwen 		}
2406aaf5a383SPascal van Leeuwen 	}
2407aaf5a383SPascal van Leeuwen 	return ret;
2408aaf5a383SPascal van Leeuwen }
2409aaf5a383SPascal van Leeuwen 
safexcel_sha3_update(struct ahash_request * req)2410aaf5a383SPascal van Leeuwen static int safexcel_sha3_update(struct ahash_request *req)
2411aaf5a383SPascal van Leeuwen {
2412aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2413aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2414b2e2e2daSHerbert Xu 	struct ahash_request *subreq = ahash_request_ctx_dma(req);
2415aaf5a383SPascal van Leeuwen 
2416aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2417aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq);
2418aaf5a383SPascal van Leeuwen }
2419aaf5a383SPascal van Leeuwen 
safexcel_sha3_final(struct ahash_request * req)2420aaf5a383SPascal van Leeuwen static int safexcel_sha3_final(struct ahash_request *req)
2421aaf5a383SPascal van Leeuwen {
2422aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2423aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2424b2e2e2daSHerbert Xu 	struct ahash_request *subreq = ahash_request_ctx_dma(req);
2425aaf5a383SPascal van Leeuwen 
2426aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2427aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq);
2428aaf5a383SPascal van Leeuwen }
2429aaf5a383SPascal van Leeuwen 
safexcel_sha3_finup(struct ahash_request * req)2430aaf5a383SPascal van Leeuwen static int safexcel_sha3_finup(struct ahash_request *req)
2431aaf5a383SPascal van Leeuwen {
2432aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2433aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2434b2e2e2daSHerbert Xu 	struct ahash_request *subreq = ahash_request_ctx_dma(req);
2435aaf5a383SPascal van Leeuwen 
2436aaf5a383SPascal van Leeuwen 	ctx->do_fallback |= !req->nbytes;
2437aaf5a383SPascal van Leeuwen 	if (ctx->do_fallback)
2438aaf5a383SPascal van Leeuwen 		/* Update or ex/import happened or len 0, cannot use the HW */
2439aaf5a383SPascal van Leeuwen 		return safexcel_sha3_fbcheck(req) ?:
2440aaf5a383SPascal van Leeuwen 		       crypto_ahash_finup(subreq);
2441aaf5a383SPascal van Leeuwen 	else
2442aaf5a383SPascal van Leeuwen 		return safexcel_ahash_finup(req);
2443aaf5a383SPascal van Leeuwen }
2444aaf5a383SPascal van Leeuwen 
safexcel_sha3_digest_fallback(struct ahash_request * req)2445aaf5a383SPascal van Leeuwen static int safexcel_sha3_digest_fallback(struct ahash_request *req)
2446aaf5a383SPascal van Leeuwen {
2447aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2448aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2449b2e2e2daSHerbert Xu 	struct ahash_request *subreq = ahash_request_ctx_dma(req);
2450aaf5a383SPascal van Leeuwen 
2451aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2452aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2453aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq);
2454aaf5a383SPascal van Leeuwen }
2455aaf5a383SPascal van Leeuwen 
safexcel_sha3_224_digest(struct ahash_request * req)2456aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_digest(struct ahash_request *req)
2457aaf5a383SPascal van Leeuwen {
2458aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2459aaf5a383SPascal van Leeuwen 		return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req);
2460aaf5a383SPascal van Leeuwen 
2461aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2462aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2463aaf5a383SPascal van Leeuwen }
2464aaf5a383SPascal van Leeuwen 
safexcel_sha3_export(struct ahash_request * req,void * out)2465aaf5a383SPascal van Leeuwen static int safexcel_sha3_export(struct ahash_request *req, void *out)
2466aaf5a383SPascal van Leeuwen {
2467aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2468aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2469b2e2e2daSHerbert Xu 	struct ahash_request *subreq = ahash_request_ctx_dma(req);
2470aaf5a383SPascal van Leeuwen 
2471aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2472aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out);
2473aaf5a383SPascal van Leeuwen }
2474aaf5a383SPascal van Leeuwen 
safexcel_sha3_import(struct ahash_request * req,const void * in)2475aaf5a383SPascal van Leeuwen static int safexcel_sha3_import(struct ahash_request *req, const void *in)
2476aaf5a383SPascal van Leeuwen {
2477aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
2478aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2479b2e2e2daSHerbert Xu 	struct ahash_request *subreq = ahash_request_ctx_dma(req);
2480aaf5a383SPascal van Leeuwen 
2481aaf5a383SPascal van Leeuwen 	ctx->do_fallback = true;
2482aaf5a383SPascal van Leeuwen 	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in);
2483aaf5a383SPascal van Leeuwen 	// return safexcel_ahash_import(req, in);
2484aaf5a383SPascal van Leeuwen }
2485aaf5a383SPascal van Leeuwen 
safexcel_sha3_cra_init(struct crypto_tfm * tfm)2486aaf5a383SPascal van Leeuwen static int safexcel_sha3_cra_init(struct crypto_tfm *tfm)
2487aaf5a383SPascal van Leeuwen {
2488aaf5a383SPascal van Leeuwen 	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
2489aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
2490aaf5a383SPascal van Leeuwen 
2491aaf5a383SPascal van Leeuwen 	safexcel_ahash_cra_init(tfm);
2492aaf5a383SPascal van Leeuwen 
2493aaf5a383SPascal van Leeuwen 	/* Allocate fallback implementation */
2494aaf5a383SPascal van Leeuwen 	ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0,
2495aaf5a383SPascal van Leeuwen 					CRYPTO_ALG_ASYNC |
2496aaf5a383SPascal van Leeuwen 					CRYPTO_ALG_NEED_FALLBACK);
2497aaf5a383SPascal van Leeuwen 	if (IS_ERR(ctx->fback))
2498aaf5a383SPascal van Leeuwen 		return PTR_ERR(ctx->fback);
2499aaf5a383SPascal van Leeuwen 
2500aaf5a383SPascal van Leeuwen 	/* Update statesize from fallback algorithm! */
2501aaf5a383SPascal van Leeuwen 	crypto_hash_alg_common(ahash)->statesize =
2502aaf5a383SPascal van Leeuwen 		crypto_ahash_statesize(ctx->fback);
2503b2e2e2daSHerbert Xu 	crypto_ahash_set_reqsize_dma(
2504b2e2e2daSHerbert Xu 		ahash, max(sizeof(struct safexcel_ahash_req),
2505aaf5a383SPascal van Leeuwen 			   sizeof(struct ahash_request) +
2506aaf5a383SPascal van Leeuwen 			   crypto_ahash_reqsize(ctx->fback)));
2507aaf5a383SPascal van Leeuwen 	return 0;
2508aaf5a383SPascal van Leeuwen }
2509aaf5a383SPascal van Leeuwen 
safexcel_sha3_cra_exit(struct crypto_tfm * tfm)2510aaf5a383SPascal van Leeuwen static void safexcel_sha3_cra_exit(struct crypto_tfm *tfm)
2511aaf5a383SPascal van Leeuwen {
2512aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
2513aaf5a383SPascal van Leeuwen 
2514aaf5a383SPascal van Leeuwen 	crypto_free_ahash(ctx->fback);
2515aaf5a383SPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
2516aaf5a383SPascal van Leeuwen }
2517aaf5a383SPascal van Leeuwen 
2518aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_224 = {
2519aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2520aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2521aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2522aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_224_init,
2523aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2524aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2525aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2526aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_224_digest,
2527aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2528aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2529aaf5a383SPascal van Leeuwen 		.halg = {
2530aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_224_DIGEST_SIZE,
2531aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2532aaf5a383SPascal van Leeuwen 			.base = {
2533aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-224",
2534aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-224",
2535aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2536aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2537aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2538aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2539aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_224_BLOCK_SIZE,
2540aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2541aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2542aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2543aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2544aaf5a383SPascal van Leeuwen 			},
2545aaf5a383SPascal van Leeuwen 		},
2546aaf5a383SPascal van Leeuwen 	},
2547aaf5a383SPascal van Leeuwen };
2548aaf5a383SPascal van Leeuwen 
safexcel_sha3_256_init(struct ahash_request * areq)2549aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_init(struct ahash_request *areq)
2550aaf5a383SPascal van Leeuwen {
2551aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2552aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2553b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
2554aaf5a383SPascal van Leeuwen 
2555aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2556aaf5a383SPascal van Leeuwen 
2557aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
2558aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2559aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_256_DIGEST_SIZE;
25606c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_256_DIGEST_SIZE;
2561aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_256_BLOCK_SIZE;
2562aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2563aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2564aaf5a383SPascal van Leeuwen 	return 0;
2565aaf5a383SPascal van Leeuwen }
2566aaf5a383SPascal van Leeuwen 
safexcel_sha3_256_digest(struct ahash_request * req)2567aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_digest(struct ahash_request *req)
2568aaf5a383SPascal van Leeuwen {
2569aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2570aaf5a383SPascal van Leeuwen 		return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req);
2571aaf5a383SPascal van Leeuwen 
2572aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2573aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2574aaf5a383SPascal van Leeuwen }
2575aaf5a383SPascal van Leeuwen 
2576aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_256 = {
2577aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2578aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2579aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2580aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_256_init,
2581aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2582aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2583aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2584aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_256_digest,
2585aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2586aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2587aaf5a383SPascal van Leeuwen 		.halg = {
2588aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_256_DIGEST_SIZE,
2589aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2590aaf5a383SPascal van Leeuwen 			.base = {
2591aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-256",
2592aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-256",
2593aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2594aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2595aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2596aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2597aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_256_BLOCK_SIZE,
2598aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2599aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2600aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2601aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2602aaf5a383SPascal van Leeuwen 			},
2603aaf5a383SPascal van Leeuwen 		},
2604aaf5a383SPascal van Leeuwen 	},
2605aaf5a383SPascal van Leeuwen };
2606aaf5a383SPascal van Leeuwen 
safexcel_sha3_384_init(struct ahash_request * areq)2607aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_init(struct ahash_request *areq)
2608aaf5a383SPascal van Leeuwen {
2609aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2610aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2611b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
2612aaf5a383SPascal van Leeuwen 
2613aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2614aaf5a383SPascal van Leeuwen 
2615aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
2616aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2617aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_384_DIGEST_SIZE;
26186c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_384_DIGEST_SIZE;
2619aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_384_BLOCK_SIZE;
2620aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2621aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2622aaf5a383SPascal van Leeuwen 	return 0;
2623aaf5a383SPascal van Leeuwen }
2624aaf5a383SPascal van Leeuwen 
safexcel_sha3_384_digest(struct ahash_request * req)2625aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_digest(struct ahash_request *req)
2626aaf5a383SPascal van Leeuwen {
2627aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2628aaf5a383SPascal van Leeuwen 		return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req);
2629aaf5a383SPascal van Leeuwen 
2630aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2631aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2632aaf5a383SPascal van Leeuwen }
2633aaf5a383SPascal van Leeuwen 
2634aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_384 = {
2635aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2636aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2637aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2638aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_384_init,
2639aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2640aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2641aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2642aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_384_digest,
2643aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2644aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2645aaf5a383SPascal van Leeuwen 		.halg = {
2646aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_384_DIGEST_SIZE,
2647aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2648aaf5a383SPascal van Leeuwen 			.base = {
2649aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-384",
2650aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-384",
2651aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2652aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2653aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2654aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2655aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_384_BLOCK_SIZE,
2656aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2657aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2658aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2659aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2660aaf5a383SPascal van Leeuwen 			},
2661aaf5a383SPascal van Leeuwen 		},
2662aaf5a383SPascal van Leeuwen 	},
2663aaf5a383SPascal van Leeuwen };
2664aaf5a383SPascal van Leeuwen 
safexcel_sha3_512_init(struct ahash_request * areq)2665aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_init(struct ahash_request *areq)
2666aaf5a383SPascal van Leeuwen {
2667aaf5a383SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2668aaf5a383SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2669b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
2670aaf5a383SPascal van Leeuwen 
2671aaf5a383SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
2672aaf5a383SPascal van Leeuwen 
2673aaf5a383SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
2674aaf5a383SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
2675aaf5a383SPascal van Leeuwen 	req->state_sz = SHA3_512_DIGEST_SIZE;
26766c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_512_DIGEST_SIZE;
2677aaf5a383SPascal van Leeuwen 	req->block_sz = SHA3_512_BLOCK_SIZE;
2678aaf5a383SPascal van Leeuwen 	ctx->do_fallback = false;
2679aaf5a383SPascal van Leeuwen 	ctx->fb_init_done = false;
2680aaf5a383SPascal van Leeuwen 	return 0;
2681aaf5a383SPascal van Leeuwen }
2682aaf5a383SPascal van Leeuwen 
safexcel_sha3_512_digest(struct ahash_request * req)2683aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_digest(struct ahash_request *req)
2684aaf5a383SPascal van Leeuwen {
2685aaf5a383SPascal van Leeuwen 	if (req->nbytes)
2686aaf5a383SPascal van Leeuwen 		return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req);
2687aaf5a383SPascal van Leeuwen 
2688aaf5a383SPascal van Leeuwen 	/* HW cannot do zero length hash, use fallback instead */
2689aaf5a383SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
2690aaf5a383SPascal van Leeuwen }
2691aaf5a383SPascal van Leeuwen 
2692aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_512 = {
2693aaf5a383SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2694aaf5a383SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
2695aaf5a383SPascal van Leeuwen 	.alg.ahash = {
2696aaf5a383SPascal van Leeuwen 		.init = safexcel_sha3_512_init,
2697aaf5a383SPascal van Leeuwen 		.update = safexcel_sha3_update,
2698aaf5a383SPascal van Leeuwen 		.final = safexcel_sha3_final,
2699aaf5a383SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
2700aaf5a383SPascal van Leeuwen 		.digest = safexcel_sha3_512_digest,
2701aaf5a383SPascal van Leeuwen 		.export = safexcel_sha3_export,
2702aaf5a383SPascal van Leeuwen 		.import = safexcel_sha3_import,
2703aaf5a383SPascal van Leeuwen 		.halg = {
2704aaf5a383SPascal van Leeuwen 			.digestsize = SHA3_512_DIGEST_SIZE,
2705aaf5a383SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2706aaf5a383SPascal van Leeuwen 			.base = {
2707aaf5a383SPascal van Leeuwen 				.cra_name = "sha3-512",
2708aaf5a383SPascal van Leeuwen 				.cra_driver_name = "safexcel-sha3-512",
2709aaf5a383SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2710aaf5a383SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2711aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
2712aaf5a383SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
2713aaf5a383SPascal van Leeuwen 				.cra_blocksize = SHA3_512_BLOCK_SIZE,
2714aaf5a383SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2715aaf5a383SPascal van Leeuwen 				.cra_init = safexcel_sha3_cra_init,
2716aaf5a383SPascal van Leeuwen 				.cra_exit = safexcel_sha3_cra_exit,
2717aaf5a383SPascal van Leeuwen 				.cra_module = THIS_MODULE,
2718aaf5a383SPascal van Leeuwen 			},
2719aaf5a383SPascal van Leeuwen 		},
2720aaf5a383SPascal van Leeuwen 	},
2721aaf5a383SPascal van Leeuwen };
27226c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_cra_init(struct crypto_tfm * tfm,const char * alg)27236c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg)
27246c1c09b3SPascal van Leeuwen {
27256c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
27266c1c09b3SPascal van Leeuwen 	int ret;
27276c1c09b3SPascal van Leeuwen 
27286c1c09b3SPascal van Leeuwen 	ret = safexcel_sha3_cra_init(tfm);
27296c1c09b3SPascal van Leeuwen 	if (ret)
27306c1c09b3SPascal van Leeuwen 		return ret;
27316c1c09b3SPascal van Leeuwen 
27326c1c09b3SPascal van Leeuwen 	/* Allocate precalc basic digest implementation */
27336c1c09b3SPascal van Leeuwen 	ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
27346c1c09b3SPascal van Leeuwen 	if (IS_ERR(ctx->shpre))
27356c1c09b3SPascal van Leeuwen 		return PTR_ERR(ctx->shpre);
27366c1c09b3SPascal van Leeuwen 
27376c1c09b3SPascal van Leeuwen 	ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) +
27386c1c09b3SPascal van Leeuwen 			      crypto_shash_descsize(ctx->shpre), GFP_KERNEL);
27396c1c09b3SPascal van Leeuwen 	if (!ctx->shdesc) {
27406c1c09b3SPascal van Leeuwen 		crypto_free_shash(ctx->shpre);
27416c1c09b3SPascal van Leeuwen 		return -ENOMEM;
27426c1c09b3SPascal van Leeuwen 	}
27436c1c09b3SPascal van Leeuwen 	ctx->shdesc->tfm = ctx->shpre;
27446c1c09b3SPascal van Leeuwen 	return 0;
27456c1c09b3SPascal van Leeuwen }
27466c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_cra_exit(struct crypto_tfm * tfm)27476c1c09b3SPascal van Leeuwen static void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm)
27486c1c09b3SPascal van Leeuwen {
27496c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
27506c1c09b3SPascal van Leeuwen 
27516c1c09b3SPascal van Leeuwen 	crypto_free_ahash(ctx->fback);
27526c1c09b3SPascal van Leeuwen 	crypto_free_shash(ctx->shpre);
27536c1c09b3SPascal van Leeuwen 	kfree(ctx->shdesc);
27546c1c09b3SPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
27556c1c09b3SPascal van Leeuwen }
27566c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)27576c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key,
27586c1c09b3SPascal van Leeuwen 				     unsigned int keylen)
27596c1c09b3SPascal van Leeuwen {
27606c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
27616c1c09b3SPascal van Leeuwen 	int ret = 0;
27626c1c09b3SPascal van Leeuwen 
27636c1c09b3SPascal van Leeuwen 	if (keylen > crypto_ahash_blocksize(tfm)) {
27646c1c09b3SPascal van Leeuwen 		/*
27656c1c09b3SPascal van Leeuwen 		 * If the key is larger than the blocksize, then hash it
27666c1c09b3SPascal van Leeuwen 		 * first using our fallback cipher
27676c1c09b3SPascal van Leeuwen 		 */
27686c1c09b3SPascal van Leeuwen 		ret = crypto_shash_digest(ctx->shdesc, key, keylen,
276978cf1c8bSHerbert Xu 					  ctx->base.ipad.byte);
27706c1c09b3SPascal van Leeuwen 		keylen = crypto_shash_digestsize(ctx->shpre);
27716c1c09b3SPascal van Leeuwen 
27726c1c09b3SPascal van Leeuwen 		/*
27736c1c09b3SPascal van Leeuwen 		 * If the digest is larger than half the blocksize, we need to
27746c1c09b3SPascal van Leeuwen 		 * move the rest to opad due to the way our HMAC infra works.
27756c1c09b3SPascal van Leeuwen 		 */
27766c1c09b3SPascal van Leeuwen 		if (keylen > crypto_ahash_blocksize(tfm) / 2)
27776c1c09b3SPascal van Leeuwen 			/* Buffers overlap, need to use memmove iso memcpy! */
277878cf1c8bSHerbert Xu 			memmove(&ctx->base.opad,
277978cf1c8bSHerbert Xu 				ctx->base.ipad.byte +
27806c1c09b3SPascal van Leeuwen 					crypto_ahash_blocksize(tfm) / 2,
27816c1c09b3SPascal van Leeuwen 				keylen - crypto_ahash_blocksize(tfm) / 2);
27826c1c09b3SPascal van Leeuwen 	} else {
27836c1c09b3SPascal van Leeuwen 		/*
27846c1c09b3SPascal van Leeuwen 		 * Copy the key to our ipad & opad buffers
27856c1c09b3SPascal van Leeuwen 		 * Note that ipad and opad each contain one half of the key,
27866c1c09b3SPascal van Leeuwen 		 * to match the existing HMAC driver infrastructure.
27876c1c09b3SPascal van Leeuwen 		 */
27886c1c09b3SPascal van Leeuwen 		if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
278978cf1c8bSHerbert Xu 			memcpy(&ctx->base.ipad, key, keylen);
27906c1c09b3SPascal van Leeuwen 		} else {
279178cf1c8bSHerbert Xu 			memcpy(&ctx->base.ipad, key,
27926c1c09b3SPascal van Leeuwen 			       crypto_ahash_blocksize(tfm) / 2);
279378cf1c8bSHerbert Xu 			memcpy(&ctx->base.opad,
27946c1c09b3SPascal van Leeuwen 			       key + crypto_ahash_blocksize(tfm) / 2,
27956c1c09b3SPascal van Leeuwen 			       keylen - crypto_ahash_blocksize(tfm) / 2);
27966c1c09b3SPascal van Leeuwen 		}
27976c1c09b3SPascal van Leeuwen 	}
27986c1c09b3SPascal van Leeuwen 
27996c1c09b3SPascal van Leeuwen 	/* Pad key with zeroes */
28006c1c09b3SPascal van Leeuwen 	if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
280178cf1c8bSHerbert Xu 		memset(ctx->base.ipad.byte + keylen, 0,
28026c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) / 2 - keylen);
280378cf1c8bSHerbert Xu 		memset(&ctx->base.opad, 0, crypto_ahash_blocksize(tfm) / 2);
28046c1c09b3SPascal van Leeuwen 	} else {
280578cf1c8bSHerbert Xu 		memset(ctx->base.opad.byte + keylen -
28066c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) / 2, 0,
28076c1c09b3SPascal van Leeuwen 		       crypto_ahash_blocksize(tfm) - keylen);
28086c1c09b3SPascal van Leeuwen 	}
28096c1c09b3SPascal van Leeuwen 
28106c1c09b3SPascal van Leeuwen 	/* If doing fallback, still need to set the new key! */
28116c1c09b3SPascal van Leeuwen 	ctx->fb_do_setkey = true;
28126c1c09b3SPascal van Leeuwen 	return ret;
28136c1c09b3SPascal van Leeuwen }
28146c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_224_init(struct ahash_request * areq)28156c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_init(struct ahash_request *areq)
28166c1c09b3SPascal van Leeuwen {
28176c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
28186c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2819b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
28206c1c09b3SPascal van Leeuwen 
28216c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
28226c1c09b3SPascal van Leeuwen 
28236c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
282478cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA3_224_BLOCK_SIZE / 2);
28256c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
28266c1c09b3SPascal van Leeuwen 	req->len	= SHA3_224_BLOCK_SIZE;
28276c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_224_BLOCK_SIZE;
28286c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
28296c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
28306c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_224_BLOCK_SIZE / 2;
28316c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_224_DIGEST_SIZE;
28326c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_224_BLOCK_SIZE;
28336c1c09b3SPascal van Leeuwen 	req->hmac = true;
28346c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
28356c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
28366c1c09b3SPascal van Leeuwen 	return 0;
28376c1c09b3SPascal van Leeuwen }
28386c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_224_digest(struct ahash_request * req)28396c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_digest(struct ahash_request *req)
28406c1c09b3SPascal van Leeuwen {
28416c1c09b3SPascal van Leeuwen 	if (req->nbytes)
28426c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_224_init(req) ?:
28436c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
28446c1c09b3SPascal van Leeuwen 
28456c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
28466c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
28476c1c09b3SPascal van Leeuwen }
28486c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_224_cra_init(struct crypto_tfm * tfm)28496c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm)
28506c1c09b3SPascal van Leeuwen {
28516c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-224");
28526c1c09b3SPascal van Leeuwen }
28536c1c09b3SPascal van Leeuwen 
28546c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_224 = {
28556c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
28566c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
28576c1c09b3SPascal van Leeuwen 	.alg.ahash = {
28586c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_224_init,
28596c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
28606c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
28616c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
28626c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_224_digest,
28636c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
28646c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
28656c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
28666c1c09b3SPascal van Leeuwen 		.halg = {
28676c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_224_DIGEST_SIZE,
28686c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
28696c1c09b3SPascal van Leeuwen 			.base = {
28706c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-224)",
28716c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-224",
28726c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
28736c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
28746c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
28756c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
28766c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_224_BLOCK_SIZE,
28776c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
28786c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_224_cra_init,
28796c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
28806c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
28816c1c09b3SPascal van Leeuwen 			},
28826c1c09b3SPascal van Leeuwen 		},
28836c1c09b3SPascal van Leeuwen 	},
28846c1c09b3SPascal van Leeuwen };
28856c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_256_init(struct ahash_request * areq)28866c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_init(struct ahash_request *areq)
28876c1c09b3SPascal van Leeuwen {
28886c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
28896c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2890b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
28916c1c09b3SPascal van Leeuwen 
28926c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
28936c1c09b3SPascal van Leeuwen 
28946c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
289578cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA3_256_BLOCK_SIZE / 2);
28966c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
28976c1c09b3SPascal van Leeuwen 	req->len	= SHA3_256_BLOCK_SIZE;
28986c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_256_BLOCK_SIZE;
28996c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
29006c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
29016c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_256_BLOCK_SIZE / 2;
29026c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_256_DIGEST_SIZE;
29036c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_256_BLOCK_SIZE;
29046c1c09b3SPascal van Leeuwen 	req->hmac = true;
29056c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
29066c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
29076c1c09b3SPascal van Leeuwen 	return 0;
29086c1c09b3SPascal van Leeuwen }
29096c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_256_digest(struct ahash_request * req)29106c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_digest(struct ahash_request *req)
29116c1c09b3SPascal van Leeuwen {
29126c1c09b3SPascal van Leeuwen 	if (req->nbytes)
29136c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_256_init(req) ?:
29146c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
29156c1c09b3SPascal van Leeuwen 
29166c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
29176c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
29186c1c09b3SPascal van Leeuwen }
29196c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_256_cra_init(struct crypto_tfm * tfm)29206c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm)
29216c1c09b3SPascal van Leeuwen {
29226c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-256");
29236c1c09b3SPascal van Leeuwen }
29246c1c09b3SPascal van Leeuwen 
29256c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_256 = {
29266c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
29276c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
29286c1c09b3SPascal van Leeuwen 	.alg.ahash = {
29296c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_256_init,
29306c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
29316c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
29326c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
29336c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_256_digest,
29346c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
29356c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
29366c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
29376c1c09b3SPascal van Leeuwen 		.halg = {
29386c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_256_DIGEST_SIZE,
29396c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
29406c1c09b3SPascal van Leeuwen 			.base = {
29416c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-256)",
29426c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-256",
29436c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
29446c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
29456c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
29466c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
29476c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_256_BLOCK_SIZE,
29486c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
29496c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_256_cra_init,
29506c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
29516c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
29526c1c09b3SPascal van Leeuwen 			},
29536c1c09b3SPascal van Leeuwen 		},
29546c1c09b3SPascal van Leeuwen 	},
29556c1c09b3SPascal van Leeuwen };
29566c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_384_init(struct ahash_request * areq)29576c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_init(struct ahash_request *areq)
29586c1c09b3SPascal van Leeuwen {
29596c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
29606c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
2961b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
29626c1c09b3SPascal van Leeuwen 
29636c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
29646c1c09b3SPascal van Leeuwen 
29656c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
296678cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA3_384_BLOCK_SIZE / 2);
29676c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
29686c1c09b3SPascal van Leeuwen 	req->len	= SHA3_384_BLOCK_SIZE;
29696c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_384_BLOCK_SIZE;
29706c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
29716c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
29726c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_384_BLOCK_SIZE / 2;
29736c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_384_DIGEST_SIZE;
29746c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_384_BLOCK_SIZE;
29756c1c09b3SPascal van Leeuwen 	req->hmac = true;
29766c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
29776c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
29786c1c09b3SPascal van Leeuwen 	return 0;
29796c1c09b3SPascal van Leeuwen }
29806c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_384_digest(struct ahash_request * req)29816c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_digest(struct ahash_request *req)
29826c1c09b3SPascal van Leeuwen {
29836c1c09b3SPascal van Leeuwen 	if (req->nbytes)
29846c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_384_init(req) ?:
29856c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
29866c1c09b3SPascal van Leeuwen 
29876c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
29886c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
29896c1c09b3SPascal van Leeuwen }
29906c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_384_cra_init(struct crypto_tfm * tfm)29916c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm)
29926c1c09b3SPascal van Leeuwen {
29936c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-384");
29946c1c09b3SPascal van Leeuwen }
29956c1c09b3SPascal van Leeuwen 
29966c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_384 = {
29976c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
29986c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
29996c1c09b3SPascal van Leeuwen 	.alg.ahash = {
30006c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_384_init,
30016c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
30026c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
30036c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
30046c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_384_digest,
30056c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
30066c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
30076c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
30086c1c09b3SPascal van Leeuwen 		.halg = {
30096c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_384_DIGEST_SIZE,
30106c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
30116c1c09b3SPascal van Leeuwen 			.base = {
30126c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-384)",
30136c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-384",
30146c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
30156c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
30166c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
30176c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
30186c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_384_BLOCK_SIZE,
30196c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
30206c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_384_cra_init,
30216c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
30226c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
30236c1c09b3SPascal van Leeuwen 			},
30246c1c09b3SPascal van Leeuwen 		},
30256c1c09b3SPascal van Leeuwen 	},
30266c1c09b3SPascal van Leeuwen };
30276c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_512_init(struct ahash_request * areq)30286c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_init(struct ahash_request *areq)
30296c1c09b3SPascal van Leeuwen {
30306c1c09b3SPascal van Leeuwen 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
30316c1c09b3SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
3032b2e2e2daSHerbert Xu 	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
30336c1c09b3SPascal van Leeuwen 
30346c1c09b3SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
30356c1c09b3SPascal van Leeuwen 
30366c1c09b3SPascal van Leeuwen 	/* Copy (half of) the key */
303778cf1c8bSHerbert Xu 	memcpy(req->state, &ctx->base.ipad, SHA3_512_BLOCK_SIZE / 2);
30386c1c09b3SPascal van Leeuwen 	/* Start of HMAC should have len == processed == blocksize */
30396c1c09b3SPascal van Leeuwen 	req->len	= SHA3_512_BLOCK_SIZE;
30406c1c09b3SPascal van Leeuwen 	req->processed	= SHA3_512_BLOCK_SIZE;
30416c1c09b3SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
30426c1c09b3SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
30436c1c09b3SPascal van Leeuwen 	req->state_sz = SHA3_512_BLOCK_SIZE / 2;
30446c1c09b3SPascal van Leeuwen 	req->digest_sz = SHA3_512_DIGEST_SIZE;
30456c1c09b3SPascal van Leeuwen 	req->block_sz = SHA3_512_BLOCK_SIZE;
30466c1c09b3SPascal van Leeuwen 	req->hmac = true;
30476c1c09b3SPascal van Leeuwen 	ctx->do_fallback = false;
30486c1c09b3SPascal van Leeuwen 	ctx->fb_init_done = false;
30496c1c09b3SPascal van Leeuwen 	return 0;
30506c1c09b3SPascal van Leeuwen }
30516c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_512_digest(struct ahash_request * req)30526c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_digest(struct ahash_request *req)
30536c1c09b3SPascal van Leeuwen {
30546c1c09b3SPascal van Leeuwen 	if (req->nbytes)
30556c1c09b3SPascal van Leeuwen 		return safexcel_hmac_sha3_512_init(req) ?:
30566c1c09b3SPascal van Leeuwen 		       safexcel_ahash_finup(req);
30576c1c09b3SPascal van Leeuwen 
30586c1c09b3SPascal van Leeuwen 	/* HW cannot do zero length HMAC, use fallback instead */
30596c1c09b3SPascal van Leeuwen 	return safexcel_sha3_digest_fallback(req);
30606c1c09b3SPascal van Leeuwen }
30616c1c09b3SPascal van Leeuwen 
safexcel_hmac_sha3_512_cra_init(struct crypto_tfm * tfm)30626c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm)
30636c1c09b3SPascal van Leeuwen {
30646c1c09b3SPascal van Leeuwen 	return safexcel_hmac_sha3_cra_init(tfm, "sha3-512");
30656c1c09b3SPascal van Leeuwen }
30666c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_512 = {
30676c1c09b3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
30686c1c09b3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA3,
30696c1c09b3SPascal van Leeuwen 	.alg.ahash = {
30706c1c09b3SPascal van Leeuwen 		.init = safexcel_hmac_sha3_512_init,
30716c1c09b3SPascal van Leeuwen 		.update = safexcel_sha3_update,
30726c1c09b3SPascal van Leeuwen 		.final = safexcel_sha3_final,
30736c1c09b3SPascal van Leeuwen 		.finup = safexcel_sha3_finup,
30746c1c09b3SPascal van Leeuwen 		.digest = safexcel_hmac_sha3_512_digest,
30756c1c09b3SPascal van Leeuwen 		.setkey = safexcel_hmac_sha3_setkey,
30766c1c09b3SPascal van Leeuwen 		.export = safexcel_sha3_export,
30776c1c09b3SPascal van Leeuwen 		.import = safexcel_sha3_import,
30786c1c09b3SPascal van Leeuwen 		.halg = {
30796c1c09b3SPascal van Leeuwen 			.digestsize = SHA3_512_DIGEST_SIZE,
30806c1c09b3SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
30816c1c09b3SPascal van Leeuwen 			.base = {
30826c1c09b3SPascal van Leeuwen 				.cra_name = "hmac(sha3-512)",
30836c1c09b3SPascal van Leeuwen 				.cra_driver_name = "safexcel-hmac-sha3-512",
30846c1c09b3SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
30856c1c09b3SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
30866c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY |
30876c1c09b3SPascal van Leeuwen 					     CRYPTO_ALG_NEED_FALLBACK,
30886c1c09b3SPascal van Leeuwen 				.cra_blocksize = SHA3_512_BLOCK_SIZE,
30896c1c09b3SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
30906c1c09b3SPascal van Leeuwen 				.cra_init = safexcel_hmac_sha3_512_cra_init,
30916c1c09b3SPascal van Leeuwen 				.cra_exit = safexcel_hmac_sha3_cra_exit,
30926c1c09b3SPascal van Leeuwen 				.cra_module = THIS_MODULE,
30936c1c09b3SPascal van Leeuwen 			},
30946c1c09b3SPascal van Leeuwen 		},
30956c1c09b3SPascal van Leeuwen 	},
30966c1c09b3SPascal van Leeuwen };
3097