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 
8aed3731eSAntoine Ténart #include <crypto/hmac.h>
9293f89cfSOfer Heifetz #include <crypto/md5.h>
101b44c5a6SAntoine Ténart #include <crypto/sha.h>
111b44c5a6SAntoine Ténart #include <linux/device.h>
121b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
131b44c5a6SAntoine Ténart #include <linux/dmapool.h>
141b44c5a6SAntoine Ténart 
151b44c5a6SAntoine Ténart #include "safexcel.h"
161b44c5a6SAntoine Ténart 
171b44c5a6SAntoine Ténart struct safexcel_ahash_ctx {
181b44c5a6SAntoine Ténart 	struct safexcel_context base;
191b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
201b44c5a6SAntoine Ténart 
211b44c5a6SAntoine Ténart 	u32 alg;
221b44c5a6SAntoine Ténart 
230de54fb1SAntoine Tenart 	u32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)];
240de54fb1SAntoine Tenart 	u32 opad[SHA512_DIGEST_SIZE / sizeof(u32)];
251b44c5a6SAntoine Ténart };
261b44c5a6SAntoine Ténart 
271b44c5a6SAntoine Ténart struct safexcel_ahash_req {
281b44c5a6SAntoine Ténart 	bool last_req;
291b44c5a6SAntoine Ténart 	bool finish;
301b44c5a6SAntoine Ténart 	bool hmac;
311eb7b403SOfer Heifetz 	bool needs_inv;
3285b36ee8SPascal van Leeuwen 	bool hmac_zlen;
3385b36ee8SPascal van Leeuwen 	bool len_is_le;
341b44c5a6SAntoine Ténart 
35c957f8b3SAntoine Ténart 	int nents;
36b8592027SOfer Heifetz 	dma_addr_t result_dma;
37c957f8b3SAntoine Ténart 
38b869648cSAntoine Tenart 	u32 digest;
39b869648cSAntoine Tenart 
4041abed7dSPascal van Leeuwen 	u8 state_sz;    /* expected state size, only set once */
4141abed7dSPascal van Leeuwen 	u8 block_sz;    /* block size, only set once */
42b460edb6SAntoine Tenart 	u32 state[SHA512_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32));
431b44c5a6SAntoine Ténart 
4431fb084cSPascal van Leeuwen 	u64 len;
4531fb084cSPascal van Leeuwen 	u64 processed;
461b44c5a6SAntoine Ténart 
4741abed7dSPascal van Leeuwen 	u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32));
48cff9a175SAntoine Tenart 	dma_addr_t cache_dma;
49cff9a175SAntoine Tenart 	unsigned int cache_sz;
50cff9a175SAntoine Tenart 
5141abed7dSPascal van Leeuwen 	u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32));
521b44c5a6SAntoine Ténart };
531b44c5a6SAntoine Ténart 
54b460edb6SAntoine Tenart static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req)
55b460edb6SAntoine Tenart {
5631fb084cSPascal van Leeuwen 	return req->len - req->processed;
57b460edb6SAntoine Tenart }
58b460edb6SAntoine Tenart 
591b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc,
601b44c5a6SAntoine Ténart 				u32 input_length, u32 result_length)
611b44c5a6SAntoine Ténart {
621b44c5a6SAntoine Ténart 	struct safexcel_token *token =
631b44c5a6SAntoine Ténart 		(struct safexcel_token *)cdesc->control_data.token;
641b44c5a6SAntoine Ténart 
651b44c5a6SAntoine Ténart 	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
661b44c5a6SAntoine Ténart 	token[0].packet_length = input_length;
671b44c5a6SAntoine Ténart 	token[0].stat = EIP197_TOKEN_STAT_LAST_HASH;
681b44c5a6SAntoine Ténart 	token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH;
691b44c5a6SAntoine Ténart 
701b44c5a6SAntoine Ténart 	token[1].opcode = EIP197_TOKEN_OPCODE_INSERT;
711b44c5a6SAntoine Ténart 	token[1].packet_length = result_length;
721b44c5a6SAntoine Ténart 	token[1].stat = EIP197_TOKEN_STAT_LAST_HASH |
731b44c5a6SAntoine Ténart 			EIP197_TOKEN_STAT_LAST_PACKET;
741b44c5a6SAntoine Ténart 	token[1].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
751b44c5a6SAntoine Ténart 				EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
761b44c5a6SAntoine Ténart }
771b44c5a6SAntoine Ténart 
781b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx,
791b44c5a6SAntoine Ténart 				     struct safexcel_ahash_req *req,
8041abed7dSPascal van Leeuwen 				     struct safexcel_command_desc *cdesc)
811b44c5a6SAntoine Ténart {
82b460edb6SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
8341abed7dSPascal van Leeuwen 	u64 count = 0;
841b44c5a6SAntoine Ténart 
851b44c5a6SAntoine Ténart 	cdesc->control_data.control0 |= ctx->alg;
86dc5268b6SPascal van Leeuwen 
871b44c5a6SAntoine Ténart 	/*
881b44c5a6SAntoine Ténart 	 * Copy the input digest if needed, and setup the context
891b44c5a6SAntoine Ténart 	 * fields. Do this now as we need it to setup the first command
901b44c5a6SAntoine Ténart 	 * descriptor.
911b44c5a6SAntoine Ténart 	 */
9231fb084cSPascal van Leeuwen 	if (!req->processed) {
9341abed7dSPascal van Leeuwen 		/* First - and possibly only - block of basic hash only */
9441abed7dSPascal van Leeuwen 		if (req->finish) {
9541abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
9641abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
9741abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH  |
9841abed7dSPascal van Leeuwen 				/* ensure its not 0! */
9941abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
10041abed7dSPascal van Leeuwen 		} else {
10141abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
10241abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
10341abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH   |
10441abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_NO_FINISH_HASH |
10541abed7dSPascal van Leeuwen 				/* ensure its not 0! */
10641abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
10741abed7dSPascal van Leeuwen 		}
10841abed7dSPascal van Leeuwen 		return;
10941abed7dSPascal van Leeuwen 	}
11041abed7dSPascal van Leeuwen 
11141abed7dSPascal van Leeuwen 	/* Hash continuation or HMAC, setup (inner) digest from state */
11241abed7dSPascal van Leeuwen 	memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
1131b44c5a6SAntoine Ténart 
114b460edb6SAntoine Tenart 	if (req->finish) {
11541abed7dSPascal van Leeuwen 		/* Compute digest count for hash/HMAC finish operations */
11641abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
11731fb084cSPascal van Leeuwen 		    req->hmac_zlen || (req->processed != req->block_sz)) {
11831fb084cSPascal van Leeuwen 			count = req->processed / EIP197_COUNTER_BLOCK_SIZE;
119b460edb6SAntoine Tenart 
12041abed7dSPascal van Leeuwen 			/* This is a hardware limitation, as the
121b460edb6SAntoine Tenart 			 * counter must fit into an u32. This represents
12241abed7dSPascal van Leeuwen 			 * a fairly big amount of input data, so we
123b460edb6SAntoine Tenart 			 * shouldn't see this.
124b460edb6SAntoine Tenart 			 */
12541abed7dSPascal van Leeuwen 			if (unlikely(count & 0xffffffff00000000ULL)) {
126b460edb6SAntoine Tenart 				dev_warn(priv->dev,
127b460edb6SAntoine Tenart 					 "Input data is too big\n");
128b460edb6SAntoine Tenart 				return;
129b460edb6SAntoine Tenart 			}
130b460edb6SAntoine Tenart 		}
1311b44c5a6SAntoine Ténart 
13241abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
13385b36ee8SPascal van Leeuwen 		    /* Special case: zero length HMAC */
13485b36ee8SPascal van Leeuwen 		    req->hmac_zlen ||
13541abed7dSPascal van Leeuwen 		    /* PE HW < 4.4 cannot do HMAC continue, fake using hash */
13631fb084cSPascal van Leeuwen 		    (req->processed != req->block_sz)) {
13741abed7dSPascal van Leeuwen 			/* Basic hash continue operation, need digest + cnt */
13841abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
13941abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) |
14041abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
14141abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
14285b36ee8SPascal van Leeuwen 			/* For zero-len HMAC, don't finalize, already padded! */
14385b36ee8SPascal van Leeuwen 			if (req->hmac_zlen)
14485b36ee8SPascal van Leeuwen 				cdesc->control_data.control0 |=
14585b36ee8SPascal van Leeuwen 					CONTEXT_CONTROL_NO_FINISH_HASH;
14641abed7dSPascal van Leeuwen 			cdesc->control_data.control1 |=
14741abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_CNT;
14841abed7dSPascal van Leeuwen 			ctx->base.ctxr->data[req->state_sz >> 2] =
14941abed7dSPascal van Leeuwen 				cpu_to_le32(count);
15041abed7dSPascal van Leeuwen 			req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
15185b36ee8SPascal van Leeuwen 
15285b36ee8SPascal van Leeuwen 			/* Clear zero-length HMAC flag for next operation! */
15385b36ee8SPascal van Leeuwen 			req->hmac_zlen = false;
15441abed7dSPascal van Leeuwen 		} else { /* HMAC */
15541abed7dSPascal van Leeuwen 			/* Need outer digest for HMAC finalization */
15641abed7dSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (req->state_sz >> 2),
1574505bb02SAntoine Tenart 			       ctx->opad, req->state_sz);
15841abed7dSPascal van Leeuwen 
15941abed7dSPascal van Leeuwen 			/* Single pass HMAC - no digest count */
16041abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
16141abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz >> 1) |
16241abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
16341abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_HMAC;
16441abed7dSPascal van Leeuwen 		}
16541abed7dSPascal van Leeuwen 	} else { /* Hash continuation, do not finish yet */
16641abed7dSPascal van Leeuwen 		cdesc->control_data.control0 |=
16741abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_SIZE(req->state_sz >> 2) |
16841abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_DIGEST_PRECOMPUTED |
16941abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_TYPE_HASH_OUT |
17041abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_NO_FINISH_HASH;
1711b44c5a6SAntoine Ténart 	}
1721b44c5a6SAntoine Ténart }
1731b44c5a6SAntoine Ténart 
17441abed7dSPascal van Leeuwen static int safexcel_ahash_enqueue(struct ahash_request *areq);
17541abed7dSPascal van Leeuwen 
17641abed7dSPascal van Leeuwen static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv,
17741abed7dSPascal van Leeuwen 				      int ring,
1781b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
1791b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
1801b44c5a6SAntoine Ténart {
1811b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
1821b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
1831b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
1841b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *sreq = ahash_request_ctx(areq);
18541abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
186b460edb6SAntoine Tenart 	u64 cache_len;
1871b44c5a6SAntoine Ténart 
1881b44c5a6SAntoine Ténart 	*ret = 0;
1891b44c5a6SAntoine Ténart 
1901b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
1911b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
1921b44c5a6SAntoine Ténart 		dev_err(priv->dev,
1931b44c5a6SAntoine Ténart 			"hash: result: could not retrieve the result descriptor\n");
1941b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
195bdfd1909SAntoine Tenart 	} else {
196bdfd1909SAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
1971b44c5a6SAntoine Ténart 	}
1981b44c5a6SAntoine Ténart 
1991b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
2001b44c5a6SAntoine Ténart 
201c957f8b3SAntoine Ténart 	if (sreq->nents) {
202c957f8b3SAntoine Ténart 		dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE);
203c957f8b3SAntoine Ténart 		sreq->nents = 0;
204c957f8b3SAntoine Ténart 	}
2051b44c5a6SAntoine Ténart 
206b8592027SOfer Heifetz 	if (sreq->result_dma) {
207b8592027SOfer Heifetz 		dma_unmap_single(priv->dev, sreq->result_dma, sreq->state_sz,
208b8592027SOfer Heifetz 				 DMA_FROM_DEVICE);
209b8592027SOfer Heifetz 		sreq->result_dma = 0;
210b8592027SOfer Heifetz 	}
211b8592027SOfer Heifetz 
212cff9a175SAntoine Tenart 	if (sreq->cache_dma) {
213cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz,
214cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
215cff9a175SAntoine Tenart 		sreq->cache_dma = 0;
216aa524286SAntoine Tenart 		sreq->cache_sz = 0;
217cff9a175SAntoine Tenart 	}
2181b44c5a6SAntoine Ténart 
21941abed7dSPascal van Leeuwen 	if (sreq->finish) {
22041abed7dSPascal van Leeuwen 		if (sreq->hmac &&
22141abed7dSPascal van Leeuwen 		    (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) {
22241abed7dSPascal van Leeuwen 			/* Faking HMAC using hash - need to do outer hash */
22341abed7dSPascal van Leeuwen 			memcpy(sreq->cache, sreq->state,
22441abed7dSPascal van Leeuwen 			       crypto_ahash_digestsize(ahash));
22541abed7dSPascal van Leeuwen 
22641abed7dSPascal van Leeuwen 			memcpy(sreq->state, ctx->opad, sreq->state_sz);
22741abed7dSPascal van Leeuwen 
22831fb084cSPascal van Leeuwen 			sreq->len = sreq->block_sz +
22941abed7dSPascal van Leeuwen 				    crypto_ahash_digestsize(ahash);
23031fb084cSPascal van Leeuwen 			sreq->processed = sreq->block_sz;
23141abed7dSPascal van Leeuwen 			sreq->hmac = 0;
23241abed7dSPascal van Leeuwen 
23341abed7dSPascal van Leeuwen 			ctx->base.needs_inv = true;
23441abed7dSPascal van Leeuwen 			areq->nbytes = 0;
23541abed7dSPascal van Leeuwen 			safexcel_ahash_enqueue(areq);
23641abed7dSPascal van Leeuwen 
23741abed7dSPascal van Leeuwen 			*should_complete = false; /* Not done yet */
23841abed7dSPascal van Leeuwen 			return 1;
23941abed7dSPascal van Leeuwen 		}
24041abed7dSPascal van Leeuwen 
241b89a8159SAntoine Tenart 		memcpy(areq->result, sreq->state,
242b89a8159SAntoine Tenart 		       crypto_ahash_digestsize(ahash));
24341abed7dSPascal van Leeuwen 	}
244b89a8159SAntoine Tenart 
245b460edb6SAntoine Tenart 	cache_len = safexcel_queued_len(sreq);
2461b44c5a6SAntoine Ténart 	if (cache_len)
2471b44c5a6SAntoine Ténart 		memcpy(sreq->cache, sreq->cache_next, cache_len);
2481b44c5a6SAntoine Ténart 
2491b44c5a6SAntoine Ténart 	*should_complete = true;
2501b44c5a6SAntoine Ténart 
2511b44c5a6SAntoine Ténart 	return 1;
2521b44c5a6SAntoine Ténart }
2531b44c5a6SAntoine Ténart 
2541eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring,
2551eb7b403SOfer Heifetz 				   int *commands, int *results)
2561b44c5a6SAntoine Ténart {
2571b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
2581b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
2591b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
2601b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
2611b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc, *first_cdesc = NULL;
2621b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
2631b44c5a6SAntoine Ténart 	struct scatterlist *sg;
264082ec2d4SAntoine Tenart 	int i, extra = 0, n_cdesc = 0, ret = 0;
26541abed7dSPascal van Leeuwen 	u64 queued, len, cache_len;
2661b44c5a6SAntoine Ténart 
267b460edb6SAntoine Tenart 	queued = len = safexcel_queued_len(req);
26841abed7dSPascal van Leeuwen 	if (queued <= HASH_CACHE_SIZE)
2691b44c5a6SAntoine Ténart 		cache_len = queued;
2701b44c5a6SAntoine Ténart 	else
2711b44c5a6SAntoine Ténart 		cache_len = queued - areq->nbytes;
2721b44c5a6SAntoine Ténart 
27341abed7dSPascal van Leeuwen 	if (!req->finish && !req->last_req) {
274809778e0SAntoine Ténart 		/* If this is not the last request and the queued data does not
27541abed7dSPascal van Leeuwen 		 * fit into full cache blocks, cache it for the next send call.
2761b44c5a6SAntoine Ténart 		 */
27741abed7dSPascal van Leeuwen 		extra = queued & (HASH_CACHE_SIZE - 1);
278082ec2d4SAntoine Tenart 
279809778e0SAntoine Ténart 		/* If this is not the last request and the queued data
280809778e0SAntoine Ténart 		 * is a multiple of a block, cache the last one for now.
281809778e0SAntoine Ténart 		 */
282dd4306a6SAntoine Tenart 		if (!extra)
28341abed7dSPascal van Leeuwen 			extra = HASH_CACHE_SIZE;
284809778e0SAntoine Ténart 
2851b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
286809778e0SAntoine Ténart 				   req->cache_next, extra,
287809778e0SAntoine Ténart 				   areq->nbytes - extra);
2881b44c5a6SAntoine Ténart 
2891b44c5a6SAntoine Ténart 		queued -= extra;
2901b44c5a6SAntoine Ténart 		len -= extra;
291dc5268b6SPascal van Leeuwen 
292dc5268b6SPascal van Leeuwen 		if (!queued) {
293dc5268b6SPascal van Leeuwen 			*commands = 0;
294dc5268b6SPascal van Leeuwen 			*results = 0;
295dc5268b6SPascal van Leeuwen 			return 0;
296dc5268b6SPascal van Leeuwen 		}
297809778e0SAntoine Ténart 	}
2981b44c5a6SAntoine Ténart 
2991b44c5a6SAntoine Ténart 	/* Add a command descriptor for the cached data, if any */
3001b44c5a6SAntoine Ténart 	if (cache_len) {
301cff9a175SAntoine Tenart 		req->cache_dma = dma_map_single(priv->dev, req->cache,
3021b44c5a6SAntoine Ténart 						cache_len, DMA_TO_DEVICE);
3039744fec9SOfer Heifetz 		if (dma_mapping_error(priv->dev, req->cache_dma))
304cff9a175SAntoine Tenart 			return -EINVAL;
3051b44c5a6SAntoine Ténart 
306cff9a175SAntoine Tenart 		req->cache_sz = cache_len;
3071b44c5a6SAntoine Ténart 		first_cdesc = safexcel_add_cdesc(priv, ring, 1,
3081b44c5a6SAntoine Ténart 						 (cache_len == len),
309cff9a175SAntoine Tenart 						 req->cache_dma, cache_len, len,
3101b44c5a6SAntoine Ténart 						 ctx->base.ctxr_dma);
3111b44c5a6SAntoine Ténart 		if (IS_ERR(first_cdesc)) {
3121b44c5a6SAntoine Ténart 			ret = PTR_ERR(first_cdesc);
3131b44c5a6SAntoine Ténart 			goto unmap_cache;
3141b44c5a6SAntoine Ténart 		}
3151b44c5a6SAntoine Ténart 		n_cdesc++;
3161b44c5a6SAntoine Ténart 
3171b44c5a6SAntoine Ténart 		queued -= cache_len;
3181b44c5a6SAntoine Ténart 		if (!queued)
3191b44c5a6SAntoine Ténart 			goto send_command;
3201b44c5a6SAntoine Ténart 	}
3211b44c5a6SAntoine Ténart 
32241abed7dSPascal van Leeuwen 	/* Skip descriptor generation for zero-length requests */
32341abed7dSPascal van Leeuwen 	if (!areq->nbytes)
32441abed7dSPascal van Leeuwen 		goto send_command;
32541abed7dSPascal van Leeuwen 
3261b44c5a6SAntoine Ténart 	/* Now handle the current ahash request buffer(s) */
32741abed7dSPascal van Leeuwen 	req->nents = dma_map_sg(priv->dev, areq->src,
32841abed7dSPascal van Leeuwen 				sg_nents_for_len(areq->src,
32941abed7dSPascal van Leeuwen 						 areq->nbytes),
3301b44c5a6SAntoine Ténart 				DMA_TO_DEVICE);
331c957f8b3SAntoine Ténart 	if (!req->nents) {
3321b44c5a6SAntoine Ténart 		ret = -ENOMEM;
3331b44c5a6SAntoine Ténart 		goto cdesc_rollback;
3341b44c5a6SAntoine Ténart 	}
3351b44c5a6SAntoine Ténart 
336c957f8b3SAntoine Ténart 	for_each_sg(areq->src, sg, req->nents, i) {
3371b44c5a6SAntoine Ténart 		int sglen = sg_dma_len(sg);
3381b44c5a6SAntoine Ténart 
3391b44c5a6SAntoine Ténart 		/* Do not overflow the request */
340b460edb6SAntoine Tenart 		if (queued < sglen)
3411b44c5a6SAntoine Ténart 			sglen = queued;
3421b44c5a6SAntoine Ténart 
3431b44c5a6SAntoine Ténart 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
34441abed7dSPascal van Leeuwen 					   !(queued - sglen),
34541abed7dSPascal van Leeuwen 					   sg_dma_address(sg),
3461b44c5a6SAntoine Ténart 					   sglen, len, ctx->base.ctxr_dma);
3471b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
3481b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
34957433b58SAntoine Tenart 			goto unmap_sg;
3501b44c5a6SAntoine Ténart 		}
3511b44c5a6SAntoine Ténart 		n_cdesc++;
3521b44c5a6SAntoine Ténart 
3531b44c5a6SAntoine Ténart 		if (n_cdesc == 1)
3541b44c5a6SAntoine Ténart 			first_cdesc = cdesc;
3551b44c5a6SAntoine Ténart 
3561b44c5a6SAntoine Ténart 		queued -= sglen;
3571b44c5a6SAntoine Ténart 		if (!queued)
3581b44c5a6SAntoine Ténart 			break;
3591b44c5a6SAntoine Ténart 	}
3601b44c5a6SAntoine Ténart 
3611b44c5a6SAntoine Ténart send_command:
3621b44c5a6SAntoine Ténart 	/* Setup the context options */
36341abed7dSPascal van Leeuwen 	safexcel_context_control(ctx, req, first_cdesc);
3641b44c5a6SAntoine Ténart 
3651b44c5a6SAntoine Ténart 	/* Add the token */
3661b44c5a6SAntoine Ténart 	safexcel_hash_token(first_cdesc, len, req->state_sz);
3671b44c5a6SAntoine Ténart 
368b8592027SOfer Heifetz 	req->result_dma = dma_map_single(priv->dev, req->state, req->state_sz,
369b8592027SOfer Heifetz 					 DMA_FROM_DEVICE);
370b8592027SOfer Heifetz 	if (dma_mapping_error(priv->dev, req->result_dma)) {
3711b44c5a6SAntoine Ténart 		ret = -EINVAL;
37257433b58SAntoine Tenart 		goto unmap_sg;
3731b44c5a6SAntoine Ténart 	}
3741b44c5a6SAntoine Ténart 
3751b44c5a6SAntoine Ténart 	/* Add a result descriptor */
376b8592027SOfer Heifetz 	rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma,
3771b44c5a6SAntoine Ténart 				   req->state_sz);
3781b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
3791b44c5a6SAntoine Ténart 		ret = PTR_ERR(rdesc);
38057240a78SAntoine Tenart 		goto unmap_result;
3811b44c5a6SAntoine Ténart 	}
3821b44c5a6SAntoine Ténart 
3839744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, rdesc, &areq->base);
3841b44c5a6SAntoine Ténart 
38531fb084cSPascal van Leeuwen 	req->processed += len;
386b460edb6SAntoine Tenart 
3871b44c5a6SAntoine Ténart 	*commands = n_cdesc;
3881b44c5a6SAntoine Ténart 	*results = 1;
3891b44c5a6SAntoine Ténart 	return 0;
3901b44c5a6SAntoine Ténart 
39157240a78SAntoine Tenart unmap_result:
39257433b58SAntoine Tenart 	dma_unmap_single(priv->dev, req->result_dma, req->state_sz,
39357433b58SAntoine Tenart 			 DMA_FROM_DEVICE);
39457433b58SAntoine Tenart unmap_sg:
39557240a78SAntoine Tenart 	dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE);
3961b44c5a6SAntoine Ténart cdesc_rollback:
3971b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
3981b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
3991b44c5a6SAntoine Ténart unmap_cache:
400cff9a175SAntoine Tenart 	if (req->cache_dma) {
401cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz,
402cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
403aa524286SAntoine Tenart 		req->cache_dma = 0;
404cff9a175SAntoine Tenart 		req->cache_sz = 0;
4051b44c5a6SAntoine Ténart 	}
4061b44c5a6SAntoine Ténart 
4071b44c5a6SAntoine Ténart 	return ret;
4081b44c5a6SAntoine Ténart }
4091b44c5a6SAntoine Ténart 
4101b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
4111b44c5a6SAntoine Ténart 				      int ring,
4121b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
4131b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
4141b44c5a6SAntoine Ténart {
4151b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
4161b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
4171b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
4181b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
4191b44c5a6SAntoine Ténart 	int enq_ret;
4201b44c5a6SAntoine Ténart 
4211b44c5a6SAntoine Ténart 	*ret = 0;
4221b44c5a6SAntoine Ténart 
4231b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
4241b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
4251b44c5a6SAntoine Ténart 		dev_err(priv->dev,
4261b44c5a6SAntoine Ténart 			"hash: invalidate: could not retrieve the result descriptor\n");
4271b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
428cda3e73aSAntoine Tenart 	} else {
429cda3e73aSAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
4301b44c5a6SAntoine Ténart 	}
4311b44c5a6SAntoine Ténart 
4321b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
4331b44c5a6SAntoine Ténart 
4341b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
4351b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
4361b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
4371b44c5a6SAntoine Ténart 
4381b44c5a6SAntoine Ténart 		*should_complete = true;
4391b44c5a6SAntoine Ténart 		return 1;
4401b44c5a6SAntoine Ténart 	}
4411b44c5a6SAntoine Ténart 
44286671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
44386671abbSAntoine Ténart 	ctx->base.ring = ring;
4441b44c5a6SAntoine Ténart 
44586671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
44686671abbSAntoine Ténart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async);
44786671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
4481b44c5a6SAntoine Ténart 
4491b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
4501b44c5a6SAntoine Ténart 		*ret = enq_ret;
4511b44c5a6SAntoine Ténart 
4528472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
4538472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
45486671abbSAntoine Ténart 
4551b44c5a6SAntoine Ténart 	*should_complete = false;
4561b44c5a6SAntoine Ténart 
4571b44c5a6SAntoine Ténart 	return 1;
4581b44c5a6SAntoine Ténart }
4591b44c5a6SAntoine Ténart 
4601eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring,
4611eb7b403SOfer Heifetz 				  struct crypto_async_request *async,
4621eb7b403SOfer Heifetz 				  bool *should_complete, int *ret)
4631eb7b403SOfer Heifetz {
4641eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
4651eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
4661eb7b403SOfer Heifetz 	int err;
4671eb7b403SOfer Heifetz 
46853c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv);
469871df319SAntoine Ténart 
4701eb7b403SOfer Heifetz 	if (req->needs_inv) {
4711eb7b403SOfer Heifetz 		req->needs_inv = false;
4721eb7b403SOfer Heifetz 		err = safexcel_handle_inv_result(priv, ring, async,
4731eb7b403SOfer Heifetz 						 should_complete, ret);
4741eb7b403SOfer Heifetz 	} else {
4751eb7b403SOfer Heifetz 		err = safexcel_handle_req_result(priv, ring, async,
4761eb7b403SOfer Heifetz 						 should_complete, ret);
4771eb7b403SOfer Heifetz 	}
4781eb7b403SOfer Heifetz 
4791eb7b403SOfer Heifetz 	return err;
4801eb7b403SOfer Heifetz }
4811eb7b403SOfer Heifetz 
4821b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async,
4839744fec9SOfer Heifetz 				   int ring, int *commands, int *results)
4841b44c5a6SAntoine Ténart {
4851b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
4861b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
4871b44c5a6SAntoine Ténart 	int ret;
4881b44c5a6SAntoine Ténart 
4895290ad6eSOfer Heifetz 	ret = safexcel_invalidate_cache(async, ctx->priv,
4909744fec9SOfer Heifetz 					ctx->base.ctxr_dma, ring);
4911b44c5a6SAntoine Ténart 	if (unlikely(ret))
4921b44c5a6SAntoine Ténart 		return ret;
4931b44c5a6SAntoine Ténart 
4941b44c5a6SAntoine Ténart 	*commands = 1;
4951b44c5a6SAntoine Ténart 	*results = 1;
4961b44c5a6SAntoine Ténart 
4971b44c5a6SAntoine Ténart 	return 0;
4981b44c5a6SAntoine Ténart }
4991b44c5a6SAntoine Ténart 
5001eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async,
5019744fec9SOfer Heifetz 			       int ring, int *commands, int *results)
5021eb7b403SOfer Heifetz {
5031eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
5041eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5051eb7b403SOfer Heifetz 	int ret;
5061eb7b403SOfer Heifetz 
5071eb7b403SOfer Heifetz 	if (req->needs_inv)
5089744fec9SOfer Heifetz 		ret = safexcel_ahash_send_inv(async, ring, commands, results);
5091eb7b403SOfer Heifetz 	else
5109744fec9SOfer Heifetz 		ret = safexcel_ahash_send_req(async, ring, commands, results);
5119744fec9SOfer Heifetz 
5121eb7b403SOfer Heifetz 	return ret;
5131eb7b403SOfer Heifetz }
5141eb7b403SOfer Heifetz 
5151b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm)
5161b44c5a6SAntoine Ténart {
5171b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
5181b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
51961824806SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE);
5207cad2fabSAntoine Ténart 	struct safexcel_ahash_req *rctx = ahash_request_ctx(req);
5213e1166b9SArnd Bergmann 	struct safexcel_inv_result result = {};
52286671abbSAntoine Ténart 	int ring = ctx->base.ring;
5231b44c5a6SAntoine Ténart 
524b926213dSAntoine Tenart 	memset(req, 0, EIP197_AHASH_REQ_SIZE);
5251b44c5a6SAntoine Ténart 
5261b44c5a6SAntoine Ténart 	/* create invalidation request */
5271b44c5a6SAntoine Ténart 	init_completion(&result.completion);
5287cad2fabSAntoine Ténart 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
5291b44c5a6SAntoine Ténart 				   safexcel_inv_complete, &result);
5301b44c5a6SAntoine Ténart 
5317cad2fabSAntoine Ténart 	ahash_request_set_tfm(req, __crypto_ahash_cast(tfm));
5327cad2fabSAntoine Ténart 	ctx = crypto_tfm_ctx(req->base.tfm);
5331b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
5341eb7b403SOfer Heifetz 	rctx->needs_inv = true;
5351b44c5a6SAntoine Ténart 
53686671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
5377cad2fabSAntoine Ténart 	crypto_enqueue_request(&priv->ring[ring].queue, &req->base);
53886671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
5391b44c5a6SAntoine Ténart 
5408472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
5418472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
5421b44c5a6SAntoine Ténart 
543b7007dbcSAntoine Tenart 	wait_for_completion(&result.completion);
5441b44c5a6SAntoine Ténart 
5451b44c5a6SAntoine Ténart 	if (result.error) {
5461b44c5a6SAntoine Ténart 		dev_warn(priv->dev, "hash: completion error (%d)\n",
5471b44c5a6SAntoine Ténart 			 result.error);
5481b44c5a6SAntoine Ténart 		return result.error;
5491b44c5a6SAntoine Ténart 	}
5501b44c5a6SAntoine Ténart 
5511b44c5a6SAntoine Ténart 	return 0;
5521b44c5a6SAntoine Ténart }
5531b44c5a6SAntoine Ténart 
554cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to
555cc75f5ceSAntoine Ténart  * the engine, aka. when there is at least 1 block size in the pipe.
556cc75f5ceSAntoine Ténart  */
55741abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq)
5581b44c5a6SAntoine Ténart {
5591b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
56041abed7dSPascal van Leeuwen 	u64 cache_len;
5611b44c5a6SAntoine Ténart 
562b460edb6SAntoine Tenart 	/* cache_len: everything accepted by the driver but not sent yet,
563b460edb6SAntoine Tenart 	 * tot sz handled by update() - last req sz - tot sz handled by send()
564b460edb6SAntoine Tenart 	 */
56541abed7dSPascal van Leeuwen 	cache_len = safexcel_queued_len(req);
5661b44c5a6SAntoine Ténart 
5671b44c5a6SAntoine Ténart 	/*
5681b44c5a6SAntoine Ténart 	 * In case there isn't enough bytes to proceed (less than a
5691b44c5a6SAntoine Ténart 	 * block size), cache the data until we have enough.
5701b44c5a6SAntoine Ténart 	 */
57141abed7dSPascal van Leeuwen 	if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) {
5721b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
5731b44c5a6SAntoine Ténart 				   req->cache + cache_len,
5741b44c5a6SAntoine Ténart 				   areq->nbytes, 0);
57541abed7dSPascal van Leeuwen 		return 0;
5761b44c5a6SAntoine Ténart 	}
5771b44c5a6SAntoine Ténart 
578dfbcc08fSAntoine Ténart 	/* We couldn't cache all the data */
5791b44c5a6SAntoine Ténart 	return -E2BIG;
5801b44c5a6SAntoine Ténart }
5811b44c5a6SAntoine Ténart 
5821b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq)
5831b44c5a6SAntoine Ténart {
5841b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
5851b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5861b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
58786671abbSAntoine Ténart 	int ret, ring;
5881b44c5a6SAntoine Ténart 
5891eb7b403SOfer Heifetz 	req->needs_inv = false;
5901b44c5a6SAntoine Ténart 
591c4daf4ccSOfer Heifetz 	if (ctx->base.ctxr) {
59253c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv &&
59331fb084cSPascal van Leeuwen 		    req->processed &&
59441abed7dSPascal van Leeuwen 		    (/* invalidate for basic hash continuation finish */
59541abed7dSPascal van Leeuwen 		     (req->finish &&
59641abed7dSPascal van Leeuwen 		      (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED)) ||
59741abed7dSPascal van Leeuwen 		     /* invalidate if (i)digest changed */
59841abed7dSPascal van Leeuwen 		     memcmp(ctx->base.ctxr->data, req->state, req->state_sz) ||
59941abed7dSPascal van Leeuwen 		     /* invalidate for HMAC continuation finish */
60031fb084cSPascal van Leeuwen 		     (req->finish && (req->processed != req->block_sz)) ||
60141abed7dSPascal van Leeuwen 		     /* invalidate for HMAC finish with odigest changed */
60241abed7dSPascal van Leeuwen 		     (req->finish &&
60341abed7dSPascal van Leeuwen 		      memcmp(ctx->base.ctxr->data + (req->state_sz>>2),
60441abed7dSPascal van Leeuwen 			     ctx->opad, req->state_sz))))
60541abed7dSPascal van Leeuwen 			/*
60641abed7dSPascal van Leeuwen 			 * We're still setting needs_inv here, even though it is
607c4daf4ccSOfer Heifetz 			 * cleared right away, because the needs_inv flag can be
608c4daf4ccSOfer Heifetz 			 * set in other functions and we want to keep the same
609c4daf4ccSOfer Heifetz 			 * logic.
610c4daf4ccSOfer Heifetz 			 */
61141abed7dSPascal van Leeuwen 			ctx->base.needs_inv = true;
6121b44c5a6SAntoine Ténart 
6131eb7b403SOfer Heifetz 		if (ctx->base.needs_inv) {
6141eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
6151eb7b403SOfer Heifetz 			req->needs_inv = true;
6161eb7b403SOfer Heifetz 		}
6171b44c5a6SAntoine Ténart 	} else {
6181b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
6191b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
6201b44c5a6SAntoine Ténart 						 EIP197_GFP_FLAGS(areq->base),
6211b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
6221b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
6231b44c5a6SAntoine Ténart 			return -ENOMEM;
6241b44c5a6SAntoine Ténart 	}
6251b44c5a6SAntoine Ténart 
62686671abbSAntoine Ténart 	ring = ctx->base.ring;
6271b44c5a6SAntoine Ténart 
62886671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
62986671abbSAntoine Ténart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base);
63086671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
63186671abbSAntoine Ténart 
6328472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
6338472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
6341b44c5a6SAntoine Ténart 
6351b44c5a6SAntoine Ténart 	return ret;
6361b44c5a6SAntoine Ténart }
6371b44c5a6SAntoine Ténart 
6381b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq)
6391b44c5a6SAntoine Ténart {
6401b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
64141abed7dSPascal van Leeuwen 	int ret;
6421b44c5a6SAntoine Ténart 
6431b44c5a6SAntoine Ténart 	/* If the request is 0 length, do nothing */
6441b44c5a6SAntoine Ténart 	if (!areq->nbytes)
6451b44c5a6SAntoine Ténart 		return 0;
6461b44c5a6SAntoine Ténart 
64741abed7dSPascal van Leeuwen 	/* Add request to the cache if it fits */
64841abed7dSPascal van Leeuwen 	ret = safexcel_ahash_cache(areq);
64941abed7dSPascal van Leeuwen 
65041abed7dSPascal van Leeuwen 	/* Update total request length */
65131fb084cSPascal van Leeuwen 	req->len += areq->nbytes;
6521b44c5a6SAntoine Ténart 
65341abed7dSPascal van Leeuwen 	/* If not all data could fit into the cache, go process the excess.
65441abed7dSPascal van Leeuwen 	 * Also go process immediately for an HMAC IV precompute, which
65541abed7dSPascal van Leeuwen 	 * will never be finished at all, but needs to be processed anyway.
6561b44c5a6SAntoine Ténart 	 */
65741abed7dSPascal van Leeuwen 	if ((ret && !req->finish) || req->last_req)
6581b44c5a6SAntoine Ténart 		return safexcel_ahash_enqueue(areq);
6591b44c5a6SAntoine Ténart 
6601b44c5a6SAntoine Ténart 	return 0;
6611b44c5a6SAntoine Ténart }
6621b44c5a6SAntoine Ténart 
6631b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq)
6641b44c5a6SAntoine Ténart {
6651b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6661b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
6671b44c5a6SAntoine Ténart 
6681b44c5a6SAntoine Ténart 	req->finish = true;
6691b44c5a6SAntoine Ténart 
67031fb084cSPascal van Leeuwen 	if (unlikely(!req->len && !areq->nbytes)) {
67185695b09SPascal van Leeuwen 		/*
67285695b09SPascal van Leeuwen 		 * If we have an overall 0 length *hash* request:
67385695b09SPascal van Leeuwen 		 * The HW cannot do 0 length hash, so we provide the correct
67485695b09SPascal van Leeuwen 		 * result directly here.
67585695b09SPascal van Leeuwen 		 */
676293f89cfSOfer Heifetz 		if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5)
677293f89cfSOfer Heifetz 			memcpy(areq->result, md5_zero_message_hash,
678293f89cfSOfer Heifetz 			       MD5_DIGEST_SIZE);
679293f89cfSOfer Heifetz 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1)
6801b44c5a6SAntoine Ténart 			memcpy(areq->result, sha1_zero_message_hash,
6811b44c5a6SAntoine Ténart 			       SHA1_DIGEST_SIZE);
6821b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224)
6831b44c5a6SAntoine Ténart 			memcpy(areq->result, sha224_zero_message_hash,
6841b44c5a6SAntoine Ténart 			       SHA224_DIGEST_SIZE);
6851b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256)
6861b44c5a6SAntoine Ténart 			memcpy(areq->result, sha256_zero_message_hash,
6871b44c5a6SAntoine Ténart 			       SHA256_DIGEST_SIZE);
6889e46eafdSAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384)
6899e46eafdSAntoine Tenart 			memcpy(areq->result, sha384_zero_message_hash,
6909e46eafdSAntoine Tenart 			       SHA384_DIGEST_SIZE);
691b460edb6SAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512)
692b460edb6SAntoine Tenart 			memcpy(areq->result, sha512_zero_message_hash,
693b460edb6SAntoine Tenart 			       SHA512_DIGEST_SIZE);
6941b44c5a6SAntoine Ténart 
6951b44c5a6SAntoine Ténart 		return 0;
69631fb084cSPascal van Leeuwen 	} else if (unlikely(req->hmac &&
69731fb084cSPascal van Leeuwen 			    (req->len == req->block_sz) &&
69841abed7dSPascal van Leeuwen 			    !areq->nbytes)) {
69985b36ee8SPascal van Leeuwen 		/*
70085b36ee8SPascal van Leeuwen 		 * If we have an overall 0 length *HMAC* request:
70185b36ee8SPascal van Leeuwen 		 * For HMAC, we need to finalize the inner digest
70285b36ee8SPascal van Leeuwen 		 * and then perform the outer hash.
70385b36ee8SPascal van Leeuwen 		 */
70485b36ee8SPascal van Leeuwen 
70585b36ee8SPascal van Leeuwen 		/* generate pad block in the cache */
70685b36ee8SPascal van Leeuwen 		/* start with a hash block of all zeroes */
70785b36ee8SPascal van Leeuwen 		memset(req->cache, 0, req->block_sz);
70885b36ee8SPascal van Leeuwen 		/* set the first byte to 0x80 to 'append a 1 bit' */
70985b36ee8SPascal van Leeuwen 		req->cache[0] = 0x80;
71085b36ee8SPascal van Leeuwen 		/* add the length in bits in the last 2 bytes */
71185b36ee8SPascal van Leeuwen 		if (req->len_is_le) {
71285b36ee8SPascal van Leeuwen 			/* Little endian length word (e.g. MD5) */
71385b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-8] = (req->block_sz << 3) &
71485b36ee8SPascal van Leeuwen 						      255;
71585b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-7] = (req->block_sz >> 5);
71685b36ee8SPascal van Leeuwen 		} else {
71785b36ee8SPascal van Leeuwen 			/* Big endian length word (e.g. any SHA) */
71885b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-2] = (req->block_sz >> 5);
71985b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-1] = (req->block_sz << 3) &
72085b36ee8SPascal van Leeuwen 						      255;
72185b36ee8SPascal van Leeuwen 		}
72285b36ee8SPascal van Leeuwen 
72331fb084cSPascal van Leeuwen 		req->len += req->block_sz; /* plus 1 hash block */
72485b36ee8SPascal van Leeuwen 
72585b36ee8SPascal van Leeuwen 		/* Set special zero-length HMAC flag */
72685b36ee8SPascal van Leeuwen 		req->hmac_zlen = true;
72785b36ee8SPascal van Leeuwen 
72885b36ee8SPascal van Leeuwen 		/* Finalize HMAC */
72985b36ee8SPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
73041abed7dSPascal van Leeuwen 	} else if (req->hmac) {
73141abed7dSPascal van Leeuwen 		/* Finalize HMAC */
73241abed7dSPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
7331b44c5a6SAntoine Ténart 	}
7341b44c5a6SAntoine Ténart 
7351b44c5a6SAntoine Ténart 	return safexcel_ahash_enqueue(areq);
7361b44c5a6SAntoine Ténart }
7371b44c5a6SAntoine Ténart 
7381b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq)
7391b44c5a6SAntoine Ténart {
7401b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
7411b44c5a6SAntoine Ténart 
7421b44c5a6SAntoine Ténart 	req->finish = true;
7431b44c5a6SAntoine Ténart 
7441b44c5a6SAntoine Ténart 	safexcel_ahash_update(areq);
7451b44c5a6SAntoine Ténart 	return safexcel_ahash_final(areq);
7461b44c5a6SAntoine Ténart }
7471b44c5a6SAntoine Ténart 
7481b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out)
7491b44c5a6SAntoine Ténart {
7501b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
7511b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state *export = out;
7521b44c5a6SAntoine Ténart 
75331fb084cSPascal van Leeuwen 	export->len = req->len;
75431fb084cSPascal van Leeuwen 	export->processed = req->processed;
7551b44c5a6SAntoine Ténart 
756b869648cSAntoine Tenart 	export->digest = req->digest;
757b869648cSAntoine Tenart 
7581b44c5a6SAntoine Ténart 	memcpy(export->state, req->state, req->state_sz);
75941abed7dSPascal van Leeuwen 	memcpy(export->cache, req->cache, HASH_CACHE_SIZE);
7601b44c5a6SAntoine Ténart 
7611b44c5a6SAntoine Ténart 	return 0;
7621b44c5a6SAntoine Ténart }
7631b44c5a6SAntoine Ténart 
7641b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in)
7651b44c5a6SAntoine Ténart {
7661b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
7671b44c5a6SAntoine Ténart 	const struct safexcel_ahash_export_state *export = in;
7681b44c5a6SAntoine Ténart 	int ret;
7691b44c5a6SAntoine Ténart 
7701b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
7711b44c5a6SAntoine Ténart 	if (ret)
7721b44c5a6SAntoine Ténart 		return ret;
7731b44c5a6SAntoine Ténart 
77431fb084cSPascal van Leeuwen 	req->len = export->len;
77531fb084cSPascal van Leeuwen 	req->processed = export->processed;
7761b44c5a6SAntoine Ténart 
777b869648cSAntoine Tenart 	req->digest = export->digest;
778b869648cSAntoine Tenart 
77941abed7dSPascal van Leeuwen 	memcpy(req->cache, export->cache, HASH_CACHE_SIZE);
7801b44c5a6SAntoine Ténart 	memcpy(req->state, export->state, req->state_sz);
7811b44c5a6SAntoine Ténart 
7821b44c5a6SAntoine Ténart 	return 0;
7831b44c5a6SAntoine Ténart }
7841b44c5a6SAntoine Ténart 
7851b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm)
7861b44c5a6SAntoine Ténart {
7871b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
7881b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
7891b44c5a6SAntoine Ténart 		container_of(__crypto_ahash_alg(tfm->__crt_alg),
7901b44c5a6SAntoine Ténart 			     struct safexcel_alg_template, alg.ahash);
7911b44c5a6SAntoine Ténart 
7921b44c5a6SAntoine Ténart 	ctx->priv = tmpl->priv;
7931eb7b403SOfer Heifetz 	ctx->base.send = safexcel_ahash_send;
7941eb7b403SOfer Heifetz 	ctx->base.handle_result = safexcel_handle_result;
7951b44c5a6SAntoine Ténart 
7961b44c5a6SAntoine Ténart 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
7971b44c5a6SAntoine Ténart 				 sizeof(struct safexcel_ahash_req));
7981b44c5a6SAntoine Ténart 	return 0;
7991b44c5a6SAntoine Ténart }
8001b44c5a6SAntoine Ténart 
8011b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq)
8021b44c5a6SAntoine Ténart {
8031b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
8041b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8051b44c5a6SAntoine Ténart 
8061b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
8071b44c5a6SAntoine Ténart 
8081b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
809b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
8101b44c5a6SAntoine Ténart 	req->state_sz = SHA1_DIGEST_SIZE;
81141abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
8121b44c5a6SAntoine Ténart 
8131b44c5a6SAntoine Ténart 	return 0;
8141b44c5a6SAntoine Ténart }
8151b44c5a6SAntoine Ténart 
8161b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq)
8171b44c5a6SAntoine Ténart {
8181b44c5a6SAntoine Ténart 	int ret = safexcel_sha1_init(areq);
8191b44c5a6SAntoine Ténart 
8201b44c5a6SAntoine Ténart 	if (ret)
8211b44c5a6SAntoine Ténart 		return ret;
8221b44c5a6SAntoine Ténart 
8231b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
8241b44c5a6SAntoine Ténart }
8251b44c5a6SAntoine Ténart 
8261b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm)
8271b44c5a6SAntoine Ténart {
8281b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
8291b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
8301b44c5a6SAntoine Ténart 	int ret;
8311b44c5a6SAntoine Ténart 
8321b44c5a6SAntoine Ténart 	/* context not allocated, skip invalidation */
8331b44c5a6SAntoine Ténart 	if (!ctx->base.ctxr)
8341b44c5a6SAntoine Ténart 		return;
8351b44c5a6SAntoine Ténart 
83653c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
8371b44c5a6SAntoine Ténart 		ret = safexcel_ahash_exit_inv(tfm);
8381b44c5a6SAntoine Ténart 		if (ret)
8391b44c5a6SAntoine Ténart 			dev_warn(priv->dev, "hash: invalidation error %d\n", ret);
840871df319SAntoine Ténart 	} else {
841871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
842871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
843871df319SAntoine Ténart 	}
8441b44c5a6SAntoine Ténart }
8451b44c5a6SAntoine Ténart 
8461b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = {
8471b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
848062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
8491b44c5a6SAntoine Ténart 	.alg.ahash = {
8501b44c5a6SAntoine Ténart 		.init = safexcel_sha1_init,
8511b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
8521b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
8531b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
8541b44c5a6SAntoine Ténart 		.digest = safexcel_sha1_digest,
8551b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
8561b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
8571b44c5a6SAntoine Ténart 		.halg = {
8581b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
8591b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
8601b44c5a6SAntoine Ténart 			.base = {
8611b44c5a6SAntoine Ténart 				.cra_name = "sha1",
8621b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha1",
863aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
8641b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
8651b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
8661b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
8671b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
8681b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
8691b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
8701b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
8711b44c5a6SAntoine Ténart 			},
8721b44c5a6SAntoine Ténart 		},
8731b44c5a6SAntoine Ténart 	},
8741b44c5a6SAntoine Ténart };
8751b44c5a6SAntoine Ténart 
8761b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq)
8771b44c5a6SAntoine Ténart {
87841abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
879b869648cSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8801b44c5a6SAntoine Ténart 
88141abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
88241abed7dSPascal van Leeuwen 
88341abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
88441abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA1_DIGEST_SIZE);
88541abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
88631fb084cSPascal van Leeuwen 	req->len	= SHA1_BLOCK_SIZE;
88731fb084cSPascal van Leeuwen 	req->processed	= SHA1_BLOCK_SIZE;
88841abed7dSPascal van Leeuwen 
88941abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
89041abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
89141abed7dSPascal van Leeuwen 	req->state_sz = SHA1_DIGEST_SIZE;
89241abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
89341abed7dSPascal van Leeuwen 	req->hmac = true;
89441abed7dSPascal van Leeuwen 
8951b44c5a6SAntoine Ténart 	return 0;
8961b44c5a6SAntoine Ténart }
8971b44c5a6SAntoine Ténart 
8981b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq)
8991b44c5a6SAntoine Ténart {
9001b44c5a6SAntoine Ténart 	int ret = safexcel_hmac_sha1_init(areq);
9011b44c5a6SAntoine Ténart 
9021b44c5a6SAntoine Ténart 	if (ret)
9031b44c5a6SAntoine Ténart 		return ret;
9041b44c5a6SAntoine Ténart 
9051b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
9061b44c5a6SAntoine Ténart }
9071b44c5a6SAntoine Ténart 
9081b44c5a6SAntoine Ténart struct safexcel_ahash_result {
9091b44c5a6SAntoine Ténart 	struct completion completion;
9101b44c5a6SAntoine Ténart 	int error;
9111b44c5a6SAntoine Ténart };
9121b44c5a6SAntoine Ténart 
9131b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error)
9141b44c5a6SAntoine Ténart {
9151b44c5a6SAntoine Ténart 	struct safexcel_ahash_result *result = req->data;
9161b44c5a6SAntoine Ténart 
9171b44c5a6SAntoine Ténart 	if (error == -EINPROGRESS)
9181b44c5a6SAntoine Ténart 		return;
9191b44c5a6SAntoine Ténart 
9201b44c5a6SAntoine Ténart 	result->error = error;
9211b44c5a6SAntoine Ténart 	complete(&result->completion);
9221b44c5a6SAntoine Ténart }
9231b44c5a6SAntoine Ténart 
9241b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq,
9251b44c5a6SAntoine Ténart 				  unsigned int blocksize, const u8 *key,
9261b44c5a6SAntoine Ténart 				  unsigned int keylen, u8 *ipad, u8 *opad)
9271b44c5a6SAntoine Ténart {
9281b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
9291b44c5a6SAntoine Ténart 	struct scatterlist sg;
9301b44c5a6SAntoine Ténart 	int ret, i;
9311b44c5a6SAntoine Ténart 	u8 *keydup;
9321b44c5a6SAntoine Ténart 
9331b44c5a6SAntoine Ténart 	if (keylen <= blocksize) {
9341b44c5a6SAntoine Ténart 		memcpy(ipad, key, keylen);
9351b44c5a6SAntoine Ténart 	} else {
9361b44c5a6SAntoine Ténart 		keydup = kmemdup(key, keylen, GFP_KERNEL);
9371b44c5a6SAntoine Ténart 		if (!keydup)
9381b44c5a6SAntoine Ténart 			return -ENOMEM;
9391b44c5a6SAntoine Ténart 
9401b44c5a6SAntoine Ténart 		ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
9411b44c5a6SAntoine Ténart 					   safexcel_ahash_complete, &result);
9421b44c5a6SAntoine Ténart 		sg_init_one(&sg, keydup, keylen);
9431b44c5a6SAntoine Ténart 		ahash_request_set_crypt(areq, &sg, ipad, keylen);
9441b44c5a6SAntoine Ténart 		init_completion(&result.completion);
9451b44c5a6SAntoine Ténart 
9461b44c5a6SAntoine Ténart 		ret = crypto_ahash_digest(areq);
9474dc5475aSAntoine Tenart 		if (ret == -EINPROGRESS || ret == -EBUSY) {
9481b44c5a6SAntoine Ténart 			wait_for_completion_interruptible(&result.completion);
9491b44c5a6SAntoine Ténart 			ret = result.error;
9501b44c5a6SAntoine Ténart 		}
9511b44c5a6SAntoine Ténart 
9521b44c5a6SAntoine Ténart 		/* Avoid leaking */
9531b44c5a6SAntoine Ténart 		memzero_explicit(keydup, keylen);
9541b44c5a6SAntoine Ténart 		kfree(keydup);
9551b44c5a6SAntoine Ténart 
9561b44c5a6SAntoine Ténart 		if (ret)
9571b44c5a6SAntoine Ténart 			return ret;
9581b44c5a6SAntoine Ténart 
9591b44c5a6SAntoine Ténart 		keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq));
9601b44c5a6SAntoine Ténart 	}
9611b44c5a6SAntoine Ténart 
9621b44c5a6SAntoine Ténart 	memset(ipad + keylen, 0, blocksize - keylen);
9631b44c5a6SAntoine Ténart 	memcpy(opad, ipad, blocksize);
9641b44c5a6SAntoine Ténart 
9651b44c5a6SAntoine Ténart 	for (i = 0; i < blocksize; i++) {
966aed3731eSAntoine Ténart 		ipad[i] ^= HMAC_IPAD_VALUE;
967aed3731eSAntoine Ténart 		opad[i] ^= HMAC_OPAD_VALUE;
9681b44c5a6SAntoine Ténart 	}
9691b44c5a6SAntoine Ténart 
9701b44c5a6SAntoine Ténart 	return 0;
9711b44c5a6SAntoine Ténart }
9721b44c5a6SAntoine Ténart 
9731b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq,
9741b44c5a6SAntoine Ténart 				 unsigned int blocksize, u8 *pad, void *state)
9751b44c5a6SAntoine Ténart {
9761b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
9771b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req;
9781b44c5a6SAntoine Ténart 	struct scatterlist sg;
9791b44c5a6SAntoine Ténart 	int ret;
9801b44c5a6SAntoine Ténart 
9811b44c5a6SAntoine Ténart 	ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
9821b44c5a6SAntoine Ténart 				   safexcel_ahash_complete, &result);
9831b44c5a6SAntoine Ténart 	sg_init_one(&sg, pad, blocksize);
9841b44c5a6SAntoine Ténart 	ahash_request_set_crypt(areq, &sg, pad, blocksize);
9851b44c5a6SAntoine Ténart 	init_completion(&result.completion);
9861b44c5a6SAntoine Ténart 
9871b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
9881b44c5a6SAntoine Ténart 	if (ret)
9891b44c5a6SAntoine Ténart 		return ret;
9901b44c5a6SAntoine Ténart 
9911b44c5a6SAntoine Ténart 	req = ahash_request_ctx(areq);
9921b44c5a6SAntoine Ténart 	req->hmac = true;
9931b44c5a6SAntoine Ténart 	req->last_req = true;
9941b44c5a6SAntoine Ténart 
9951b44c5a6SAntoine Ténart 	ret = crypto_ahash_update(areq);
99612bf4142SOfer Heifetz 	if (ret && ret != -EINPROGRESS && ret != -EBUSY)
9971b44c5a6SAntoine Ténart 		return ret;
9981b44c5a6SAntoine Ténart 
9991b44c5a6SAntoine Ténart 	wait_for_completion_interruptible(&result.completion);
10001b44c5a6SAntoine Ténart 	if (result.error)
10011b44c5a6SAntoine Ténart 		return result.error;
10021b44c5a6SAntoine Ténart 
10031b44c5a6SAntoine Ténart 	return crypto_ahash_export(areq, state);
10041b44c5a6SAntoine Ténart }
10051b44c5a6SAntoine Ténart 
1006f6beaea3SAntoine Tenart int safexcel_hmac_setkey(const char *alg, const u8 *key, unsigned int keylen,
1007f6beaea3SAntoine Tenart 			 void *istate, void *ostate)
10081b44c5a6SAntoine Ténart {
10091b44c5a6SAntoine Ténart 	struct ahash_request *areq;
10101b44c5a6SAntoine Ténart 	struct crypto_ahash *tfm;
10111b44c5a6SAntoine Ténart 	unsigned int blocksize;
10121b44c5a6SAntoine Ténart 	u8 *ipad, *opad;
10131b44c5a6SAntoine Ténart 	int ret;
10141b44c5a6SAntoine Ténart 
101585d7311fSEric Biggers 	tfm = crypto_alloc_ahash(alg, 0, 0);
10161b44c5a6SAntoine Ténart 	if (IS_ERR(tfm))
10171b44c5a6SAntoine Ténart 		return PTR_ERR(tfm);
10181b44c5a6SAntoine Ténart 
10191b44c5a6SAntoine Ténart 	areq = ahash_request_alloc(tfm, GFP_KERNEL);
10201b44c5a6SAntoine Ténart 	if (!areq) {
10211b44c5a6SAntoine Ténart 		ret = -ENOMEM;
10221b44c5a6SAntoine Ténart 		goto free_ahash;
10231b44c5a6SAntoine Ténart 	}
10241b44c5a6SAntoine Ténart 
10251b44c5a6SAntoine Ténart 	crypto_ahash_clear_flags(tfm, ~0);
10261b44c5a6SAntoine Ténart 	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
10271b44c5a6SAntoine Ténart 
10286396bb22SKees Cook 	ipad = kcalloc(2, blocksize, GFP_KERNEL);
10291b44c5a6SAntoine Ténart 	if (!ipad) {
10301b44c5a6SAntoine Ténart 		ret = -ENOMEM;
10311b44c5a6SAntoine Ténart 		goto free_request;
10321b44c5a6SAntoine Ténart 	}
10331b44c5a6SAntoine Ténart 
10341b44c5a6SAntoine Ténart 	opad = ipad + blocksize;
10351b44c5a6SAntoine Ténart 
10361b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad);
10371b44c5a6SAntoine Ténart 	if (ret)
10381b44c5a6SAntoine Ténart 		goto free_ipad;
10391b44c5a6SAntoine Ténart 
10401b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate);
10411b44c5a6SAntoine Ténart 	if (ret)
10421b44c5a6SAntoine Ténart 		goto free_ipad;
10431b44c5a6SAntoine Ténart 
10441b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate);
10451b44c5a6SAntoine Ténart 
10461b44c5a6SAntoine Ténart free_ipad:
10471b44c5a6SAntoine Ténart 	kfree(ipad);
10481b44c5a6SAntoine Ténart free_request:
10491b44c5a6SAntoine Ténart 	ahash_request_free(areq);
10501b44c5a6SAntoine Ténart free_ahash:
10511b44c5a6SAntoine Ténart 	crypto_free_ahash(tfm);
10521b44c5a6SAntoine Ténart 
10531b44c5a6SAntoine Ténart 	return ret;
10541b44c5a6SAntoine Ténart }
10551b44c5a6SAntoine Ténart 
105673f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key,
105773f36ea7SAntoine Tenart 				    unsigned int keylen, const char *alg,
105873f36ea7SAntoine Tenart 				    unsigned int state_sz)
10591b44c5a6SAntoine Ténart {
10601b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1061871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
10621b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state istate, ostate;
106341abed7dSPascal van Leeuwen 	int ret;
10641b44c5a6SAntoine Ténart 
106573f36ea7SAntoine Tenart 	ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate);
10661b44c5a6SAntoine Ténart 	if (ret)
10671b44c5a6SAntoine Ténart 		return ret;
10681b44c5a6SAntoine Ténart 
106941abed7dSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr &&
107041abed7dSPascal van Leeuwen 	    (memcmp(ctx->ipad, istate.state, state_sz) ||
107141abed7dSPascal van Leeuwen 	     memcmp(ctx->opad, ostate.state, state_sz)))
10721b44c5a6SAntoine Ténart 		ctx->base.needs_inv = true;
10731b44c5a6SAntoine Ténart 
107473f36ea7SAntoine Tenart 	memcpy(ctx->ipad, &istate.state, state_sz);
107573f36ea7SAntoine Tenart 	memcpy(ctx->opad, &ostate.state, state_sz);
107642ef3bedSAntoine Ténart 
10771b44c5a6SAntoine Ténart 	return 0;
10781b44c5a6SAntoine Ténart }
10791b44c5a6SAntoine Ténart 
108073f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
108173f36ea7SAntoine Tenart 				     unsigned int keylen)
108273f36ea7SAntoine Tenart {
108373f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1",
108473f36ea7SAntoine Tenart 					SHA1_DIGEST_SIZE);
108573f36ea7SAntoine Tenart }
108673f36ea7SAntoine Tenart 
10871b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = {
10881b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1089062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
10901b44c5a6SAntoine Ténart 	.alg.ahash = {
10911b44c5a6SAntoine Ténart 		.init = safexcel_hmac_sha1_init,
10921b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
10931b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
10941b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
10951b44c5a6SAntoine Ténart 		.digest = safexcel_hmac_sha1_digest,
10961b44c5a6SAntoine Ténart 		.setkey = safexcel_hmac_sha1_setkey,
10971b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
10981b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
10991b44c5a6SAntoine Ténart 		.halg = {
11001b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
11011b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
11021b44c5a6SAntoine Ténart 			.base = {
11031b44c5a6SAntoine Ténart 				.cra_name = "hmac(sha1)",
11041b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-hmac-sha1",
1105aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
11061b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
11071b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
11081b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
11091b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
11101b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
11111b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
11121b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
11131b44c5a6SAntoine Ténart 			},
11141b44c5a6SAntoine Ténart 		},
11151b44c5a6SAntoine Ténart 	},
11161b44c5a6SAntoine Ténart };
11171b44c5a6SAntoine Ténart 
11181b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq)
11191b44c5a6SAntoine Ténart {
11201b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
11211b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
11221b44c5a6SAntoine Ténart 
11231b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
11241b44c5a6SAntoine Ténart 
11251b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1126b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
11271b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
112841abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
11291b44c5a6SAntoine Ténart 
11301b44c5a6SAntoine Ténart 	return 0;
11311b44c5a6SAntoine Ténart }
11321b44c5a6SAntoine Ténart 
11331b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq)
11341b44c5a6SAntoine Ténart {
11351b44c5a6SAntoine Ténart 	int ret = safexcel_sha256_init(areq);
11361b44c5a6SAntoine Ténart 
11371b44c5a6SAntoine Ténart 	if (ret)
11381b44c5a6SAntoine Ténart 		return ret;
11391b44c5a6SAntoine Ténart 
11401b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
11411b44c5a6SAntoine Ténart }
11421b44c5a6SAntoine Ténart 
11431b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = {
11441b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1145062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
11461b44c5a6SAntoine Ténart 	.alg.ahash = {
11471b44c5a6SAntoine Ténart 		.init = safexcel_sha256_init,
11481b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
11491b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
11501b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
11511b44c5a6SAntoine Ténart 		.digest = safexcel_sha256_digest,
11521b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
11531b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
11541b44c5a6SAntoine Ténart 		.halg = {
11551b44c5a6SAntoine Ténart 			.digestsize = SHA256_DIGEST_SIZE,
11561b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
11571b44c5a6SAntoine Ténart 			.base = {
11581b44c5a6SAntoine Ténart 				.cra_name = "sha256",
11591b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha256",
1160aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
11611b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
11621b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
11631b44c5a6SAntoine Ténart 				.cra_blocksize = SHA256_BLOCK_SIZE,
11641b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
11651b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
11661b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
11671b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
11681b44c5a6SAntoine Ténart 			},
11691b44c5a6SAntoine Ténart 		},
11701b44c5a6SAntoine Ténart 	},
11711b44c5a6SAntoine Ténart };
11721b44c5a6SAntoine Ténart 
11731b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq)
11741b44c5a6SAntoine Ténart {
11751b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
11761b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
11771b44c5a6SAntoine Ténart 
11781b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
11791b44c5a6SAntoine Ténart 
11801b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1181b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
11821b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
118341abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
11841b44c5a6SAntoine Ténart 
11851b44c5a6SAntoine Ténart 	return 0;
11861b44c5a6SAntoine Ténart }
11871b44c5a6SAntoine Ténart 
11881b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq)
11891b44c5a6SAntoine Ténart {
11901b44c5a6SAntoine Ténart 	int ret = safexcel_sha224_init(areq);
11911b44c5a6SAntoine Ténart 
11921b44c5a6SAntoine Ténart 	if (ret)
11931b44c5a6SAntoine Ténart 		return ret;
11941b44c5a6SAntoine Ténart 
11951b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
11961b44c5a6SAntoine Ténart }
11971b44c5a6SAntoine Ténart 
11981b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = {
11991b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1200062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
12011b44c5a6SAntoine Ténart 	.alg.ahash = {
12021b44c5a6SAntoine Ténart 		.init = safexcel_sha224_init,
12031b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12041b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12051b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12061b44c5a6SAntoine Ténart 		.digest = safexcel_sha224_digest,
12071b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12081b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12091b44c5a6SAntoine Ténart 		.halg = {
12101b44c5a6SAntoine Ténart 			.digestsize = SHA224_DIGEST_SIZE,
12111b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12121b44c5a6SAntoine Ténart 			.base = {
12131b44c5a6SAntoine Ténart 				.cra_name = "sha224",
12141b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha224",
1215aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12161b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
12171b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12181b44c5a6SAntoine Ténart 				.cra_blocksize = SHA224_BLOCK_SIZE,
12191b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12201b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
12211b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
12221b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
12231b44c5a6SAntoine Ténart 			},
12241b44c5a6SAntoine Ténart 		},
12251b44c5a6SAntoine Ténart 	},
12261b44c5a6SAntoine Ténart };
122773f36ea7SAntoine Tenart 
12283ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key,
12293ad618d8SAntoine Tenart 				       unsigned int keylen)
12303ad618d8SAntoine Tenart {
12313ad618d8SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224",
12323ad618d8SAntoine Tenart 					SHA256_DIGEST_SIZE);
12333ad618d8SAntoine Tenart }
12343ad618d8SAntoine Tenart 
12353ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq)
12363ad618d8SAntoine Tenart {
123741abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
12383ad618d8SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
12393ad618d8SAntoine Tenart 
124041abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
124141abed7dSPascal van Leeuwen 
124241abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
124341abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE);
124441abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
124531fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
124631fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
124741abed7dSPascal van Leeuwen 
124841abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
124941abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
125041abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
125141abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
125241abed7dSPascal van Leeuwen 	req->hmac = true;
125341abed7dSPascal van Leeuwen 
12543ad618d8SAntoine Tenart 	return 0;
12553ad618d8SAntoine Tenart }
12563ad618d8SAntoine Tenart 
12573ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq)
12583ad618d8SAntoine Tenart {
12593ad618d8SAntoine Tenart 	int ret = safexcel_hmac_sha224_init(areq);
12603ad618d8SAntoine Tenart 
12613ad618d8SAntoine Tenart 	if (ret)
12623ad618d8SAntoine Tenart 		return ret;
12633ad618d8SAntoine Tenart 
12643ad618d8SAntoine Tenart 	return safexcel_ahash_finup(areq);
12653ad618d8SAntoine Tenart }
12663ad618d8SAntoine Tenart 
12673ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = {
12683ad618d8SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1269062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
12703ad618d8SAntoine Tenart 	.alg.ahash = {
12713ad618d8SAntoine Tenart 		.init = safexcel_hmac_sha224_init,
12723ad618d8SAntoine Tenart 		.update = safexcel_ahash_update,
12733ad618d8SAntoine Tenart 		.final = safexcel_ahash_final,
12743ad618d8SAntoine Tenart 		.finup = safexcel_ahash_finup,
12753ad618d8SAntoine Tenart 		.digest = safexcel_hmac_sha224_digest,
12763ad618d8SAntoine Tenart 		.setkey = safexcel_hmac_sha224_setkey,
12773ad618d8SAntoine Tenart 		.export = safexcel_ahash_export,
12783ad618d8SAntoine Tenart 		.import = safexcel_ahash_import,
12793ad618d8SAntoine Tenart 		.halg = {
12803ad618d8SAntoine Tenart 			.digestsize = SHA224_DIGEST_SIZE,
12813ad618d8SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12823ad618d8SAntoine Tenart 			.base = {
12833ad618d8SAntoine Tenart 				.cra_name = "hmac(sha224)",
12843ad618d8SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha224",
1285aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12863ad618d8SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
12873ad618d8SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12883ad618d8SAntoine Tenart 				.cra_blocksize = SHA224_BLOCK_SIZE,
12893ad618d8SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12903ad618d8SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
12913ad618d8SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
12923ad618d8SAntoine Tenart 				.cra_module = THIS_MODULE,
12933ad618d8SAntoine Tenart 			},
12943ad618d8SAntoine Tenart 		},
12953ad618d8SAntoine Tenart 	},
12963ad618d8SAntoine Tenart };
12973ad618d8SAntoine Tenart 
129873f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
129973f36ea7SAntoine Tenart 				     unsigned int keylen)
130073f36ea7SAntoine Tenart {
130173f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256",
130273f36ea7SAntoine Tenart 					SHA256_DIGEST_SIZE);
130373f36ea7SAntoine Tenart }
130473f36ea7SAntoine Tenart 
130573f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq)
130673f36ea7SAntoine Tenart {
130741abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
130873f36ea7SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
130973f36ea7SAntoine Tenart 
131041abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
131141abed7dSPascal van Leeuwen 
131241abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
131341abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE);
131441abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
131531fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
131631fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
131741abed7dSPascal van Leeuwen 
131841abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
131941abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
132041abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
132141abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
132241abed7dSPascal van Leeuwen 	req->hmac = true;
132341abed7dSPascal van Leeuwen 
132473f36ea7SAntoine Tenart 	return 0;
132573f36ea7SAntoine Tenart }
132673f36ea7SAntoine Tenart 
132773f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq)
132873f36ea7SAntoine Tenart {
132973f36ea7SAntoine Tenart 	int ret = safexcel_hmac_sha256_init(areq);
133073f36ea7SAntoine Tenart 
133173f36ea7SAntoine Tenart 	if (ret)
133273f36ea7SAntoine Tenart 		return ret;
133373f36ea7SAntoine Tenart 
133473f36ea7SAntoine Tenart 	return safexcel_ahash_finup(areq);
133573f36ea7SAntoine Tenart }
133673f36ea7SAntoine Tenart 
133773f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = {
133873f36ea7SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1339062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
134073f36ea7SAntoine Tenart 	.alg.ahash = {
134173f36ea7SAntoine Tenart 		.init = safexcel_hmac_sha256_init,
134273f36ea7SAntoine Tenart 		.update = safexcel_ahash_update,
134373f36ea7SAntoine Tenart 		.final = safexcel_ahash_final,
134473f36ea7SAntoine Tenart 		.finup = safexcel_ahash_finup,
134573f36ea7SAntoine Tenart 		.digest = safexcel_hmac_sha256_digest,
134673f36ea7SAntoine Tenart 		.setkey = safexcel_hmac_sha256_setkey,
134773f36ea7SAntoine Tenart 		.export = safexcel_ahash_export,
134873f36ea7SAntoine Tenart 		.import = safexcel_ahash_import,
134973f36ea7SAntoine Tenart 		.halg = {
135073f36ea7SAntoine Tenart 			.digestsize = SHA256_DIGEST_SIZE,
135173f36ea7SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
135273f36ea7SAntoine Tenart 			.base = {
135373f36ea7SAntoine Tenart 				.cra_name = "hmac(sha256)",
135473f36ea7SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha256",
1355aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
135673f36ea7SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
135773f36ea7SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
135873f36ea7SAntoine Tenart 				.cra_blocksize = SHA256_BLOCK_SIZE,
135973f36ea7SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
136073f36ea7SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
136173f36ea7SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
136273f36ea7SAntoine Tenart 				.cra_module = THIS_MODULE,
136373f36ea7SAntoine Tenart 			},
136473f36ea7SAntoine Tenart 		},
136573f36ea7SAntoine Tenart 	},
136673f36ea7SAntoine Tenart };
1367b460edb6SAntoine Tenart 
1368b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq)
1369b460edb6SAntoine Tenart {
1370b460edb6SAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1371b460edb6SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1372b460edb6SAntoine Tenart 
1373b460edb6SAntoine Tenart 	memset(req, 0, sizeof(*req));
1374b460edb6SAntoine Tenart 
1375b460edb6SAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
1376b460edb6SAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1377b460edb6SAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
137841abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
1379b460edb6SAntoine Tenart 
1380b460edb6SAntoine Tenart 	return 0;
1381b460edb6SAntoine Tenart }
1382b460edb6SAntoine Tenart 
1383b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq)
1384b460edb6SAntoine Tenart {
1385b460edb6SAntoine Tenart 	int ret = safexcel_sha512_init(areq);
1386b460edb6SAntoine Tenart 
1387b460edb6SAntoine Tenart 	if (ret)
1388b460edb6SAntoine Tenart 		return ret;
1389b460edb6SAntoine Tenart 
1390b460edb6SAntoine Tenart 	return safexcel_ahash_finup(areq);
1391b460edb6SAntoine Tenart }
1392b460edb6SAntoine Tenart 
1393b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = {
1394b460edb6SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1395062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
1396b460edb6SAntoine Tenart 	.alg.ahash = {
1397b460edb6SAntoine Tenart 		.init = safexcel_sha512_init,
1398b460edb6SAntoine Tenart 		.update = safexcel_ahash_update,
1399b460edb6SAntoine Tenart 		.final = safexcel_ahash_final,
1400b460edb6SAntoine Tenart 		.finup = safexcel_ahash_finup,
1401b460edb6SAntoine Tenart 		.digest = safexcel_sha512_digest,
1402b460edb6SAntoine Tenart 		.export = safexcel_ahash_export,
1403b460edb6SAntoine Tenart 		.import = safexcel_ahash_import,
1404b460edb6SAntoine Tenart 		.halg = {
1405b460edb6SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
1406b460edb6SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
1407b460edb6SAntoine Tenart 			.base = {
1408b460edb6SAntoine Tenart 				.cra_name = "sha512",
1409b460edb6SAntoine Tenart 				.cra_driver_name = "safexcel-sha512",
1410aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1411b460edb6SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1412b460edb6SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1413b460edb6SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
1414b460edb6SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1415b460edb6SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
1416b460edb6SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
1417b460edb6SAntoine Tenart 				.cra_module = THIS_MODULE,
1418b460edb6SAntoine Tenart 			},
1419b460edb6SAntoine Tenart 		},
1420b460edb6SAntoine Tenart 	},
1421b460edb6SAntoine Tenart };
14220de54fb1SAntoine Tenart 
14239e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq)
14249e46eafdSAntoine Tenart {
14259e46eafdSAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
14269e46eafdSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
14279e46eafdSAntoine Tenart 
14289e46eafdSAntoine Tenart 	memset(req, 0, sizeof(*req));
14299e46eafdSAntoine Tenart 
14309e46eafdSAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
14319e46eafdSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
14329e46eafdSAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
143341abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
14349e46eafdSAntoine Tenart 
14359e46eafdSAntoine Tenart 	return 0;
14369e46eafdSAntoine Tenart }
14379e46eafdSAntoine Tenart 
14389e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq)
14399e46eafdSAntoine Tenart {
14409e46eafdSAntoine Tenart 	int ret = safexcel_sha384_init(areq);
14419e46eafdSAntoine Tenart 
14429e46eafdSAntoine Tenart 	if (ret)
14439e46eafdSAntoine Tenart 		return ret;
14449e46eafdSAntoine Tenart 
14459e46eafdSAntoine Tenart 	return safexcel_ahash_finup(areq);
14469e46eafdSAntoine Tenart }
14479e46eafdSAntoine Tenart 
14489e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = {
14499e46eafdSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1450062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
14519e46eafdSAntoine Tenart 	.alg.ahash = {
14529e46eafdSAntoine Tenart 		.init = safexcel_sha384_init,
14539e46eafdSAntoine Tenart 		.update = safexcel_ahash_update,
14549e46eafdSAntoine Tenart 		.final = safexcel_ahash_final,
14559e46eafdSAntoine Tenart 		.finup = safexcel_ahash_finup,
14569e46eafdSAntoine Tenart 		.digest = safexcel_sha384_digest,
14579e46eafdSAntoine Tenart 		.export = safexcel_ahash_export,
14589e46eafdSAntoine Tenart 		.import = safexcel_ahash_import,
14599e46eafdSAntoine Tenart 		.halg = {
14609e46eafdSAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
14619e46eafdSAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
14629e46eafdSAntoine Tenart 			.base = {
14639e46eafdSAntoine Tenart 				.cra_name = "sha384",
14649e46eafdSAntoine Tenart 				.cra_driver_name = "safexcel-sha384",
1465aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
14669e46eafdSAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
14679e46eafdSAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
14689e46eafdSAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
14699e46eafdSAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
14709e46eafdSAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
14719e46eafdSAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
14729e46eafdSAntoine Tenart 				.cra_module = THIS_MODULE,
14739e46eafdSAntoine Tenart 			},
14749e46eafdSAntoine Tenart 		},
14759e46eafdSAntoine Tenart 	},
14769e46eafdSAntoine Tenart };
14779e46eafdSAntoine Tenart 
14780de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key,
14790de54fb1SAntoine Tenart 				       unsigned int keylen)
14800de54fb1SAntoine Tenart {
14810de54fb1SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512",
14820de54fb1SAntoine Tenart 					SHA512_DIGEST_SIZE);
14830de54fb1SAntoine Tenart }
14840de54fb1SAntoine Tenart 
14850de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq)
14860de54fb1SAntoine Tenart {
148741abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
14880de54fb1SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
14890de54fb1SAntoine Tenart 
149041abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
149141abed7dSPascal van Leeuwen 
149241abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
149341abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE);
149441abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
149531fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
149631fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
149741abed7dSPascal van Leeuwen 
149841abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
149941abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
150041abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
150141abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
150241abed7dSPascal van Leeuwen 	req->hmac = true;
150341abed7dSPascal van Leeuwen 
15040de54fb1SAntoine Tenart 	return 0;
15050de54fb1SAntoine Tenart }
15060de54fb1SAntoine Tenart 
15070de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq)
15080de54fb1SAntoine Tenart {
15090de54fb1SAntoine Tenart 	int ret = safexcel_hmac_sha512_init(areq);
15100de54fb1SAntoine Tenart 
15110de54fb1SAntoine Tenart 	if (ret)
15120de54fb1SAntoine Tenart 		return ret;
15130de54fb1SAntoine Tenart 
15140de54fb1SAntoine Tenart 	return safexcel_ahash_finup(areq);
15150de54fb1SAntoine Tenart }
15160de54fb1SAntoine Tenart 
15170de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = {
15180de54fb1SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1519062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
15200de54fb1SAntoine Tenart 	.alg.ahash = {
15210de54fb1SAntoine Tenart 		.init = safexcel_hmac_sha512_init,
15220de54fb1SAntoine Tenart 		.update = safexcel_ahash_update,
15230de54fb1SAntoine Tenart 		.final = safexcel_ahash_final,
15240de54fb1SAntoine Tenart 		.finup = safexcel_ahash_finup,
15250de54fb1SAntoine Tenart 		.digest = safexcel_hmac_sha512_digest,
15260de54fb1SAntoine Tenart 		.setkey = safexcel_hmac_sha512_setkey,
15270de54fb1SAntoine Tenart 		.export = safexcel_ahash_export,
15280de54fb1SAntoine Tenart 		.import = safexcel_ahash_import,
15290de54fb1SAntoine Tenart 		.halg = {
15300de54fb1SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
15310de54fb1SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
15320de54fb1SAntoine Tenart 			.base = {
15330de54fb1SAntoine Tenart 				.cra_name = "hmac(sha512)",
15340de54fb1SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha512",
1535aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
15360de54fb1SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
15370de54fb1SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
15380de54fb1SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
15390de54fb1SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
15400de54fb1SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
15410de54fb1SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
15420de54fb1SAntoine Tenart 				.cra_module = THIS_MODULE,
15430de54fb1SAntoine Tenart 			},
15440de54fb1SAntoine Tenart 		},
15450de54fb1SAntoine Tenart 	},
15460de54fb1SAntoine Tenart };
15471f5d5d98SAntoine Tenart 
15481f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key,
15491f5d5d98SAntoine Tenart 				       unsigned int keylen)
15501f5d5d98SAntoine Tenart {
15511f5d5d98SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384",
15521f5d5d98SAntoine Tenart 					SHA512_DIGEST_SIZE);
15531f5d5d98SAntoine Tenart }
15541f5d5d98SAntoine Tenart 
15551f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq)
15561f5d5d98SAntoine Tenart {
155741abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
15581f5d5d98SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
15591f5d5d98SAntoine Tenart 
156041abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
156141abed7dSPascal van Leeuwen 
156241abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
156341abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE);
156441abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
156531fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
156631fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
156741abed7dSPascal van Leeuwen 
156841abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
156941abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
157041abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
157141abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
157241abed7dSPascal van Leeuwen 	req->hmac = true;
157341abed7dSPascal van Leeuwen 
15741f5d5d98SAntoine Tenart 	return 0;
15751f5d5d98SAntoine Tenart }
15761f5d5d98SAntoine Tenart 
15771f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq)
15781f5d5d98SAntoine Tenart {
15791f5d5d98SAntoine Tenart 	int ret = safexcel_hmac_sha384_init(areq);
15801f5d5d98SAntoine Tenart 
15811f5d5d98SAntoine Tenart 	if (ret)
15821f5d5d98SAntoine Tenart 		return ret;
15831f5d5d98SAntoine Tenart 
15841f5d5d98SAntoine Tenart 	return safexcel_ahash_finup(areq);
15851f5d5d98SAntoine Tenart }
15861f5d5d98SAntoine Tenart 
15871f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = {
15881f5d5d98SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1589062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
15901f5d5d98SAntoine Tenart 	.alg.ahash = {
15911f5d5d98SAntoine Tenart 		.init = safexcel_hmac_sha384_init,
15921f5d5d98SAntoine Tenart 		.update = safexcel_ahash_update,
15931f5d5d98SAntoine Tenart 		.final = safexcel_ahash_final,
15941f5d5d98SAntoine Tenart 		.finup = safexcel_ahash_finup,
15951f5d5d98SAntoine Tenart 		.digest = safexcel_hmac_sha384_digest,
15961f5d5d98SAntoine Tenart 		.setkey = safexcel_hmac_sha384_setkey,
15971f5d5d98SAntoine Tenart 		.export = safexcel_ahash_export,
15981f5d5d98SAntoine Tenart 		.import = safexcel_ahash_import,
15991f5d5d98SAntoine Tenart 		.halg = {
16001f5d5d98SAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
16011f5d5d98SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
16021f5d5d98SAntoine Tenart 			.base = {
16031f5d5d98SAntoine Tenart 				.cra_name = "hmac(sha384)",
16041f5d5d98SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha384",
1605aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
16061f5d5d98SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
16071f5d5d98SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16081f5d5d98SAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
16091f5d5d98SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
16101f5d5d98SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
16111f5d5d98SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
16121f5d5d98SAntoine Tenart 				.cra_module = THIS_MODULE,
16131f5d5d98SAntoine Tenart 			},
16141f5d5d98SAntoine Tenart 		},
16151f5d5d98SAntoine Tenart 	},
16161f5d5d98SAntoine Tenart };
1617293f89cfSOfer Heifetz 
1618293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq)
1619293f89cfSOfer Heifetz {
1620293f89cfSOfer Heifetz 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1621293f89cfSOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1622293f89cfSOfer Heifetz 
1623293f89cfSOfer Heifetz 	memset(req, 0, sizeof(*req));
1624293f89cfSOfer Heifetz 
1625293f89cfSOfer Heifetz 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
1626293f89cfSOfer Heifetz 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1627293f89cfSOfer Heifetz 	req->state_sz = MD5_DIGEST_SIZE;
162841abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
1629293f89cfSOfer Heifetz 
1630293f89cfSOfer Heifetz 	return 0;
1631293f89cfSOfer Heifetz }
1632293f89cfSOfer Heifetz 
1633293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq)
1634293f89cfSOfer Heifetz {
1635293f89cfSOfer Heifetz 	int ret = safexcel_md5_init(areq);
1636293f89cfSOfer Heifetz 
1637293f89cfSOfer Heifetz 	if (ret)
1638293f89cfSOfer Heifetz 		return ret;
1639293f89cfSOfer Heifetz 
1640293f89cfSOfer Heifetz 	return safexcel_ahash_finup(areq);
1641293f89cfSOfer Heifetz }
1642293f89cfSOfer Heifetz 
1643293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = {
1644293f89cfSOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1645062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1646293f89cfSOfer Heifetz 	.alg.ahash = {
1647293f89cfSOfer Heifetz 		.init = safexcel_md5_init,
1648293f89cfSOfer Heifetz 		.update = safexcel_ahash_update,
1649293f89cfSOfer Heifetz 		.final = safexcel_ahash_final,
1650293f89cfSOfer Heifetz 		.finup = safexcel_ahash_finup,
1651293f89cfSOfer Heifetz 		.digest = safexcel_md5_digest,
1652293f89cfSOfer Heifetz 		.export = safexcel_ahash_export,
1653293f89cfSOfer Heifetz 		.import = safexcel_ahash_import,
1654293f89cfSOfer Heifetz 		.halg = {
1655293f89cfSOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1656293f89cfSOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1657293f89cfSOfer Heifetz 			.base = {
1658293f89cfSOfer Heifetz 				.cra_name = "md5",
1659293f89cfSOfer Heifetz 				.cra_driver_name = "safexcel-md5",
1660aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1661293f89cfSOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1662293f89cfSOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1663293f89cfSOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1664293f89cfSOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1665293f89cfSOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1666293f89cfSOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1667293f89cfSOfer Heifetz 				.cra_module = THIS_MODULE,
1668293f89cfSOfer Heifetz 			},
1669293f89cfSOfer Heifetz 		},
1670293f89cfSOfer Heifetz 	},
1671293f89cfSOfer Heifetz };
1672b471e4b9SOfer Heifetz 
1673b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq)
1674b471e4b9SOfer Heifetz {
167541abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1676b471e4b9SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1677b471e4b9SOfer Heifetz 
167841abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
167941abed7dSPascal van Leeuwen 
168041abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
168141abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, MD5_DIGEST_SIZE);
168241abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
168331fb084cSPascal van Leeuwen 	req->len	= MD5_HMAC_BLOCK_SIZE;
168431fb084cSPascal van Leeuwen 	req->processed	= MD5_HMAC_BLOCK_SIZE;
168541abed7dSPascal van Leeuwen 
168641abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
168741abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
168841abed7dSPascal van Leeuwen 	req->state_sz = MD5_DIGEST_SIZE;
168941abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
169085b36ee8SPascal van Leeuwen 	req->len_is_le = true; /* MD5 is little endian! ... */
169141abed7dSPascal van Leeuwen 	req->hmac = true;
169241abed7dSPascal van Leeuwen 
1693b471e4b9SOfer Heifetz 	return 0;
1694b471e4b9SOfer Heifetz }
1695b471e4b9SOfer Heifetz 
1696b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key,
1697b471e4b9SOfer Heifetz 				     unsigned int keylen)
1698b471e4b9SOfer Heifetz {
1699b471e4b9SOfer Heifetz 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5",
1700b471e4b9SOfer Heifetz 					MD5_DIGEST_SIZE);
1701b471e4b9SOfer Heifetz }
1702b471e4b9SOfer Heifetz 
1703b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq)
1704b471e4b9SOfer Heifetz {
1705b471e4b9SOfer Heifetz 	int ret = safexcel_hmac_md5_init(areq);
1706b471e4b9SOfer Heifetz 
1707b471e4b9SOfer Heifetz 	if (ret)
1708b471e4b9SOfer Heifetz 		return ret;
1709b471e4b9SOfer Heifetz 
1710b471e4b9SOfer Heifetz 	return safexcel_ahash_finup(areq);
1711b471e4b9SOfer Heifetz }
1712b471e4b9SOfer Heifetz 
1713b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = {
1714b471e4b9SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1715062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1716b471e4b9SOfer Heifetz 	.alg.ahash = {
1717b471e4b9SOfer Heifetz 		.init = safexcel_hmac_md5_init,
1718b471e4b9SOfer Heifetz 		.update = safexcel_ahash_update,
1719b471e4b9SOfer Heifetz 		.final = safexcel_ahash_final,
1720b471e4b9SOfer Heifetz 		.finup = safexcel_ahash_finup,
1721b471e4b9SOfer Heifetz 		.digest = safexcel_hmac_md5_digest,
1722b471e4b9SOfer Heifetz 		.setkey = safexcel_hmac_md5_setkey,
1723b471e4b9SOfer Heifetz 		.export = safexcel_ahash_export,
1724b471e4b9SOfer Heifetz 		.import = safexcel_ahash_import,
1725b471e4b9SOfer Heifetz 		.halg = {
1726b471e4b9SOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1727b471e4b9SOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1728b471e4b9SOfer Heifetz 			.base = {
1729b471e4b9SOfer Heifetz 				.cra_name = "hmac(md5)",
1730b471e4b9SOfer Heifetz 				.cra_driver_name = "safexcel-hmac-md5",
1731aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1732b471e4b9SOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1733b471e4b9SOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1734b471e4b9SOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1735b471e4b9SOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1736b471e4b9SOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1737b471e4b9SOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1738b471e4b9SOfer Heifetz 				.cra_module = THIS_MODULE,
1739b471e4b9SOfer Heifetz 			},
1740b471e4b9SOfer Heifetz 		},
1741b471e4b9SOfer Heifetz 	},
1742b471e4b9SOfer Heifetz };
1743