1301422e3SAntoine Tenart // SPDX-License-Identifier: GPL-2.0
21b44c5a6SAntoine Ténart /*
31b44c5a6SAntoine Ténart  * Copyright (C) 2017 Marvell
41b44c5a6SAntoine Ténart  *
51b44c5a6SAntoine Ténart  * Antoine Tenart <antoine.tenart@free-electrons.com>
61b44c5a6SAntoine Ténart  */
71b44c5a6SAntoine Ténart 
8b98687bbSPascal van Leeuwen #include <crypto/aes.h>
9aed3731eSAntoine Ténart #include <crypto/hmac.h>
10293f89cfSOfer Heifetz #include <crypto/md5.h>
111b44c5a6SAntoine Ténart #include <crypto/sha.h>
1238f21b4bSPascal van Leeuwen #include <crypto/skcipher.h>
130f2bc131SPascal van Leeuwen #include <crypto/sm3.h>
141b44c5a6SAntoine Ténart #include <linux/device.h>
151b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
161b44c5a6SAntoine Ténart #include <linux/dmapool.h>
171b44c5a6SAntoine Ténart 
181b44c5a6SAntoine Ténart #include "safexcel.h"
191b44c5a6SAntoine Ténart 
201b44c5a6SAntoine Ténart struct safexcel_ahash_ctx {
211b44c5a6SAntoine Ténart 	struct safexcel_context base;
221b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
231b44c5a6SAntoine Ténart 
241b44c5a6SAntoine Ténart 	u32 alg;
25b98687bbSPascal van Leeuwen 	u8  key_sz;
2638f21b4bSPascal van Leeuwen 	bool cbcmac;
271b44c5a6SAntoine Ténart 
280de54fb1SAntoine Tenart 	u32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)];
290de54fb1SAntoine Tenart 	u32 opad[SHA512_DIGEST_SIZE / sizeof(u32)];
3038f21b4bSPascal van Leeuwen 
3138f21b4bSPascal van Leeuwen 	struct crypto_cipher *kaes;
321b44c5a6SAntoine Ténart };
331b44c5a6SAntoine Ténart 
341b44c5a6SAntoine Ténart struct safexcel_ahash_req {
351b44c5a6SAntoine Ténart 	bool last_req;
361b44c5a6SAntoine Ténart 	bool finish;
371b44c5a6SAntoine Ténart 	bool hmac;
381eb7b403SOfer Heifetz 	bool needs_inv;
3985b36ee8SPascal van Leeuwen 	bool hmac_zlen;
4085b36ee8SPascal van Leeuwen 	bool len_is_le;
41b98687bbSPascal van Leeuwen 	bool not_first;
42b98687bbSPascal van Leeuwen 	bool xcbcmac;
431b44c5a6SAntoine Ténart 
44c957f8b3SAntoine Ténart 	int nents;
45b8592027SOfer Heifetz 	dma_addr_t result_dma;
46c957f8b3SAntoine Ténart 
47b869648cSAntoine Tenart 	u32 digest;
48b869648cSAntoine Tenart 
4941abed7dSPascal van Leeuwen 	u8 state_sz;    /* expected state size, only set once */
5041abed7dSPascal van Leeuwen 	u8 block_sz;    /* block size, only set once */
51b460edb6SAntoine Tenart 	u32 state[SHA512_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32));
521b44c5a6SAntoine Ténart 
5331fb084cSPascal van Leeuwen 	u64 len;
5431fb084cSPascal van Leeuwen 	u64 processed;
551b44c5a6SAntoine Ténart 
5641abed7dSPascal van Leeuwen 	u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32));
57cff9a175SAntoine Tenart 	dma_addr_t cache_dma;
58cff9a175SAntoine Tenart 	unsigned int cache_sz;
59cff9a175SAntoine Tenart 
6041abed7dSPascal van Leeuwen 	u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32));
611b44c5a6SAntoine Ténart };
621b44c5a6SAntoine Ténart 
63b460edb6SAntoine Tenart static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req)
64b460edb6SAntoine Tenart {
6531fb084cSPascal van Leeuwen 	return req->len - req->processed;
66b460edb6SAntoine Tenart }
67b460edb6SAntoine Tenart 
681b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc,
69b98687bbSPascal van Leeuwen 				u32 input_length, u32 result_length,
7038f21b4bSPascal van Leeuwen 				bool cbcmac)
711b44c5a6SAntoine Ténart {
721b44c5a6SAntoine Ténart 	struct safexcel_token *token =
731b44c5a6SAntoine Ténart 		(struct safexcel_token *)cdesc->control_data.token;
741b44c5a6SAntoine Ténart 
751b44c5a6SAntoine Ténart 	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
761b44c5a6SAntoine Ténart 	token[0].packet_length = input_length;
771b44c5a6SAntoine Ténart 	token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH;
781b44c5a6SAntoine Ténart 
79b98687bbSPascal van Leeuwen 	input_length &= 15;
8038f21b4bSPascal van Leeuwen 	if (unlikely(cbcmac && input_length)) {
811b44c5a6SAntoine Ténart 		token[1].opcode = EIP197_TOKEN_OPCODE_INSERT;
82b98687bbSPascal van Leeuwen 		token[1].packet_length = 16 - input_length;
83b98687bbSPascal van Leeuwen 		token[1].stat = EIP197_TOKEN_STAT_LAST_HASH;
84b98687bbSPascal van Leeuwen 		token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH;
85b98687bbSPascal van Leeuwen 	} else {
86b98687bbSPascal van Leeuwen 		token[0].stat = EIP197_TOKEN_STAT_LAST_HASH;
87b98687bbSPascal van Leeuwen 	}
88b98687bbSPascal van Leeuwen 
89b98687bbSPascal van Leeuwen 	token[2].opcode = EIP197_TOKEN_OPCODE_INSERT;
90b98687bbSPascal van Leeuwen 	token[2].stat = EIP197_TOKEN_STAT_LAST_HASH |
911b44c5a6SAntoine Ténart 			EIP197_TOKEN_STAT_LAST_PACKET;
92b98687bbSPascal van Leeuwen 	token[2].packet_length = result_length;
93b98687bbSPascal van Leeuwen 	token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
941b44c5a6SAntoine Ténart 				EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
951b44c5a6SAntoine Ténart }
961b44c5a6SAntoine Ténart 
971b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx,
981b44c5a6SAntoine Ténart 				     struct safexcel_ahash_req *req,
9941abed7dSPascal van Leeuwen 				     struct safexcel_command_desc *cdesc)
1001b44c5a6SAntoine Ténart {
101b460edb6SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
10241abed7dSPascal van Leeuwen 	u64 count = 0;
1031b44c5a6SAntoine Ténart 
104a7cf8658SPascal van Leeuwen 	cdesc->control_data.control0 = ctx->alg;
105dc5268b6SPascal van Leeuwen 
1061b44c5a6SAntoine Ténart 	/*
1071b44c5a6SAntoine Ténart 	 * Copy the input digest if needed, and setup the context
1081b44c5a6SAntoine Ténart 	 * fields. Do this now as we need it to setup the first command
1091b44c5a6SAntoine Ténart 	 * descriptor.
1101b44c5a6SAntoine Ténart 	 */
111a7cf8658SPascal van Leeuwen 	if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) {
112b98687bbSPascal van Leeuwen 		if (req->xcbcmac)
113b98687bbSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data, ctx->ipad, ctx->key_sz);
114b98687bbSPascal van Leeuwen 		else
115b98687bbSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
116a7cf8658SPascal van Leeuwen 
117b98687bbSPascal van Leeuwen 		if (!req->finish && req->xcbcmac)
118b98687bbSPascal van Leeuwen 			cdesc->control_data.control0 |=
119b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
120a7cf8658SPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
121b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_NO_FINISH_HASH |
122b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz /
123b98687bbSPascal van Leeuwen 						     sizeof(u32));
124b98687bbSPascal van Leeuwen 		else
125b98687bbSPascal van Leeuwen 			cdesc->control_data.control0 |=
126b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
127b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
128b98687bbSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz /
129b98687bbSPascal van Leeuwen 						     sizeof(u32));
130a7cf8658SPascal van Leeuwen 		return;
131a7cf8658SPascal van Leeuwen 	} else if (!req->processed) {
13241abed7dSPascal van Leeuwen 		/* First - and possibly only - block of basic hash only */
133b98687bbSPascal van Leeuwen 		if (req->finish)
134a7cf8658SPascal van Leeuwen 			cdesc->control_data.control0 |= req->digest |
13541abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
13641abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH  |
13741abed7dSPascal van Leeuwen 				/* ensure its not 0! */
13841abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
139b98687bbSPascal van Leeuwen 		else
140a7cf8658SPascal van Leeuwen 			cdesc->control_data.control0 |= req->digest |
14141abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT  |
14241abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_RESTART_HASH   |
14341abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_NO_FINISH_HASH |
14441abed7dSPascal van Leeuwen 				/* ensure its not 0! */
14541abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(1);
14641abed7dSPascal van Leeuwen 		return;
14741abed7dSPascal van Leeuwen 	}
14841abed7dSPascal van Leeuwen 
14941abed7dSPascal van Leeuwen 	/* Hash continuation or HMAC, setup (inner) digest from state */
15041abed7dSPascal van Leeuwen 	memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
1511b44c5a6SAntoine Ténart 
152b460edb6SAntoine Tenart 	if (req->finish) {
15341abed7dSPascal van Leeuwen 		/* Compute digest count for hash/HMAC finish operations */
15441abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
15531fb084cSPascal van Leeuwen 		    req->hmac_zlen || (req->processed != req->block_sz)) {
15631fb084cSPascal van Leeuwen 			count = req->processed / EIP197_COUNTER_BLOCK_SIZE;
157b460edb6SAntoine Tenart 
15841abed7dSPascal van Leeuwen 			/* This is a hardware limitation, as the
159b460edb6SAntoine Tenart 			 * counter must fit into an u32. This represents
16041abed7dSPascal van Leeuwen 			 * a fairly big amount of input data, so we
161b460edb6SAntoine Tenart 			 * shouldn't see this.
162b460edb6SAntoine Tenart 			 */
16341abed7dSPascal van Leeuwen 			if (unlikely(count & 0xffffffff00000000ULL)) {
164b460edb6SAntoine Tenart 				dev_warn(priv->dev,
165b460edb6SAntoine Tenart 					 "Input data is too big\n");
166b460edb6SAntoine Tenart 				return;
167b460edb6SAntoine Tenart 			}
168b460edb6SAntoine Tenart 		}
1691b44c5a6SAntoine Ténart 
17041abed7dSPascal van Leeuwen 		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
17185b36ee8SPascal van Leeuwen 		    /* Special case: zero length HMAC */
17285b36ee8SPascal van Leeuwen 		    req->hmac_zlen ||
17341abed7dSPascal van Leeuwen 		    /* PE HW < 4.4 cannot do HMAC continue, fake using hash */
17431fb084cSPascal van Leeuwen 		    (req->processed != req->block_sz)) {
17541abed7dSPascal van Leeuwen 			/* Basic hash continue operation, need digest + cnt */
17641abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
17741abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) |
17841abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
17941abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
18085b36ee8SPascal van Leeuwen 			/* For zero-len HMAC, don't finalize, already padded! */
18185b36ee8SPascal van Leeuwen 			if (req->hmac_zlen)
18285b36ee8SPascal van Leeuwen 				cdesc->control_data.control0 |=
18385b36ee8SPascal van Leeuwen 					CONTEXT_CONTROL_NO_FINISH_HASH;
18441abed7dSPascal van Leeuwen 			cdesc->control_data.control1 |=
18541abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_CNT;
18641abed7dSPascal van Leeuwen 			ctx->base.ctxr->data[req->state_sz >> 2] =
18741abed7dSPascal van Leeuwen 				cpu_to_le32(count);
18841abed7dSPascal van Leeuwen 			req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
18985b36ee8SPascal van Leeuwen 
19085b36ee8SPascal van Leeuwen 			/* Clear zero-length HMAC flag for next operation! */
19185b36ee8SPascal van Leeuwen 			req->hmac_zlen = false;
19241abed7dSPascal van Leeuwen 		} else { /* HMAC */
19341abed7dSPascal van Leeuwen 			/* Need outer digest for HMAC finalization */
19441abed7dSPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (req->state_sz >> 2),
1954505bb02SAntoine Tenart 			       ctx->opad, req->state_sz);
19641abed7dSPascal van Leeuwen 
19741abed7dSPascal van Leeuwen 			/* Single pass HMAC - no digest count */
19841abed7dSPascal van Leeuwen 			cdesc->control_data.control0 |=
19941abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(req->state_sz >> 1) |
20041abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_OUT |
20141abed7dSPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_HMAC;
20241abed7dSPascal van Leeuwen 		}
20341abed7dSPascal van Leeuwen 	} else { /* Hash continuation, do not finish yet */
20441abed7dSPascal van Leeuwen 		cdesc->control_data.control0 |=
20541abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_SIZE(req->state_sz >> 2) |
20641abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_DIGEST_PRECOMPUTED |
20741abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_TYPE_HASH_OUT |
20841abed7dSPascal van Leeuwen 			CONTEXT_CONTROL_NO_FINISH_HASH;
2091b44c5a6SAntoine Ténart 	}
2101b44c5a6SAntoine Ténart }
2111b44c5a6SAntoine Ténart 
21241abed7dSPascal van Leeuwen static int safexcel_ahash_enqueue(struct ahash_request *areq);
21341abed7dSPascal van Leeuwen 
21441abed7dSPascal van Leeuwen static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv,
21541abed7dSPascal van Leeuwen 				      int ring,
2161b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
2171b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
2181b44c5a6SAntoine Ténart {
2191b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
2201b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
2211b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2221b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *sreq = ahash_request_ctx(areq);
22341abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
224b460edb6SAntoine Tenart 	u64 cache_len;
2251b44c5a6SAntoine Ténart 
2261b44c5a6SAntoine Ténart 	*ret = 0;
2271b44c5a6SAntoine Ténart 
2281b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
2291b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
2301b44c5a6SAntoine Ténart 		dev_err(priv->dev,
2311b44c5a6SAntoine Ténart 			"hash: result: could not retrieve the result descriptor\n");
2321b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
233bdfd1909SAntoine Tenart 	} else {
234bdfd1909SAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
2351b44c5a6SAntoine Ténart 	}
2361b44c5a6SAntoine Ténart 
2371b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
2381b44c5a6SAntoine Ténart 
239c957f8b3SAntoine Ténart 	if (sreq->nents) {
240c957f8b3SAntoine Ténart 		dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE);
241c957f8b3SAntoine Ténart 		sreq->nents = 0;
242c957f8b3SAntoine Ténart 	}
2431b44c5a6SAntoine Ténart 
244b8592027SOfer Heifetz 	if (sreq->result_dma) {
245b8592027SOfer Heifetz 		dma_unmap_single(priv->dev, sreq->result_dma, sreq->state_sz,
246b8592027SOfer Heifetz 				 DMA_FROM_DEVICE);
247b8592027SOfer Heifetz 		sreq->result_dma = 0;
248b8592027SOfer Heifetz 	}
249b8592027SOfer Heifetz 
250cff9a175SAntoine Tenart 	if (sreq->cache_dma) {
251cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz,
252cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
253cff9a175SAntoine Tenart 		sreq->cache_dma = 0;
254aa524286SAntoine Tenart 		sreq->cache_sz = 0;
255cff9a175SAntoine Tenart 	}
2561b44c5a6SAntoine Ténart 
25741abed7dSPascal van Leeuwen 	if (sreq->finish) {
25841abed7dSPascal van Leeuwen 		if (sreq->hmac &&
25941abed7dSPascal van Leeuwen 		    (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) {
26041abed7dSPascal van Leeuwen 			/* Faking HMAC using hash - need to do outer hash */
26141abed7dSPascal van Leeuwen 			memcpy(sreq->cache, sreq->state,
26241abed7dSPascal van Leeuwen 			       crypto_ahash_digestsize(ahash));
26341abed7dSPascal van Leeuwen 
26441abed7dSPascal van Leeuwen 			memcpy(sreq->state, ctx->opad, sreq->state_sz);
26541abed7dSPascal van Leeuwen 
26631fb084cSPascal van Leeuwen 			sreq->len = sreq->block_sz +
26741abed7dSPascal van Leeuwen 				    crypto_ahash_digestsize(ahash);
26831fb084cSPascal van Leeuwen 			sreq->processed = sreq->block_sz;
26941abed7dSPascal van Leeuwen 			sreq->hmac = 0;
27041abed7dSPascal van Leeuwen 
27141abed7dSPascal van Leeuwen 			ctx->base.needs_inv = true;
27241abed7dSPascal van Leeuwen 			areq->nbytes = 0;
27341abed7dSPascal van Leeuwen 			safexcel_ahash_enqueue(areq);
27441abed7dSPascal van Leeuwen 
27541abed7dSPascal van Leeuwen 			*should_complete = false; /* Not done yet */
27641abed7dSPascal van Leeuwen 			return 1;
27741abed7dSPascal van Leeuwen 		}
27841abed7dSPascal van Leeuwen 
279b98687bbSPascal van Leeuwen 		if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM &&
280b98687bbSPascal van Leeuwen 			     ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) {
281a7cf8658SPascal van Leeuwen 			/* Undo final XOR with 0xffffffff ...*/
282a7cf8658SPascal van Leeuwen 			*(u32 *)areq->result = ~sreq->state[0];
283a7cf8658SPascal van Leeuwen 		} else {
284b89a8159SAntoine Tenart 			memcpy(areq->result, sreq->state,
285b89a8159SAntoine Tenart 			       crypto_ahash_digestsize(ahash));
28641abed7dSPascal van Leeuwen 		}
287a7cf8658SPascal van Leeuwen 	}
288b89a8159SAntoine Tenart 
289b460edb6SAntoine Tenart 	cache_len = safexcel_queued_len(sreq);
2901b44c5a6SAntoine Ténart 	if (cache_len)
2911b44c5a6SAntoine Ténart 		memcpy(sreq->cache, sreq->cache_next, cache_len);
2921b44c5a6SAntoine Ténart 
2931b44c5a6SAntoine Ténart 	*should_complete = true;
2941b44c5a6SAntoine Ténart 
2951b44c5a6SAntoine Ténart 	return 1;
2961b44c5a6SAntoine Ténart }
2971b44c5a6SAntoine Ténart 
2981eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring,
2991eb7b403SOfer Heifetz 				   int *commands, int *results)
3001b44c5a6SAntoine Ténart {
3011b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
3021b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
3031b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
3041b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
3051b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc, *first_cdesc = NULL;
3061b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
3071b44c5a6SAntoine Ténart 	struct scatterlist *sg;
308b98687bbSPascal van Leeuwen 	int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0, res_sz;
309b98687bbSPascal van Leeuwen 	u64 queued, len;
3101b44c5a6SAntoine Ténart 
311b98687bbSPascal van Leeuwen 	queued = safexcel_queued_len(req);
31241abed7dSPascal van Leeuwen 	if (queued <= HASH_CACHE_SIZE)
3131b44c5a6SAntoine Ténart 		cache_len = queued;
3141b44c5a6SAntoine Ténart 	else
3151b44c5a6SAntoine Ténart 		cache_len = queued - areq->nbytes;
3161b44c5a6SAntoine Ténart 
31741abed7dSPascal van Leeuwen 	if (!req->finish && !req->last_req) {
318809778e0SAntoine Ténart 		/* If this is not the last request and the queued data does not
31941abed7dSPascal van Leeuwen 		 * fit into full cache blocks, cache it for the next send call.
3201b44c5a6SAntoine Ténart 		 */
32141abed7dSPascal van Leeuwen 		extra = queued & (HASH_CACHE_SIZE - 1);
322082ec2d4SAntoine Tenart 
323809778e0SAntoine Ténart 		/* If this is not the last request and the queued data
324809778e0SAntoine Ténart 		 * is a multiple of a block, cache the last one for now.
325809778e0SAntoine Ténart 		 */
326dd4306a6SAntoine Tenart 		if (!extra)
32741abed7dSPascal van Leeuwen 			extra = HASH_CACHE_SIZE;
328809778e0SAntoine Ténart 
3291b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
330809778e0SAntoine Ténart 				   req->cache_next, extra,
331809778e0SAntoine Ténart 				   areq->nbytes - extra);
3321b44c5a6SAntoine Ténart 
3331b44c5a6SAntoine Ténart 		queued -= extra;
334dc5268b6SPascal van Leeuwen 
335dc5268b6SPascal van Leeuwen 		if (!queued) {
336dc5268b6SPascal van Leeuwen 			*commands = 0;
337dc5268b6SPascal van Leeuwen 			*results = 0;
338dc5268b6SPascal van Leeuwen 			return 0;
339dc5268b6SPascal van Leeuwen 		}
340b98687bbSPascal van Leeuwen 
341b98687bbSPascal van Leeuwen 		extra = 0;
342809778e0SAntoine Ténart 	}
3431b44c5a6SAntoine Ténart 
344b98687bbSPascal van Leeuwen 	if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) {
345b98687bbSPascal van Leeuwen 		if (unlikely(cache_len < AES_BLOCK_SIZE)) {
346b98687bbSPascal van Leeuwen 			/*
347b98687bbSPascal van Leeuwen 			 * Cache contains less than 1 full block, complete.
348b98687bbSPascal van Leeuwen 			 */
349b98687bbSPascal van Leeuwen 			extra = AES_BLOCK_SIZE - cache_len;
350b98687bbSPascal van Leeuwen 			if (queued > cache_len) {
351b98687bbSPascal van Leeuwen 				/* More data follows: borrow bytes */
352b98687bbSPascal van Leeuwen 				u64 tmp = queued - cache_len;
353b98687bbSPascal van Leeuwen 
354b98687bbSPascal van Leeuwen 				skip = min_t(u64, tmp, extra);
355b98687bbSPascal van Leeuwen 				sg_pcopy_to_buffer(areq->src,
356b98687bbSPascal van Leeuwen 					sg_nents(areq->src),
357b98687bbSPascal van Leeuwen 					req->cache + cache_len,
358b98687bbSPascal van Leeuwen 					skip, 0);
359b98687bbSPascal van Leeuwen 			}
360b98687bbSPascal van Leeuwen 			extra -= skip;
361b98687bbSPascal van Leeuwen 			memset(req->cache + cache_len + skip, 0, extra);
36238f21b4bSPascal van Leeuwen 			if (!ctx->cbcmac && extra) {
36338f21b4bSPascal van Leeuwen 				// 10- padding for XCBCMAC & CMAC
36438f21b4bSPascal van Leeuwen 				req->cache[cache_len + skip] = 0x80;
36538f21b4bSPascal van Leeuwen 				// HW will use K2 iso K3 - compensate!
36638f21b4bSPascal van Leeuwen 				for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
36738f21b4bSPascal van Leeuwen 					((u32 *)req->cache)[i] ^=
36838f21b4bSPascal van Leeuwen 						cpu_to_be32(ctx->ipad[i]) ^
36938f21b4bSPascal van Leeuwen 						cpu_to_be32(ctx->ipad[i + 4]);
37038f21b4bSPascal van Leeuwen 			}
371b98687bbSPascal van Leeuwen 			cache_len = AES_BLOCK_SIZE;
372b98687bbSPascal van Leeuwen 			queued = queued + extra;
373b98687bbSPascal van Leeuwen 		}
374b98687bbSPascal van Leeuwen 
375b98687bbSPascal van Leeuwen 		/* XCBC continue: XOR previous result into 1st word */
376b98687bbSPascal van Leeuwen 		crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE);
377b98687bbSPascal van Leeuwen 	}
378b98687bbSPascal van Leeuwen 
379b98687bbSPascal van Leeuwen 	len = queued;
3801b44c5a6SAntoine Ténart 	/* Add a command descriptor for the cached data, if any */
3811b44c5a6SAntoine Ténart 	if (cache_len) {
382cff9a175SAntoine Tenart 		req->cache_dma = dma_map_single(priv->dev, req->cache,
3831b44c5a6SAntoine Ténart 						cache_len, DMA_TO_DEVICE);
3849744fec9SOfer Heifetz 		if (dma_mapping_error(priv->dev, req->cache_dma))
385cff9a175SAntoine Tenart 			return -EINVAL;
3861b44c5a6SAntoine Ténart 
387cff9a175SAntoine Tenart 		req->cache_sz = cache_len;
3881b44c5a6SAntoine Ténart 		first_cdesc = safexcel_add_cdesc(priv, ring, 1,
3891b44c5a6SAntoine Ténart 						 (cache_len == len),
390b98687bbSPascal van Leeuwen 						 req->cache_dma, cache_len,
391b98687bbSPascal van Leeuwen 						 len, ctx->base.ctxr_dma);
3921b44c5a6SAntoine Ténart 		if (IS_ERR(first_cdesc)) {
3931b44c5a6SAntoine Ténart 			ret = PTR_ERR(first_cdesc);
3941b44c5a6SAntoine Ténart 			goto unmap_cache;
3951b44c5a6SAntoine Ténart 		}
3961b44c5a6SAntoine Ténart 		n_cdesc++;
3971b44c5a6SAntoine Ténart 
3981b44c5a6SAntoine Ténart 		queued -= cache_len;
3991b44c5a6SAntoine Ténart 		if (!queued)
4001b44c5a6SAntoine Ténart 			goto send_command;
4011b44c5a6SAntoine Ténart 	}
4021b44c5a6SAntoine Ténart 
4031b44c5a6SAntoine Ténart 	/* Now handle the current ahash request buffer(s) */
40441abed7dSPascal van Leeuwen 	req->nents = dma_map_sg(priv->dev, areq->src,
40541abed7dSPascal van Leeuwen 				sg_nents_for_len(areq->src,
40641abed7dSPascal van Leeuwen 						 areq->nbytes),
4071b44c5a6SAntoine Ténart 				DMA_TO_DEVICE);
408c957f8b3SAntoine Ténart 	if (!req->nents) {
4091b44c5a6SAntoine Ténart 		ret = -ENOMEM;
4101b44c5a6SAntoine Ténart 		goto cdesc_rollback;
4111b44c5a6SAntoine Ténart 	}
4121b44c5a6SAntoine Ténart 
413c957f8b3SAntoine Ténart 	for_each_sg(areq->src, sg, req->nents, i) {
4141b44c5a6SAntoine Ténart 		int sglen = sg_dma_len(sg);
4151b44c5a6SAntoine Ténart 
416b98687bbSPascal van Leeuwen 		if (unlikely(sglen <= skip)) {
417b98687bbSPascal van Leeuwen 			skip -= sglen;
418b98687bbSPascal van Leeuwen 			continue;
419b98687bbSPascal van Leeuwen 		}
420b98687bbSPascal van Leeuwen 
4211b44c5a6SAntoine Ténart 		/* Do not overflow the request */
422b98687bbSPascal van Leeuwen 		if ((queued + skip) <= sglen)
4231b44c5a6SAntoine Ténart 			sglen = queued;
424b98687bbSPascal van Leeuwen 		else
425b98687bbSPascal van Leeuwen 			sglen -= skip;
4261b44c5a6SAntoine Ténart 
4271b44c5a6SAntoine Ténart 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
42841abed7dSPascal van Leeuwen 					   !(queued - sglen),
429b98687bbSPascal van Leeuwen 					   sg_dma_address(sg) + skip, sglen,
430b98687bbSPascal van Leeuwen 					   len, ctx->base.ctxr_dma);
4311b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
4321b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
43357433b58SAntoine Tenart 			goto unmap_sg;
4341b44c5a6SAntoine Ténart 		}
4351b44c5a6SAntoine Ténart 
436b98687bbSPascal van Leeuwen 		if (!n_cdesc)
4371b44c5a6SAntoine Ténart 			first_cdesc = cdesc;
438b98687bbSPascal van Leeuwen 		n_cdesc++;
4391b44c5a6SAntoine Ténart 
4401b44c5a6SAntoine Ténart 		queued -= sglen;
4411b44c5a6SAntoine Ténart 		if (!queued)
4421b44c5a6SAntoine Ténart 			break;
443b98687bbSPascal van Leeuwen 		skip = 0;
4441b44c5a6SAntoine Ténart 	}
4451b44c5a6SAntoine Ténart 
4461b44c5a6SAntoine Ténart send_command:
4471b44c5a6SAntoine Ténart 	/* Setup the context options */
44841abed7dSPascal van Leeuwen 	safexcel_context_control(ctx, req, first_cdesc);
4491b44c5a6SAntoine Ténart 
450b98687bbSPascal van Leeuwen 	/* Add the token. Note that the XCBC result is only 1 AES block. */
451b98687bbSPascal van Leeuwen 	res_sz = req->xcbcmac ? AES_BLOCK_SIZE : req->state_sz;
45238f21b4bSPascal van Leeuwen 	safexcel_hash_token(first_cdesc, len, res_sz, ctx->cbcmac);
4531b44c5a6SAntoine Ténart 
454b8592027SOfer Heifetz 	req->result_dma = dma_map_single(priv->dev, req->state, req->state_sz,
455b8592027SOfer Heifetz 					 DMA_FROM_DEVICE);
456b8592027SOfer Heifetz 	if (dma_mapping_error(priv->dev, req->result_dma)) {
4571b44c5a6SAntoine Ténart 		ret = -EINVAL;
45857433b58SAntoine Tenart 		goto unmap_sg;
4591b44c5a6SAntoine Ténart 	}
4601b44c5a6SAntoine Ténart 
4611b44c5a6SAntoine Ténart 	/* Add a result descriptor */
462b8592027SOfer Heifetz 	rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma,
463b98687bbSPascal van Leeuwen 				   res_sz);
4641b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
4651b44c5a6SAntoine Ténart 		ret = PTR_ERR(rdesc);
46657240a78SAntoine Tenart 		goto unmap_result;
4671b44c5a6SAntoine Ténart 	}
4681b44c5a6SAntoine Ténart 
4699744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, rdesc, &areq->base);
4701b44c5a6SAntoine Ténart 
471b98687bbSPascal van Leeuwen 	req->processed += len - extra;
472b460edb6SAntoine Tenart 
4731b44c5a6SAntoine Ténart 	*commands = n_cdesc;
4741b44c5a6SAntoine Ténart 	*results = 1;
4751b44c5a6SAntoine Ténart 	return 0;
4761b44c5a6SAntoine Ténart 
47757240a78SAntoine Tenart unmap_result:
47857433b58SAntoine Tenart 	dma_unmap_single(priv->dev, req->result_dma, req->state_sz,
47957433b58SAntoine Tenart 			 DMA_FROM_DEVICE);
48057433b58SAntoine Tenart unmap_sg:
481b98687bbSPascal van Leeuwen 	if (req->nents) {
48257240a78SAntoine Tenart 		dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE);
483b98687bbSPascal van Leeuwen 		req->nents = 0;
484b98687bbSPascal van Leeuwen 	}
4851b44c5a6SAntoine Ténart cdesc_rollback:
4861b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
4871b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
4881b44c5a6SAntoine Ténart unmap_cache:
489cff9a175SAntoine Tenart 	if (req->cache_dma) {
490cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz,
491cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
492aa524286SAntoine Tenart 		req->cache_dma = 0;
493cff9a175SAntoine Tenart 		req->cache_sz = 0;
4941b44c5a6SAntoine Ténart 	}
4951b44c5a6SAntoine Ténart 
4961b44c5a6SAntoine Ténart 	return ret;
4971b44c5a6SAntoine Ténart }
4981b44c5a6SAntoine Ténart 
4991b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
5001b44c5a6SAntoine Ténart 				      int ring,
5011b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
5021b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
5031b44c5a6SAntoine Ténart {
5041b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
5051b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
5061b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
5071b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
5081b44c5a6SAntoine Ténart 	int enq_ret;
5091b44c5a6SAntoine Ténart 
5101b44c5a6SAntoine Ténart 	*ret = 0;
5111b44c5a6SAntoine Ténart 
5121b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
5131b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
5141b44c5a6SAntoine Ténart 		dev_err(priv->dev,
5151b44c5a6SAntoine Ténart 			"hash: invalidate: could not retrieve the result descriptor\n");
5161b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
517cda3e73aSAntoine Tenart 	} else {
518cda3e73aSAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
5191b44c5a6SAntoine Ténart 	}
5201b44c5a6SAntoine Ténart 
5211b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
5221b44c5a6SAntoine Ténart 
5231b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
5241b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
5251b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
5261b44c5a6SAntoine Ténart 
5271b44c5a6SAntoine Ténart 		*should_complete = true;
5281b44c5a6SAntoine Ténart 		return 1;
5291b44c5a6SAntoine Ténart 	}
5301b44c5a6SAntoine Ténart 
53186671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
53286671abbSAntoine Ténart 	ctx->base.ring = ring;
5331b44c5a6SAntoine Ténart 
53486671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
53586671abbSAntoine Ténart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async);
53686671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
5371b44c5a6SAntoine Ténart 
5381b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
5391b44c5a6SAntoine Ténart 		*ret = enq_ret;
5401b44c5a6SAntoine Ténart 
5418472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
5428472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
54386671abbSAntoine Ténart 
5441b44c5a6SAntoine Ténart 	*should_complete = false;
5451b44c5a6SAntoine Ténart 
5461b44c5a6SAntoine Ténart 	return 1;
5471b44c5a6SAntoine Ténart }
5481b44c5a6SAntoine Ténart 
5491eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring,
5501eb7b403SOfer Heifetz 				  struct crypto_async_request *async,
5511eb7b403SOfer Heifetz 				  bool *should_complete, int *ret)
5521eb7b403SOfer Heifetz {
5531eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
5541eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5551eb7b403SOfer Heifetz 	int err;
5561eb7b403SOfer Heifetz 
55753c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv);
558871df319SAntoine Ténart 
5591eb7b403SOfer Heifetz 	if (req->needs_inv) {
5601eb7b403SOfer Heifetz 		req->needs_inv = false;
5611eb7b403SOfer Heifetz 		err = safexcel_handle_inv_result(priv, ring, async,
5621eb7b403SOfer Heifetz 						 should_complete, ret);
5631eb7b403SOfer Heifetz 	} else {
5641eb7b403SOfer Heifetz 		err = safexcel_handle_req_result(priv, ring, async,
5651eb7b403SOfer Heifetz 						 should_complete, ret);
5661eb7b403SOfer Heifetz 	}
5671eb7b403SOfer Heifetz 
5681eb7b403SOfer Heifetz 	return err;
5691eb7b403SOfer Heifetz }
5701eb7b403SOfer Heifetz 
5711b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async,
5729744fec9SOfer Heifetz 				   int ring, int *commands, int *results)
5731b44c5a6SAntoine Ténart {
5741b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
5751b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
5761b44c5a6SAntoine Ténart 	int ret;
5771b44c5a6SAntoine Ténart 
5785290ad6eSOfer Heifetz 	ret = safexcel_invalidate_cache(async, ctx->priv,
5799744fec9SOfer Heifetz 					ctx->base.ctxr_dma, ring);
5801b44c5a6SAntoine Ténart 	if (unlikely(ret))
5811b44c5a6SAntoine Ténart 		return ret;
5821b44c5a6SAntoine Ténart 
5831b44c5a6SAntoine Ténart 	*commands = 1;
5841b44c5a6SAntoine Ténart 	*results = 1;
5851b44c5a6SAntoine Ténart 
5861b44c5a6SAntoine Ténart 	return 0;
5871b44c5a6SAntoine Ténart }
5881b44c5a6SAntoine Ténart 
5891eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async,
5909744fec9SOfer Heifetz 			       int ring, int *commands, int *results)
5911eb7b403SOfer Heifetz {
5921eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
5931eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5941eb7b403SOfer Heifetz 	int ret;
5951eb7b403SOfer Heifetz 
5961eb7b403SOfer Heifetz 	if (req->needs_inv)
5979744fec9SOfer Heifetz 		ret = safexcel_ahash_send_inv(async, ring, commands, results);
5981eb7b403SOfer Heifetz 	else
5999744fec9SOfer Heifetz 		ret = safexcel_ahash_send_req(async, ring, commands, results);
6009744fec9SOfer Heifetz 
6011eb7b403SOfer Heifetz 	return ret;
6021eb7b403SOfer Heifetz }
6031eb7b403SOfer Heifetz 
6041b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm)
6051b44c5a6SAntoine Ténart {
6061b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
6071b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
60861824806SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE);
6097cad2fabSAntoine Ténart 	struct safexcel_ahash_req *rctx = ahash_request_ctx(req);
6103e1166b9SArnd Bergmann 	struct safexcel_inv_result result = {};
61186671abbSAntoine Ténart 	int ring = ctx->base.ring;
6121b44c5a6SAntoine Ténart 
613b926213dSAntoine Tenart 	memset(req, 0, EIP197_AHASH_REQ_SIZE);
6141b44c5a6SAntoine Ténart 
6151b44c5a6SAntoine Ténart 	/* create invalidation request */
6161b44c5a6SAntoine Ténart 	init_completion(&result.completion);
6177cad2fabSAntoine Ténart 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
6181b44c5a6SAntoine Ténart 				   safexcel_inv_complete, &result);
6191b44c5a6SAntoine Ténart 
6207cad2fabSAntoine Ténart 	ahash_request_set_tfm(req, __crypto_ahash_cast(tfm));
6217cad2fabSAntoine Ténart 	ctx = crypto_tfm_ctx(req->base.tfm);
6221b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
6231eb7b403SOfer Heifetz 	rctx->needs_inv = true;
6241b44c5a6SAntoine Ténart 
62586671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
6267cad2fabSAntoine Ténart 	crypto_enqueue_request(&priv->ring[ring].queue, &req->base);
62786671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
6281b44c5a6SAntoine Ténart 
6298472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
6308472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
6311b44c5a6SAntoine Ténart 
632b7007dbcSAntoine Tenart 	wait_for_completion(&result.completion);
6331b44c5a6SAntoine Ténart 
6341b44c5a6SAntoine Ténart 	if (result.error) {
6351b44c5a6SAntoine Ténart 		dev_warn(priv->dev, "hash: completion error (%d)\n",
6361b44c5a6SAntoine Ténart 			 result.error);
6371b44c5a6SAntoine Ténart 		return result.error;
6381b44c5a6SAntoine Ténart 	}
6391b44c5a6SAntoine Ténart 
6401b44c5a6SAntoine Ténart 	return 0;
6411b44c5a6SAntoine Ténart }
6421b44c5a6SAntoine Ténart 
643cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to
644cc75f5ceSAntoine Ténart  * the engine, aka. when there is at least 1 block size in the pipe.
645cc75f5ceSAntoine Ténart  */
64641abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq)
6471b44c5a6SAntoine Ténart {
6481b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
64941abed7dSPascal van Leeuwen 	u64 cache_len;
6501b44c5a6SAntoine Ténart 
651b460edb6SAntoine Tenart 	/* cache_len: everything accepted by the driver but not sent yet,
652b460edb6SAntoine Tenart 	 * tot sz handled by update() - last req sz - tot sz handled by send()
653b460edb6SAntoine Tenart 	 */
65441abed7dSPascal van Leeuwen 	cache_len = safexcel_queued_len(req);
6551b44c5a6SAntoine Ténart 
6561b44c5a6SAntoine Ténart 	/*
6571b44c5a6SAntoine Ténart 	 * In case there isn't enough bytes to proceed (less than a
6581b44c5a6SAntoine Ténart 	 * block size), cache the data until we have enough.
6591b44c5a6SAntoine Ténart 	 */
66041abed7dSPascal van Leeuwen 	if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) {
6611b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
6621b44c5a6SAntoine Ténart 				   req->cache + cache_len,
6631b44c5a6SAntoine Ténart 				   areq->nbytes, 0);
66441abed7dSPascal van Leeuwen 		return 0;
6651b44c5a6SAntoine Ténart 	}
6661b44c5a6SAntoine Ténart 
667dfbcc08fSAntoine Ténart 	/* We couldn't cache all the data */
6681b44c5a6SAntoine Ténart 	return -E2BIG;
6691b44c5a6SAntoine Ténart }
6701b44c5a6SAntoine Ténart 
6711b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq)
6721b44c5a6SAntoine Ténart {
6731b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
6741b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6751b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
67686671abbSAntoine Ténart 	int ret, ring;
6771b44c5a6SAntoine Ténart 
6781eb7b403SOfer Heifetz 	req->needs_inv = false;
6791b44c5a6SAntoine Ténart 
680c4daf4ccSOfer Heifetz 	if (ctx->base.ctxr) {
68153c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv &&
682b98687bbSPascal van Leeuwen 		     /* invalidate for *any* non-XCBC continuation */
683b98687bbSPascal van Leeuwen 		   ((req->not_first && !req->xcbcmac) ||
68441abed7dSPascal van Leeuwen 		     /* invalidate if (i)digest changed */
68541abed7dSPascal van Leeuwen 		     memcmp(ctx->base.ctxr->data, req->state, req->state_sz) ||
68641abed7dSPascal van Leeuwen 		     /* invalidate for HMAC finish with odigest changed */
687a7cf8658SPascal van Leeuwen 		     (req->finish && req->hmac &&
68841abed7dSPascal van Leeuwen 		      memcmp(ctx->base.ctxr->data + (req->state_sz>>2),
68941abed7dSPascal van Leeuwen 			     ctx->opad, req->state_sz))))
69041abed7dSPascal van Leeuwen 			/*
69141abed7dSPascal van Leeuwen 			 * We're still setting needs_inv here, even though it is
692c4daf4ccSOfer Heifetz 			 * cleared right away, because the needs_inv flag can be
693c4daf4ccSOfer Heifetz 			 * set in other functions and we want to keep the same
694c4daf4ccSOfer Heifetz 			 * logic.
695c4daf4ccSOfer Heifetz 			 */
69641abed7dSPascal van Leeuwen 			ctx->base.needs_inv = true;
6971b44c5a6SAntoine Ténart 
6981eb7b403SOfer Heifetz 		if (ctx->base.needs_inv) {
6991eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
7001eb7b403SOfer Heifetz 			req->needs_inv = true;
7011eb7b403SOfer Heifetz 		}
7021b44c5a6SAntoine Ténart 	} else {
7031b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
7041b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
7051b44c5a6SAntoine Ténart 						 EIP197_GFP_FLAGS(areq->base),
7061b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
7071b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
7081b44c5a6SAntoine Ténart 			return -ENOMEM;
7091b44c5a6SAntoine Ténart 	}
710b98687bbSPascal van Leeuwen 	req->not_first = true;
7111b44c5a6SAntoine Ténart 
71286671abbSAntoine Ténart 	ring = ctx->base.ring;
7131b44c5a6SAntoine Ténart 
71486671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
71586671abbSAntoine Ténart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base);
71686671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
71786671abbSAntoine Ténart 
7188472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
7198472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
7201b44c5a6SAntoine Ténart 
7211b44c5a6SAntoine Ténart 	return ret;
7221b44c5a6SAntoine Ténart }
7231b44c5a6SAntoine Ténart 
7241b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq)
7251b44c5a6SAntoine Ténart {
7261b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
72741abed7dSPascal van Leeuwen 	int ret;
7281b44c5a6SAntoine Ténart 
7291b44c5a6SAntoine Ténart 	/* If the request is 0 length, do nothing */
7301b44c5a6SAntoine Ténart 	if (!areq->nbytes)
7311b44c5a6SAntoine Ténart 		return 0;
7321b44c5a6SAntoine Ténart 
73341abed7dSPascal van Leeuwen 	/* Add request to the cache if it fits */
73441abed7dSPascal van Leeuwen 	ret = safexcel_ahash_cache(areq);
73541abed7dSPascal van Leeuwen 
73641abed7dSPascal van Leeuwen 	/* Update total request length */
73731fb084cSPascal van Leeuwen 	req->len += areq->nbytes;
7381b44c5a6SAntoine Ténart 
73941abed7dSPascal van Leeuwen 	/* If not all data could fit into the cache, go process the excess.
74041abed7dSPascal van Leeuwen 	 * Also go process immediately for an HMAC IV precompute, which
74141abed7dSPascal van Leeuwen 	 * will never be finished at all, but needs to be processed anyway.
7421b44c5a6SAntoine Ténart 	 */
74341abed7dSPascal van Leeuwen 	if ((ret && !req->finish) || req->last_req)
7441b44c5a6SAntoine Ténart 		return safexcel_ahash_enqueue(areq);
7451b44c5a6SAntoine Ténart 
7461b44c5a6SAntoine Ténart 	return 0;
7471b44c5a6SAntoine Ténart }
7481b44c5a6SAntoine Ténart 
7491b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq)
7501b44c5a6SAntoine Ténart {
7511b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
7521b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
7531b44c5a6SAntoine Ténart 
7541b44c5a6SAntoine Ténart 	req->finish = true;
7551b44c5a6SAntoine Ténart 
75631fb084cSPascal van Leeuwen 	if (unlikely(!req->len && !areq->nbytes)) {
75785695b09SPascal van Leeuwen 		/*
75885695b09SPascal van Leeuwen 		 * If we have an overall 0 length *hash* request:
75985695b09SPascal van Leeuwen 		 * The HW cannot do 0 length hash, so we provide the correct
76085695b09SPascal van Leeuwen 		 * result directly here.
76185695b09SPascal van Leeuwen 		 */
762293f89cfSOfer Heifetz 		if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5)
763293f89cfSOfer Heifetz 			memcpy(areq->result, md5_zero_message_hash,
764293f89cfSOfer Heifetz 			       MD5_DIGEST_SIZE);
765293f89cfSOfer Heifetz 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1)
7661b44c5a6SAntoine Ténart 			memcpy(areq->result, sha1_zero_message_hash,
7671b44c5a6SAntoine Ténart 			       SHA1_DIGEST_SIZE);
7681b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224)
7691b44c5a6SAntoine Ténart 			memcpy(areq->result, sha224_zero_message_hash,
7701b44c5a6SAntoine Ténart 			       SHA224_DIGEST_SIZE);
7711b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256)
7721b44c5a6SAntoine Ténart 			memcpy(areq->result, sha256_zero_message_hash,
7731b44c5a6SAntoine Ténart 			       SHA256_DIGEST_SIZE);
7749e46eafdSAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384)
7759e46eafdSAntoine Tenart 			memcpy(areq->result, sha384_zero_message_hash,
7769e46eafdSAntoine Tenart 			       SHA384_DIGEST_SIZE);
777b460edb6SAntoine Tenart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512)
778b460edb6SAntoine Tenart 			memcpy(areq->result, sha512_zero_message_hash,
779b460edb6SAntoine Tenart 			       SHA512_DIGEST_SIZE);
7800f2bc131SPascal van Leeuwen 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) {
7810f2bc131SPascal van Leeuwen 			if (IS_ENABLED(CONFIG_CRYPTO_SM3))
7820f2bc131SPascal van Leeuwen 				memcpy(areq->result, sm3_zero_message_hash,
7830f2bc131SPascal van Leeuwen 				       SM3_DIGEST_SIZE);
7840f2bc131SPascal van Leeuwen 			else
7850f2bc131SPascal van Leeuwen 				memcpy(areq->result,
7860f2bc131SPascal van Leeuwen 				       EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE);
7870f2bc131SPascal van Leeuwen 		}
7881b44c5a6SAntoine Ténart 
7891b44c5a6SAntoine Ténart 		return 0;
790a7cf8658SPascal van Leeuwen 	} else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM &&
791a7cf8658SPascal van Leeuwen 			    ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 &&
792a7cf8658SPascal van Leeuwen 			    req->len == sizeof(u32) && !areq->nbytes)) {
793a7cf8658SPascal van Leeuwen 		/* Zero length CRC32 */
794a7cf8658SPascal van Leeuwen 		memcpy(areq->result, ctx->ipad, sizeof(u32));
795a7cf8658SPascal van Leeuwen 		return 0;
79638f21b4bSPascal van Leeuwen 	} else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE &&
797b98687bbSPascal van Leeuwen 			    !areq->nbytes)) {
798b98687bbSPascal van Leeuwen 		/* Zero length CBC MAC */
799b98687bbSPascal van Leeuwen 		memset(areq->result, 0, AES_BLOCK_SIZE);
800b98687bbSPascal van Leeuwen 		return 0;
80138f21b4bSPascal van Leeuwen 	} else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE &&
80238f21b4bSPascal van Leeuwen 			    !areq->nbytes)) {
80338f21b4bSPascal van Leeuwen 		/* Zero length (X)CBC/CMAC */
80438f21b4bSPascal van Leeuwen 		int i;
80538f21b4bSPascal van Leeuwen 
80638f21b4bSPascal van Leeuwen 		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
80738f21b4bSPascal van Leeuwen 			((u32 *)areq->result)[i] =
80838f21b4bSPascal van Leeuwen 				cpu_to_be32(ctx->ipad[i + 4]);	// K3
80938f21b4bSPascal van Leeuwen 		areq->result[0] ^= 0x80;			// 10- padding
81038f21b4bSPascal van Leeuwen 		crypto_cipher_encrypt_one(ctx->kaes, areq->result, areq->result);
81138f21b4bSPascal van Leeuwen 		return 0;
81231fb084cSPascal van Leeuwen 	} else if (unlikely(req->hmac &&
81331fb084cSPascal van Leeuwen 			    (req->len == req->block_sz) &&
81441abed7dSPascal van Leeuwen 			    !areq->nbytes)) {
81585b36ee8SPascal van Leeuwen 		/*
81685b36ee8SPascal van Leeuwen 		 * If we have an overall 0 length *HMAC* request:
81785b36ee8SPascal van Leeuwen 		 * For HMAC, we need to finalize the inner digest
81885b36ee8SPascal van Leeuwen 		 * and then perform the outer hash.
81985b36ee8SPascal van Leeuwen 		 */
82085b36ee8SPascal van Leeuwen 
82185b36ee8SPascal van Leeuwen 		/* generate pad block in the cache */
82285b36ee8SPascal van Leeuwen 		/* start with a hash block of all zeroes */
82385b36ee8SPascal van Leeuwen 		memset(req->cache, 0, req->block_sz);
82485b36ee8SPascal van Leeuwen 		/* set the first byte to 0x80 to 'append a 1 bit' */
82585b36ee8SPascal van Leeuwen 		req->cache[0] = 0x80;
82685b36ee8SPascal van Leeuwen 		/* add the length in bits in the last 2 bytes */
82785b36ee8SPascal van Leeuwen 		if (req->len_is_le) {
82885b36ee8SPascal van Leeuwen 			/* Little endian length word (e.g. MD5) */
82985b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-8] = (req->block_sz << 3) &
83085b36ee8SPascal van Leeuwen 						      255;
83185b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-7] = (req->block_sz >> 5);
83285b36ee8SPascal van Leeuwen 		} else {
83385b36ee8SPascal van Leeuwen 			/* Big endian length word (e.g. any SHA) */
83485b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-2] = (req->block_sz >> 5);
83585b36ee8SPascal van Leeuwen 			req->cache[req->block_sz-1] = (req->block_sz << 3) &
83685b36ee8SPascal van Leeuwen 						      255;
83785b36ee8SPascal van Leeuwen 		}
83885b36ee8SPascal van Leeuwen 
83931fb084cSPascal van Leeuwen 		req->len += req->block_sz; /* plus 1 hash block */
84085b36ee8SPascal van Leeuwen 
84185b36ee8SPascal van Leeuwen 		/* Set special zero-length HMAC flag */
84285b36ee8SPascal van Leeuwen 		req->hmac_zlen = true;
84385b36ee8SPascal van Leeuwen 
84485b36ee8SPascal van Leeuwen 		/* Finalize HMAC */
84585b36ee8SPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
84641abed7dSPascal van Leeuwen 	} else if (req->hmac) {
84741abed7dSPascal van Leeuwen 		/* Finalize HMAC */
84841abed7dSPascal van Leeuwen 		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
8491b44c5a6SAntoine Ténart 	}
8501b44c5a6SAntoine Ténart 
8511b44c5a6SAntoine Ténart 	return safexcel_ahash_enqueue(areq);
8521b44c5a6SAntoine Ténart }
8531b44c5a6SAntoine Ténart 
8541b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq)
8551b44c5a6SAntoine Ténart {
8561b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8571b44c5a6SAntoine Ténart 
8581b44c5a6SAntoine Ténart 	req->finish = true;
8591b44c5a6SAntoine Ténart 
8601b44c5a6SAntoine Ténart 	safexcel_ahash_update(areq);
8611b44c5a6SAntoine Ténart 	return safexcel_ahash_final(areq);
8621b44c5a6SAntoine Ténart }
8631b44c5a6SAntoine Ténart 
8641b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out)
8651b44c5a6SAntoine Ténart {
8661b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8671b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state *export = out;
8681b44c5a6SAntoine Ténart 
86931fb084cSPascal van Leeuwen 	export->len = req->len;
87031fb084cSPascal van Leeuwen 	export->processed = req->processed;
8711b44c5a6SAntoine Ténart 
872b869648cSAntoine Tenart 	export->digest = req->digest;
873b869648cSAntoine Tenart 
8741b44c5a6SAntoine Ténart 	memcpy(export->state, req->state, req->state_sz);
87541abed7dSPascal van Leeuwen 	memcpy(export->cache, req->cache, HASH_CACHE_SIZE);
8761b44c5a6SAntoine Ténart 
8771b44c5a6SAntoine Ténart 	return 0;
8781b44c5a6SAntoine Ténart }
8791b44c5a6SAntoine Ténart 
8801b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in)
8811b44c5a6SAntoine Ténart {
8821b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
8831b44c5a6SAntoine Ténart 	const struct safexcel_ahash_export_state *export = in;
8841b44c5a6SAntoine Ténart 	int ret;
8851b44c5a6SAntoine Ténart 
8861b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
8871b44c5a6SAntoine Ténart 	if (ret)
8881b44c5a6SAntoine Ténart 		return ret;
8891b44c5a6SAntoine Ténart 
89031fb084cSPascal van Leeuwen 	req->len = export->len;
89131fb084cSPascal van Leeuwen 	req->processed = export->processed;
8921b44c5a6SAntoine Ténart 
893b869648cSAntoine Tenart 	req->digest = export->digest;
894b869648cSAntoine Tenart 
89541abed7dSPascal van Leeuwen 	memcpy(req->cache, export->cache, HASH_CACHE_SIZE);
8961b44c5a6SAntoine Ténart 	memcpy(req->state, export->state, req->state_sz);
8971b44c5a6SAntoine Ténart 
8981b44c5a6SAntoine Ténart 	return 0;
8991b44c5a6SAntoine Ténart }
9001b44c5a6SAntoine Ténart 
9011b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm)
9021b44c5a6SAntoine Ténart {
9031b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
9041b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
9051b44c5a6SAntoine Ténart 		container_of(__crypto_ahash_alg(tfm->__crt_alg),
9061b44c5a6SAntoine Ténart 			     struct safexcel_alg_template, alg.ahash);
9071b44c5a6SAntoine Ténart 
9081b44c5a6SAntoine Ténart 	ctx->priv = tmpl->priv;
9091eb7b403SOfer Heifetz 	ctx->base.send = safexcel_ahash_send;
9101eb7b403SOfer Heifetz 	ctx->base.handle_result = safexcel_handle_result;
9111b44c5a6SAntoine Ténart 
9121b44c5a6SAntoine Ténart 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
9131b44c5a6SAntoine Ténart 				 sizeof(struct safexcel_ahash_req));
9141b44c5a6SAntoine Ténart 	return 0;
9151b44c5a6SAntoine Ténart }
9161b44c5a6SAntoine Ténart 
9171b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq)
9181b44c5a6SAntoine Ténart {
9191b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
9201b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
9211b44c5a6SAntoine Ténart 
9221b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
9231b44c5a6SAntoine Ténart 
9241b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
925b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
9261b44c5a6SAntoine Ténart 	req->state_sz = SHA1_DIGEST_SIZE;
92741abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
9281b44c5a6SAntoine Ténart 
9291b44c5a6SAntoine Ténart 	return 0;
9301b44c5a6SAntoine Ténart }
9311b44c5a6SAntoine Ténart 
9321b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq)
9331b44c5a6SAntoine Ténart {
9341b44c5a6SAntoine Ténart 	int ret = safexcel_sha1_init(areq);
9351b44c5a6SAntoine Ténart 
9361b44c5a6SAntoine Ténart 	if (ret)
9371b44c5a6SAntoine Ténart 		return ret;
9381b44c5a6SAntoine Ténart 
9391b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
9401b44c5a6SAntoine Ténart }
9411b44c5a6SAntoine Ténart 
9421b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm)
9431b44c5a6SAntoine Ténart {
9441b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
9451b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
9461b44c5a6SAntoine Ténart 	int ret;
9471b44c5a6SAntoine Ténart 
9481b44c5a6SAntoine Ténart 	/* context not allocated, skip invalidation */
9491b44c5a6SAntoine Ténart 	if (!ctx->base.ctxr)
9501b44c5a6SAntoine Ténart 		return;
9511b44c5a6SAntoine Ténart 
95253c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
9531b44c5a6SAntoine Ténart 		ret = safexcel_ahash_exit_inv(tfm);
9541b44c5a6SAntoine Ténart 		if (ret)
9551b44c5a6SAntoine Ténart 			dev_warn(priv->dev, "hash: invalidation error %d\n", ret);
956871df319SAntoine Ténart 	} else {
957871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
958871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
959871df319SAntoine Ténart 	}
9601b44c5a6SAntoine Ténart }
9611b44c5a6SAntoine Ténart 
9621b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = {
9631b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
964062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
9651b44c5a6SAntoine Ténart 	.alg.ahash = {
9661b44c5a6SAntoine Ténart 		.init = safexcel_sha1_init,
9671b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
9681b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
9691b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
9701b44c5a6SAntoine Ténart 		.digest = safexcel_sha1_digest,
9711b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
9721b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
9731b44c5a6SAntoine Ténart 		.halg = {
9741b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
9751b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
9761b44c5a6SAntoine Ténart 			.base = {
9771b44c5a6SAntoine Ténart 				.cra_name = "sha1",
9781b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha1",
979aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
9801b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
9811b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
9821b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
9831b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
9841b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
9851b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
9861b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
9871b44c5a6SAntoine Ténart 			},
9881b44c5a6SAntoine Ténart 		},
9891b44c5a6SAntoine Ténart 	},
9901b44c5a6SAntoine Ténart };
9911b44c5a6SAntoine Ténart 
9921b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq)
9931b44c5a6SAntoine Ténart {
99441abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
995b869648cSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
9961b44c5a6SAntoine Ténart 
99741abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
99841abed7dSPascal van Leeuwen 
99941abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
100041abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA1_DIGEST_SIZE);
100141abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
100231fb084cSPascal van Leeuwen 	req->len	= SHA1_BLOCK_SIZE;
100331fb084cSPascal van Leeuwen 	req->processed	= SHA1_BLOCK_SIZE;
100441abed7dSPascal van Leeuwen 
100541abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
100641abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
100741abed7dSPascal van Leeuwen 	req->state_sz = SHA1_DIGEST_SIZE;
100841abed7dSPascal van Leeuwen 	req->block_sz = SHA1_BLOCK_SIZE;
100941abed7dSPascal van Leeuwen 	req->hmac = true;
101041abed7dSPascal van Leeuwen 
10111b44c5a6SAntoine Ténart 	return 0;
10121b44c5a6SAntoine Ténart }
10131b44c5a6SAntoine Ténart 
10141b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq)
10151b44c5a6SAntoine Ténart {
10161b44c5a6SAntoine Ténart 	int ret = safexcel_hmac_sha1_init(areq);
10171b44c5a6SAntoine Ténart 
10181b44c5a6SAntoine Ténart 	if (ret)
10191b44c5a6SAntoine Ténart 		return ret;
10201b44c5a6SAntoine Ténart 
10211b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
10221b44c5a6SAntoine Ténart }
10231b44c5a6SAntoine Ténart 
10241b44c5a6SAntoine Ténart struct safexcel_ahash_result {
10251b44c5a6SAntoine Ténart 	struct completion completion;
10261b44c5a6SAntoine Ténart 	int error;
10271b44c5a6SAntoine Ténart };
10281b44c5a6SAntoine Ténart 
10291b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error)
10301b44c5a6SAntoine Ténart {
10311b44c5a6SAntoine Ténart 	struct safexcel_ahash_result *result = req->data;
10321b44c5a6SAntoine Ténart 
10331b44c5a6SAntoine Ténart 	if (error == -EINPROGRESS)
10341b44c5a6SAntoine Ténart 		return;
10351b44c5a6SAntoine Ténart 
10361b44c5a6SAntoine Ténart 	result->error = error;
10371b44c5a6SAntoine Ténart 	complete(&result->completion);
10381b44c5a6SAntoine Ténart }
10391b44c5a6SAntoine Ténart 
10401b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq,
10411b44c5a6SAntoine Ténart 				  unsigned int blocksize, const u8 *key,
10421b44c5a6SAntoine Ténart 				  unsigned int keylen, u8 *ipad, u8 *opad)
10431b44c5a6SAntoine Ténart {
10441b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
10451b44c5a6SAntoine Ténart 	struct scatterlist sg;
10461b44c5a6SAntoine Ténart 	int ret, i;
10471b44c5a6SAntoine Ténart 	u8 *keydup;
10481b44c5a6SAntoine Ténart 
10491b44c5a6SAntoine Ténart 	if (keylen <= blocksize) {
10501b44c5a6SAntoine Ténart 		memcpy(ipad, key, keylen);
10511b44c5a6SAntoine Ténart 	} else {
10521b44c5a6SAntoine Ténart 		keydup = kmemdup(key, keylen, GFP_KERNEL);
10531b44c5a6SAntoine Ténart 		if (!keydup)
10541b44c5a6SAntoine Ténart 			return -ENOMEM;
10551b44c5a6SAntoine Ténart 
10561b44c5a6SAntoine Ténart 		ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
10571b44c5a6SAntoine Ténart 					   safexcel_ahash_complete, &result);
10581b44c5a6SAntoine Ténart 		sg_init_one(&sg, keydup, keylen);
10591b44c5a6SAntoine Ténart 		ahash_request_set_crypt(areq, &sg, ipad, keylen);
10601b44c5a6SAntoine Ténart 		init_completion(&result.completion);
10611b44c5a6SAntoine Ténart 
10621b44c5a6SAntoine Ténart 		ret = crypto_ahash_digest(areq);
10634dc5475aSAntoine Tenart 		if (ret == -EINPROGRESS || ret == -EBUSY) {
10641b44c5a6SAntoine Ténart 			wait_for_completion_interruptible(&result.completion);
10651b44c5a6SAntoine Ténart 			ret = result.error;
10661b44c5a6SAntoine Ténart 		}
10671b44c5a6SAntoine Ténart 
10681b44c5a6SAntoine Ténart 		/* Avoid leaking */
10691b44c5a6SAntoine Ténart 		memzero_explicit(keydup, keylen);
10701b44c5a6SAntoine Ténart 		kfree(keydup);
10711b44c5a6SAntoine Ténart 
10721b44c5a6SAntoine Ténart 		if (ret)
10731b44c5a6SAntoine Ténart 			return ret;
10741b44c5a6SAntoine Ténart 
10751b44c5a6SAntoine Ténart 		keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq));
10761b44c5a6SAntoine Ténart 	}
10771b44c5a6SAntoine Ténart 
10781b44c5a6SAntoine Ténart 	memset(ipad + keylen, 0, blocksize - keylen);
10791b44c5a6SAntoine Ténart 	memcpy(opad, ipad, blocksize);
10801b44c5a6SAntoine Ténart 
10811b44c5a6SAntoine Ténart 	for (i = 0; i < blocksize; i++) {
1082aed3731eSAntoine Ténart 		ipad[i] ^= HMAC_IPAD_VALUE;
1083aed3731eSAntoine Ténart 		opad[i] ^= HMAC_OPAD_VALUE;
10841b44c5a6SAntoine Ténart 	}
10851b44c5a6SAntoine Ténart 
10861b44c5a6SAntoine Ténart 	return 0;
10871b44c5a6SAntoine Ténart }
10881b44c5a6SAntoine Ténart 
10891b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq,
10901b44c5a6SAntoine Ténart 				 unsigned int blocksize, u8 *pad, void *state)
10911b44c5a6SAntoine Ténart {
10921b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
10931b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req;
10941b44c5a6SAntoine Ténart 	struct scatterlist sg;
10951b44c5a6SAntoine Ténart 	int ret;
10961b44c5a6SAntoine Ténart 
10971b44c5a6SAntoine Ténart 	ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
10981b44c5a6SAntoine Ténart 				   safexcel_ahash_complete, &result);
10991b44c5a6SAntoine Ténart 	sg_init_one(&sg, pad, blocksize);
11001b44c5a6SAntoine Ténart 	ahash_request_set_crypt(areq, &sg, pad, blocksize);
11011b44c5a6SAntoine Ténart 	init_completion(&result.completion);
11021b44c5a6SAntoine Ténart 
11031b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
11041b44c5a6SAntoine Ténart 	if (ret)
11051b44c5a6SAntoine Ténart 		return ret;
11061b44c5a6SAntoine Ténart 
11071b44c5a6SAntoine Ténart 	req = ahash_request_ctx(areq);
11081b44c5a6SAntoine Ténart 	req->hmac = true;
11091b44c5a6SAntoine Ténart 	req->last_req = true;
11101b44c5a6SAntoine Ténart 
11111b44c5a6SAntoine Ténart 	ret = crypto_ahash_update(areq);
111212bf4142SOfer Heifetz 	if (ret && ret != -EINPROGRESS && ret != -EBUSY)
11131b44c5a6SAntoine Ténart 		return ret;
11141b44c5a6SAntoine Ténart 
11151b44c5a6SAntoine Ténart 	wait_for_completion_interruptible(&result.completion);
11161b44c5a6SAntoine Ténart 	if (result.error)
11171b44c5a6SAntoine Ténart 		return result.error;
11181b44c5a6SAntoine Ténart 
11191b44c5a6SAntoine Ténart 	return crypto_ahash_export(areq, state);
11201b44c5a6SAntoine Ténart }
11211b44c5a6SAntoine Ténart 
1122f6beaea3SAntoine Tenart int safexcel_hmac_setkey(const char *alg, const u8 *key, unsigned int keylen,
1123f6beaea3SAntoine Tenart 			 void *istate, void *ostate)
11241b44c5a6SAntoine Ténart {
11251b44c5a6SAntoine Ténart 	struct ahash_request *areq;
11261b44c5a6SAntoine Ténart 	struct crypto_ahash *tfm;
11271b44c5a6SAntoine Ténart 	unsigned int blocksize;
11281b44c5a6SAntoine Ténart 	u8 *ipad, *opad;
11291b44c5a6SAntoine Ténart 	int ret;
11301b44c5a6SAntoine Ténart 
113185d7311fSEric Biggers 	tfm = crypto_alloc_ahash(alg, 0, 0);
11321b44c5a6SAntoine Ténart 	if (IS_ERR(tfm))
11331b44c5a6SAntoine Ténart 		return PTR_ERR(tfm);
11341b44c5a6SAntoine Ténart 
11351b44c5a6SAntoine Ténart 	areq = ahash_request_alloc(tfm, GFP_KERNEL);
11361b44c5a6SAntoine Ténart 	if (!areq) {
11371b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11381b44c5a6SAntoine Ténart 		goto free_ahash;
11391b44c5a6SAntoine Ténart 	}
11401b44c5a6SAntoine Ténart 
11411b44c5a6SAntoine Ténart 	crypto_ahash_clear_flags(tfm, ~0);
11421b44c5a6SAntoine Ténart 	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
11431b44c5a6SAntoine Ténart 
11446396bb22SKees Cook 	ipad = kcalloc(2, blocksize, GFP_KERNEL);
11451b44c5a6SAntoine Ténart 	if (!ipad) {
11461b44c5a6SAntoine Ténart 		ret = -ENOMEM;
11471b44c5a6SAntoine Ténart 		goto free_request;
11481b44c5a6SAntoine Ténart 	}
11491b44c5a6SAntoine Ténart 
11501b44c5a6SAntoine Ténart 	opad = ipad + blocksize;
11511b44c5a6SAntoine Ténart 
11521b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad);
11531b44c5a6SAntoine Ténart 	if (ret)
11541b44c5a6SAntoine Ténart 		goto free_ipad;
11551b44c5a6SAntoine Ténart 
11561b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate);
11571b44c5a6SAntoine Ténart 	if (ret)
11581b44c5a6SAntoine Ténart 		goto free_ipad;
11591b44c5a6SAntoine Ténart 
11601b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate);
11611b44c5a6SAntoine Ténart 
11621b44c5a6SAntoine Ténart free_ipad:
11631b44c5a6SAntoine Ténart 	kfree(ipad);
11641b44c5a6SAntoine Ténart free_request:
11651b44c5a6SAntoine Ténart 	ahash_request_free(areq);
11661b44c5a6SAntoine Ténart free_ahash:
11671b44c5a6SAntoine Ténart 	crypto_free_ahash(tfm);
11681b44c5a6SAntoine Ténart 
11691b44c5a6SAntoine Ténart 	return ret;
11701b44c5a6SAntoine Ténart }
11711b44c5a6SAntoine Ténart 
117273f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key,
117373f36ea7SAntoine Tenart 				    unsigned int keylen, const char *alg,
117473f36ea7SAntoine Tenart 				    unsigned int state_sz)
11751b44c5a6SAntoine Ténart {
11761b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1177871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
11781b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state istate, ostate;
117941abed7dSPascal van Leeuwen 	int ret;
11801b44c5a6SAntoine Ténart 
118173f36ea7SAntoine Tenart 	ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate);
11821b44c5a6SAntoine Ténart 	if (ret)
11831b44c5a6SAntoine Ténart 		return ret;
11841b44c5a6SAntoine Ténart 
118541abed7dSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr &&
118641abed7dSPascal van Leeuwen 	    (memcmp(ctx->ipad, istate.state, state_sz) ||
118741abed7dSPascal van Leeuwen 	     memcmp(ctx->opad, ostate.state, state_sz)))
11881b44c5a6SAntoine Ténart 		ctx->base.needs_inv = true;
11891b44c5a6SAntoine Ténart 
119073f36ea7SAntoine Tenart 	memcpy(ctx->ipad, &istate.state, state_sz);
119173f36ea7SAntoine Tenart 	memcpy(ctx->opad, &ostate.state, state_sz);
119242ef3bedSAntoine Ténart 
11931b44c5a6SAntoine Ténart 	return 0;
11941b44c5a6SAntoine Ténart }
11951b44c5a6SAntoine Ténart 
119673f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
119773f36ea7SAntoine Tenart 				     unsigned int keylen)
119873f36ea7SAntoine Tenart {
119973f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1",
120073f36ea7SAntoine Tenart 					SHA1_DIGEST_SIZE);
120173f36ea7SAntoine Tenart }
120273f36ea7SAntoine Tenart 
12031b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = {
12041b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1205062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA1,
12061b44c5a6SAntoine Ténart 	.alg.ahash = {
12071b44c5a6SAntoine Ténart 		.init = safexcel_hmac_sha1_init,
12081b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12091b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12101b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12111b44c5a6SAntoine Ténart 		.digest = safexcel_hmac_sha1_digest,
12121b44c5a6SAntoine Ténart 		.setkey = safexcel_hmac_sha1_setkey,
12131b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12141b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12151b44c5a6SAntoine Ténart 		.halg = {
12161b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
12171b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12181b44c5a6SAntoine Ténart 			.base = {
12191b44c5a6SAntoine Ténart 				.cra_name = "hmac(sha1)",
12201b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-hmac-sha1",
1221aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12221b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
12231b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12241b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
12251b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12261b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
12271b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
12281b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
12291b44c5a6SAntoine Ténart 			},
12301b44c5a6SAntoine Ténart 		},
12311b44c5a6SAntoine Ténart 	},
12321b44c5a6SAntoine Ténart };
12331b44c5a6SAntoine Ténart 
12341b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq)
12351b44c5a6SAntoine Ténart {
12361b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
12371b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
12381b44c5a6SAntoine Ténart 
12391b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
12401b44c5a6SAntoine Ténart 
12411b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1242b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
12431b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
124441abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
12451b44c5a6SAntoine Ténart 
12461b44c5a6SAntoine Ténart 	return 0;
12471b44c5a6SAntoine Ténart }
12481b44c5a6SAntoine Ténart 
12491b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq)
12501b44c5a6SAntoine Ténart {
12511b44c5a6SAntoine Ténart 	int ret = safexcel_sha256_init(areq);
12521b44c5a6SAntoine Ténart 
12531b44c5a6SAntoine Ténart 	if (ret)
12541b44c5a6SAntoine Ténart 		return ret;
12551b44c5a6SAntoine Ténart 
12561b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
12571b44c5a6SAntoine Ténart }
12581b44c5a6SAntoine Ténart 
12591b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = {
12601b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1261062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
12621b44c5a6SAntoine Ténart 	.alg.ahash = {
12631b44c5a6SAntoine Ténart 		.init = safexcel_sha256_init,
12641b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
12651b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
12661b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
12671b44c5a6SAntoine Ténart 		.digest = safexcel_sha256_digest,
12681b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
12691b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
12701b44c5a6SAntoine Ténart 		.halg = {
12711b44c5a6SAntoine Ténart 			.digestsize = SHA256_DIGEST_SIZE,
12721b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
12731b44c5a6SAntoine Ténart 			.base = {
12741b44c5a6SAntoine Ténart 				.cra_name = "sha256",
12751b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha256",
1276aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
12771b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
12781b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
12791b44c5a6SAntoine Ténart 				.cra_blocksize = SHA256_BLOCK_SIZE,
12801b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12811b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
12821b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
12831b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
12841b44c5a6SAntoine Ténart 			},
12851b44c5a6SAntoine Ténart 		},
12861b44c5a6SAntoine Ténart 	},
12871b44c5a6SAntoine Ténart };
12881b44c5a6SAntoine Ténart 
12891b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq)
12901b44c5a6SAntoine Ténart {
12911b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
12921b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
12931b44c5a6SAntoine Ténart 
12941b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
12951b44c5a6SAntoine Ténart 
12961b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1297b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
12981b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
129941abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
13001b44c5a6SAntoine Ténart 
13011b44c5a6SAntoine Ténart 	return 0;
13021b44c5a6SAntoine Ténart }
13031b44c5a6SAntoine Ténart 
13041b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq)
13051b44c5a6SAntoine Ténart {
13061b44c5a6SAntoine Ténart 	int ret = safexcel_sha224_init(areq);
13071b44c5a6SAntoine Ténart 
13081b44c5a6SAntoine Ténart 	if (ret)
13091b44c5a6SAntoine Ténart 		return ret;
13101b44c5a6SAntoine Ténart 
13111b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
13121b44c5a6SAntoine Ténart }
13131b44c5a6SAntoine Ténart 
13141b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = {
13151b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1316062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
13171b44c5a6SAntoine Ténart 	.alg.ahash = {
13181b44c5a6SAntoine Ténart 		.init = safexcel_sha224_init,
13191b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
13201b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
13211b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
13221b44c5a6SAntoine Ténart 		.digest = safexcel_sha224_digest,
13231b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
13241b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
13251b44c5a6SAntoine Ténart 		.halg = {
13261b44c5a6SAntoine Ténart 			.digestsize = SHA224_DIGEST_SIZE,
13271b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
13281b44c5a6SAntoine Ténart 			.base = {
13291b44c5a6SAntoine Ténart 				.cra_name = "sha224",
13301b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha224",
1331aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
13321b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
13331b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
13341b44c5a6SAntoine Ténart 				.cra_blocksize = SHA224_BLOCK_SIZE,
13351b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
13361b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
13371b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
13381b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
13391b44c5a6SAntoine Ténart 			},
13401b44c5a6SAntoine Ténart 		},
13411b44c5a6SAntoine Ténart 	},
13421b44c5a6SAntoine Ténart };
134373f36ea7SAntoine Tenart 
13443ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key,
13453ad618d8SAntoine Tenart 				       unsigned int keylen)
13463ad618d8SAntoine Tenart {
13473ad618d8SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224",
13483ad618d8SAntoine Tenart 					SHA256_DIGEST_SIZE);
13493ad618d8SAntoine Tenart }
13503ad618d8SAntoine Tenart 
13513ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq)
13523ad618d8SAntoine Tenart {
135341abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
13543ad618d8SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
13553ad618d8SAntoine Tenart 
135641abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
135741abed7dSPascal van Leeuwen 
135841abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
135941abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE);
136041abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
136131fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
136231fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
136341abed7dSPascal van Leeuwen 
136441abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
136541abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
136641abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
136741abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
136841abed7dSPascal van Leeuwen 	req->hmac = true;
136941abed7dSPascal van Leeuwen 
13703ad618d8SAntoine Tenart 	return 0;
13713ad618d8SAntoine Tenart }
13723ad618d8SAntoine Tenart 
13733ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq)
13743ad618d8SAntoine Tenart {
13753ad618d8SAntoine Tenart 	int ret = safexcel_hmac_sha224_init(areq);
13763ad618d8SAntoine Tenart 
13773ad618d8SAntoine Tenart 	if (ret)
13783ad618d8SAntoine Tenart 		return ret;
13793ad618d8SAntoine Tenart 
13803ad618d8SAntoine Tenart 	return safexcel_ahash_finup(areq);
13813ad618d8SAntoine Tenart }
13823ad618d8SAntoine Tenart 
13833ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = {
13843ad618d8SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1385062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
13863ad618d8SAntoine Tenart 	.alg.ahash = {
13873ad618d8SAntoine Tenart 		.init = safexcel_hmac_sha224_init,
13883ad618d8SAntoine Tenart 		.update = safexcel_ahash_update,
13893ad618d8SAntoine Tenart 		.final = safexcel_ahash_final,
13903ad618d8SAntoine Tenart 		.finup = safexcel_ahash_finup,
13913ad618d8SAntoine Tenart 		.digest = safexcel_hmac_sha224_digest,
13923ad618d8SAntoine Tenart 		.setkey = safexcel_hmac_sha224_setkey,
13933ad618d8SAntoine Tenart 		.export = safexcel_ahash_export,
13943ad618d8SAntoine Tenart 		.import = safexcel_ahash_import,
13953ad618d8SAntoine Tenart 		.halg = {
13963ad618d8SAntoine Tenart 			.digestsize = SHA224_DIGEST_SIZE,
13973ad618d8SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
13983ad618d8SAntoine Tenart 			.base = {
13993ad618d8SAntoine Tenart 				.cra_name = "hmac(sha224)",
14003ad618d8SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha224",
1401aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
14023ad618d8SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
14033ad618d8SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
14043ad618d8SAntoine Tenart 				.cra_blocksize = SHA224_BLOCK_SIZE,
14053ad618d8SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
14063ad618d8SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
14073ad618d8SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
14083ad618d8SAntoine Tenart 				.cra_module = THIS_MODULE,
14093ad618d8SAntoine Tenart 			},
14103ad618d8SAntoine Tenart 		},
14113ad618d8SAntoine Tenart 	},
14123ad618d8SAntoine Tenart };
14133ad618d8SAntoine Tenart 
141473f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
141573f36ea7SAntoine Tenart 				     unsigned int keylen)
141673f36ea7SAntoine Tenart {
141773f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256",
141873f36ea7SAntoine Tenart 					SHA256_DIGEST_SIZE);
141973f36ea7SAntoine Tenart }
142073f36ea7SAntoine Tenart 
142173f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq)
142273f36ea7SAntoine Tenart {
142341abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
142473f36ea7SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
142573f36ea7SAntoine Tenart 
142641abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
142741abed7dSPascal van Leeuwen 
142841abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
142941abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE);
143041abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
143131fb084cSPascal van Leeuwen 	req->len	= SHA256_BLOCK_SIZE;
143231fb084cSPascal van Leeuwen 	req->processed	= SHA256_BLOCK_SIZE;
143341abed7dSPascal van Leeuwen 
143441abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
143541abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
143641abed7dSPascal van Leeuwen 	req->state_sz = SHA256_DIGEST_SIZE;
143741abed7dSPascal van Leeuwen 	req->block_sz = SHA256_BLOCK_SIZE;
143841abed7dSPascal van Leeuwen 	req->hmac = true;
143941abed7dSPascal van Leeuwen 
144073f36ea7SAntoine Tenart 	return 0;
144173f36ea7SAntoine Tenart }
144273f36ea7SAntoine Tenart 
144373f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq)
144473f36ea7SAntoine Tenart {
144573f36ea7SAntoine Tenart 	int ret = safexcel_hmac_sha256_init(areq);
144673f36ea7SAntoine Tenart 
144773f36ea7SAntoine Tenart 	if (ret)
144873f36ea7SAntoine Tenart 		return ret;
144973f36ea7SAntoine Tenart 
145073f36ea7SAntoine Tenart 	return safexcel_ahash_finup(areq);
145173f36ea7SAntoine Tenart }
145273f36ea7SAntoine Tenart 
145373f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = {
145473f36ea7SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1455062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_256,
145673f36ea7SAntoine Tenart 	.alg.ahash = {
145773f36ea7SAntoine Tenart 		.init = safexcel_hmac_sha256_init,
145873f36ea7SAntoine Tenart 		.update = safexcel_ahash_update,
145973f36ea7SAntoine Tenart 		.final = safexcel_ahash_final,
146073f36ea7SAntoine Tenart 		.finup = safexcel_ahash_finup,
146173f36ea7SAntoine Tenart 		.digest = safexcel_hmac_sha256_digest,
146273f36ea7SAntoine Tenart 		.setkey = safexcel_hmac_sha256_setkey,
146373f36ea7SAntoine Tenart 		.export = safexcel_ahash_export,
146473f36ea7SAntoine Tenart 		.import = safexcel_ahash_import,
146573f36ea7SAntoine Tenart 		.halg = {
146673f36ea7SAntoine Tenart 			.digestsize = SHA256_DIGEST_SIZE,
146773f36ea7SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
146873f36ea7SAntoine Tenart 			.base = {
146973f36ea7SAntoine Tenart 				.cra_name = "hmac(sha256)",
147073f36ea7SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha256",
1471aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
147273f36ea7SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
147373f36ea7SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
147473f36ea7SAntoine Tenart 				.cra_blocksize = SHA256_BLOCK_SIZE,
147573f36ea7SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
147673f36ea7SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
147773f36ea7SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
147873f36ea7SAntoine Tenart 				.cra_module = THIS_MODULE,
147973f36ea7SAntoine Tenart 			},
148073f36ea7SAntoine Tenart 		},
148173f36ea7SAntoine Tenart 	},
148273f36ea7SAntoine Tenart };
1483b460edb6SAntoine Tenart 
1484b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq)
1485b460edb6SAntoine Tenart {
1486b460edb6SAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1487b460edb6SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1488b460edb6SAntoine Tenart 
1489b460edb6SAntoine Tenart 	memset(req, 0, sizeof(*req));
1490b460edb6SAntoine Tenart 
1491b460edb6SAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
1492b460edb6SAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1493b460edb6SAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
149441abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
1495b460edb6SAntoine Tenart 
1496b460edb6SAntoine Tenart 	return 0;
1497b460edb6SAntoine Tenart }
1498b460edb6SAntoine Tenart 
1499b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq)
1500b460edb6SAntoine Tenart {
1501b460edb6SAntoine Tenart 	int ret = safexcel_sha512_init(areq);
1502b460edb6SAntoine Tenart 
1503b460edb6SAntoine Tenart 	if (ret)
1504b460edb6SAntoine Tenart 		return ret;
1505b460edb6SAntoine Tenart 
1506b460edb6SAntoine Tenart 	return safexcel_ahash_finup(areq);
1507b460edb6SAntoine Tenart }
1508b460edb6SAntoine Tenart 
1509b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = {
1510b460edb6SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1511062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
1512b460edb6SAntoine Tenart 	.alg.ahash = {
1513b460edb6SAntoine Tenart 		.init = safexcel_sha512_init,
1514b460edb6SAntoine Tenart 		.update = safexcel_ahash_update,
1515b460edb6SAntoine Tenart 		.final = safexcel_ahash_final,
1516b460edb6SAntoine Tenart 		.finup = safexcel_ahash_finup,
1517b460edb6SAntoine Tenart 		.digest = safexcel_sha512_digest,
1518b460edb6SAntoine Tenart 		.export = safexcel_ahash_export,
1519b460edb6SAntoine Tenart 		.import = safexcel_ahash_import,
1520b460edb6SAntoine Tenart 		.halg = {
1521b460edb6SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
1522b460edb6SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
1523b460edb6SAntoine Tenart 			.base = {
1524b460edb6SAntoine Tenart 				.cra_name = "sha512",
1525b460edb6SAntoine Tenart 				.cra_driver_name = "safexcel-sha512",
1526aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1527b460edb6SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
1528b460edb6SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1529b460edb6SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
1530b460edb6SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1531b460edb6SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
1532b460edb6SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
1533b460edb6SAntoine Tenart 				.cra_module = THIS_MODULE,
1534b460edb6SAntoine Tenart 			},
1535b460edb6SAntoine Tenart 		},
1536b460edb6SAntoine Tenart 	},
1537b460edb6SAntoine Tenart };
15380de54fb1SAntoine Tenart 
15399e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq)
15409e46eafdSAntoine Tenart {
15419e46eafdSAntoine Tenart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
15429e46eafdSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
15439e46eafdSAntoine Tenart 
15449e46eafdSAntoine Tenart 	memset(req, 0, sizeof(*req));
15459e46eafdSAntoine Tenart 
15469e46eafdSAntoine Tenart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
15479e46eafdSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
15489e46eafdSAntoine Tenart 	req->state_sz = SHA512_DIGEST_SIZE;
154941abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
15509e46eafdSAntoine Tenart 
15519e46eafdSAntoine Tenart 	return 0;
15529e46eafdSAntoine Tenart }
15539e46eafdSAntoine Tenart 
15549e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq)
15559e46eafdSAntoine Tenart {
15569e46eafdSAntoine Tenart 	int ret = safexcel_sha384_init(areq);
15579e46eafdSAntoine Tenart 
15589e46eafdSAntoine Tenart 	if (ret)
15599e46eafdSAntoine Tenart 		return ret;
15609e46eafdSAntoine Tenart 
15619e46eafdSAntoine Tenart 	return safexcel_ahash_finup(areq);
15629e46eafdSAntoine Tenart }
15639e46eafdSAntoine Tenart 
15649e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = {
15659e46eafdSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1566062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
15679e46eafdSAntoine Tenart 	.alg.ahash = {
15689e46eafdSAntoine Tenart 		.init = safexcel_sha384_init,
15699e46eafdSAntoine Tenart 		.update = safexcel_ahash_update,
15709e46eafdSAntoine Tenart 		.final = safexcel_ahash_final,
15719e46eafdSAntoine Tenart 		.finup = safexcel_ahash_finup,
15729e46eafdSAntoine Tenart 		.digest = safexcel_sha384_digest,
15739e46eafdSAntoine Tenart 		.export = safexcel_ahash_export,
15749e46eafdSAntoine Tenart 		.import = safexcel_ahash_import,
15759e46eafdSAntoine Tenart 		.halg = {
15769e46eafdSAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
15779e46eafdSAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
15789e46eafdSAntoine Tenart 			.base = {
15799e46eafdSAntoine Tenart 				.cra_name = "sha384",
15809e46eafdSAntoine Tenart 				.cra_driver_name = "safexcel-sha384",
1581aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
15829e46eafdSAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
15839e46eafdSAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
15849e46eafdSAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
15859e46eafdSAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
15869e46eafdSAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
15879e46eafdSAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
15889e46eafdSAntoine Tenart 				.cra_module = THIS_MODULE,
15899e46eafdSAntoine Tenart 			},
15909e46eafdSAntoine Tenart 		},
15919e46eafdSAntoine Tenart 	},
15929e46eafdSAntoine Tenart };
15939e46eafdSAntoine Tenart 
15940de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key,
15950de54fb1SAntoine Tenart 				       unsigned int keylen)
15960de54fb1SAntoine Tenart {
15970de54fb1SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512",
15980de54fb1SAntoine Tenart 					SHA512_DIGEST_SIZE);
15990de54fb1SAntoine Tenart }
16000de54fb1SAntoine Tenart 
16010de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq)
16020de54fb1SAntoine Tenart {
160341abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
16040de54fb1SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
16050de54fb1SAntoine Tenart 
160641abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
160741abed7dSPascal van Leeuwen 
160841abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
160941abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE);
161041abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
161131fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
161231fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
161341abed7dSPascal van Leeuwen 
161441abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
161541abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
161641abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
161741abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
161841abed7dSPascal van Leeuwen 	req->hmac = true;
161941abed7dSPascal van Leeuwen 
16200de54fb1SAntoine Tenart 	return 0;
16210de54fb1SAntoine Tenart }
16220de54fb1SAntoine Tenart 
16230de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq)
16240de54fb1SAntoine Tenart {
16250de54fb1SAntoine Tenart 	int ret = safexcel_hmac_sha512_init(areq);
16260de54fb1SAntoine Tenart 
16270de54fb1SAntoine Tenart 	if (ret)
16280de54fb1SAntoine Tenart 		return ret;
16290de54fb1SAntoine Tenart 
16300de54fb1SAntoine Tenart 	return safexcel_ahash_finup(areq);
16310de54fb1SAntoine Tenart }
16320de54fb1SAntoine Tenart 
16330de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = {
16340de54fb1SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1635062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
16360de54fb1SAntoine Tenart 	.alg.ahash = {
16370de54fb1SAntoine Tenart 		.init = safexcel_hmac_sha512_init,
16380de54fb1SAntoine Tenart 		.update = safexcel_ahash_update,
16390de54fb1SAntoine Tenart 		.final = safexcel_ahash_final,
16400de54fb1SAntoine Tenart 		.finup = safexcel_ahash_finup,
16410de54fb1SAntoine Tenart 		.digest = safexcel_hmac_sha512_digest,
16420de54fb1SAntoine Tenart 		.setkey = safexcel_hmac_sha512_setkey,
16430de54fb1SAntoine Tenart 		.export = safexcel_ahash_export,
16440de54fb1SAntoine Tenart 		.import = safexcel_ahash_import,
16450de54fb1SAntoine Tenart 		.halg = {
16460de54fb1SAntoine Tenart 			.digestsize = SHA512_DIGEST_SIZE,
16470de54fb1SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
16480de54fb1SAntoine Tenart 			.base = {
16490de54fb1SAntoine Tenart 				.cra_name = "hmac(sha512)",
16500de54fb1SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha512",
1651aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
16520de54fb1SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
16530de54fb1SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
16540de54fb1SAntoine Tenart 				.cra_blocksize = SHA512_BLOCK_SIZE,
16550de54fb1SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
16560de54fb1SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
16570de54fb1SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
16580de54fb1SAntoine Tenart 				.cra_module = THIS_MODULE,
16590de54fb1SAntoine Tenart 			},
16600de54fb1SAntoine Tenart 		},
16610de54fb1SAntoine Tenart 	},
16620de54fb1SAntoine Tenart };
16631f5d5d98SAntoine Tenart 
16641f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key,
16651f5d5d98SAntoine Tenart 				       unsigned int keylen)
16661f5d5d98SAntoine Tenart {
16671f5d5d98SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384",
16681f5d5d98SAntoine Tenart 					SHA512_DIGEST_SIZE);
16691f5d5d98SAntoine Tenart }
16701f5d5d98SAntoine Tenart 
16711f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq)
16721f5d5d98SAntoine Tenart {
167341abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
16741f5d5d98SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
16751f5d5d98SAntoine Tenart 
167641abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
167741abed7dSPascal van Leeuwen 
167841abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
167941abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE);
168041abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
168131fb084cSPascal van Leeuwen 	req->len	= SHA512_BLOCK_SIZE;
168231fb084cSPascal van Leeuwen 	req->processed	= SHA512_BLOCK_SIZE;
168341abed7dSPascal van Leeuwen 
168441abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
168541abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
168641abed7dSPascal van Leeuwen 	req->state_sz = SHA512_DIGEST_SIZE;
168741abed7dSPascal van Leeuwen 	req->block_sz = SHA512_BLOCK_SIZE;
168841abed7dSPascal van Leeuwen 	req->hmac = true;
168941abed7dSPascal van Leeuwen 
16901f5d5d98SAntoine Tenart 	return 0;
16911f5d5d98SAntoine Tenart }
16921f5d5d98SAntoine Tenart 
16931f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq)
16941f5d5d98SAntoine Tenart {
16951f5d5d98SAntoine Tenart 	int ret = safexcel_hmac_sha384_init(areq);
16961f5d5d98SAntoine Tenart 
16971f5d5d98SAntoine Tenart 	if (ret)
16981f5d5d98SAntoine Tenart 		return ret;
16991f5d5d98SAntoine Tenart 
17001f5d5d98SAntoine Tenart 	return safexcel_ahash_finup(areq);
17011f5d5d98SAntoine Tenart }
17021f5d5d98SAntoine Tenart 
17031f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = {
17041f5d5d98SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1705062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SHA2_512,
17061f5d5d98SAntoine Tenart 	.alg.ahash = {
17071f5d5d98SAntoine Tenart 		.init = safexcel_hmac_sha384_init,
17081f5d5d98SAntoine Tenart 		.update = safexcel_ahash_update,
17091f5d5d98SAntoine Tenart 		.final = safexcel_ahash_final,
17101f5d5d98SAntoine Tenart 		.finup = safexcel_ahash_finup,
17111f5d5d98SAntoine Tenart 		.digest = safexcel_hmac_sha384_digest,
17121f5d5d98SAntoine Tenart 		.setkey = safexcel_hmac_sha384_setkey,
17131f5d5d98SAntoine Tenart 		.export = safexcel_ahash_export,
17141f5d5d98SAntoine Tenart 		.import = safexcel_ahash_import,
17151f5d5d98SAntoine Tenart 		.halg = {
17161f5d5d98SAntoine Tenart 			.digestsize = SHA384_DIGEST_SIZE,
17171f5d5d98SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
17181f5d5d98SAntoine Tenart 			.base = {
17191f5d5d98SAntoine Tenart 				.cra_name = "hmac(sha384)",
17201f5d5d98SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha384",
1721aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
17221f5d5d98SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
17231f5d5d98SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
17241f5d5d98SAntoine Tenart 				.cra_blocksize = SHA384_BLOCK_SIZE,
17251f5d5d98SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
17261f5d5d98SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
17271f5d5d98SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
17281f5d5d98SAntoine Tenart 				.cra_module = THIS_MODULE,
17291f5d5d98SAntoine Tenart 			},
17301f5d5d98SAntoine Tenart 		},
17311f5d5d98SAntoine Tenart 	},
17321f5d5d98SAntoine Tenart };
1733293f89cfSOfer Heifetz 
1734293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq)
1735293f89cfSOfer Heifetz {
1736293f89cfSOfer Heifetz 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1737293f89cfSOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1738293f89cfSOfer Heifetz 
1739293f89cfSOfer Heifetz 	memset(req, 0, sizeof(*req));
1740293f89cfSOfer Heifetz 
1741293f89cfSOfer Heifetz 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
1742293f89cfSOfer Heifetz 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
1743293f89cfSOfer Heifetz 	req->state_sz = MD5_DIGEST_SIZE;
174441abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
1745293f89cfSOfer Heifetz 
1746293f89cfSOfer Heifetz 	return 0;
1747293f89cfSOfer Heifetz }
1748293f89cfSOfer Heifetz 
1749293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq)
1750293f89cfSOfer Heifetz {
1751293f89cfSOfer Heifetz 	int ret = safexcel_md5_init(areq);
1752293f89cfSOfer Heifetz 
1753293f89cfSOfer Heifetz 	if (ret)
1754293f89cfSOfer Heifetz 		return ret;
1755293f89cfSOfer Heifetz 
1756293f89cfSOfer Heifetz 	return safexcel_ahash_finup(areq);
1757293f89cfSOfer Heifetz }
1758293f89cfSOfer Heifetz 
1759293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = {
1760293f89cfSOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1761062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1762293f89cfSOfer Heifetz 	.alg.ahash = {
1763293f89cfSOfer Heifetz 		.init = safexcel_md5_init,
1764293f89cfSOfer Heifetz 		.update = safexcel_ahash_update,
1765293f89cfSOfer Heifetz 		.final = safexcel_ahash_final,
1766293f89cfSOfer Heifetz 		.finup = safexcel_ahash_finup,
1767293f89cfSOfer Heifetz 		.digest = safexcel_md5_digest,
1768293f89cfSOfer Heifetz 		.export = safexcel_ahash_export,
1769293f89cfSOfer Heifetz 		.import = safexcel_ahash_import,
1770293f89cfSOfer Heifetz 		.halg = {
1771293f89cfSOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1772293f89cfSOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1773293f89cfSOfer Heifetz 			.base = {
1774293f89cfSOfer Heifetz 				.cra_name = "md5",
1775293f89cfSOfer Heifetz 				.cra_driver_name = "safexcel-md5",
1776aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1777293f89cfSOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1778293f89cfSOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1779293f89cfSOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1780293f89cfSOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1781293f89cfSOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1782293f89cfSOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1783293f89cfSOfer Heifetz 				.cra_module = THIS_MODULE,
1784293f89cfSOfer Heifetz 			},
1785293f89cfSOfer Heifetz 		},
1786293f89cfSOfer Heifetz 	},
1787293f89cfSOfer Heifetz };
1788b471e4b9SOfer Heifetz 
1789b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq)
1790b471e4b9SOfer Heifetz {
179141abed7dSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1792b471e4b9SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1793b471e4b9SOfer Heifetz 
179441abed7dSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
179541abed7dSPascal van Leeuwen 
179641abed7dSPascal van Leeuwen 	/* Start from ipad precompute */
179741abed7dSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, MD5_DIGEST_SIZE);
179841abed7dSPascal van Leeuwen 	/* Already processed the key^ipad part now! */
179931fb084cSPascal van Leeuwen 	req->len	= MD5_HMAC_BLOCK_SIZE;
180031fb084cSPascal van Leeuwen 	req->processed	= MD5_HMAC_BLOCK_SIZE;
180141abed7dSPascal van Leeuwen 
180241abed7dSPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
180341abed7dSPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
180441abed7dSPascal van Leeuwen 	req->state_sz = MD5_DIGEST_SIZE;
180541abed7dSPascal van Leeuwen 	req->block_sz = MD5_HMAC_BLOCK_SIZE;
180685b36ee8SPascal van Leeuwen 	req->len_is_le = true; /* MD5 is little endian! ... */
180741abed7dSPascal van Leeuwen 	req->hmac = true;
180841abed7dSPascal van Leeuwen 
1809b471e4b9SOfer Heifetz 	return 0;
1810b471e4b9SOfer Heifetz }
1811b471e4b9SOfer Heifetz 
1812b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key,
1813b471e4b9SOfer Heifetz 				     unsigned int keylen)
1814b471e4b9SOfer Heifetz {
1815b471e4b9SOfer Heifetz 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5",
1816b471e4b9SOfer Heifetz 					MD5_DIGEST_SIZE);
1817b471e4b9SOfer Heifetz }
1818b471e4b9SOfer Heifetz 
1819b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq)
1820b471e4b9SOfer Heifetz {
1821b471e4b9SOfer Heifetz 	int ret = safexcel_hmac_md5_init(areq);
1822b471e4b9SOfer Heifetz 
1823b471e4b9SOfer Heifetz 	if (ret)
1824b471e4b9SOfer Heifetz 		return ret;
1825b471e4b9SOfer Heifetz 
1826b471e4b9SOfer Heifetz 	return safexcel_ahash_finup(areq);
1827b471e4b9SOfer Heifetz }
1828b471e4b9SOfer Heifetz 
1829b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = {
1830b471e4b9SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1831062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_MD5,
1832b471e4b9SOfer Heifetz 	.alg.ahash = {
1833b471e4b9SOfer Heifetz 		.init = safexcel_hmac_md5_init,
1834b471e4b9SOfer Heifetz 		.update = safexcel_ahash_update,
1835b471e4b9SOfer Heifetz 		.final = safexcel_ahash_final,
1836b471e4b9SOfer Heifetz 		.finup = safexcel_ahash_finup,
1837b471e4b9SOfer Heifetz 		.digest = safexcel_hmac_md5_digest,
1838b471e4b9SOfer Heifetz 		.setkey = safexcel_hmac_md5_setkey,
1839b471e4b9SOfer Heifetz 		.export = safexcel_ahash_export,
1840b471e4b9SOfer Heifetz 		.import = safexcel_ahash_import,
1841b471e4b9SOfer Heifetz 		.halg = {
1842b471e4b9SOfer Heifetz 			.digestsize = MD5_DIGEST_SIZE,
1843b471e4b9SOfer Heifetz 			.statesize = sizeof(struct safexcel_ahash_export_state),
1844b471e4b9SOfer Heifetz 			.base = {
1845b471e4b9SOfer Heifetz 				.cra_name = "hmac(md5)",
1846b471e4b9SOfer Heifetz 				.cra_driver_name = "safexcel-hmac-md5",
1847aa88f331SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1848b471e4b9SOfer Heifetz 				.cra_flags = CRYPTO_ALG_ASYNC |
1849b471e4b9SOfer Heifetz 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1850b471e4b9SOfer Heifetz 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1851b471e4b9SOfer Heifetz 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1852b471e4b9SOfer Heifetz 				.cra_init = safexcel_ahash_cra_init,
1853b471e4b9SOfer Heifetz 				.cra_exit = safexcel_ahash_cra_exit,
1854b471e4b9SOfer Heifetz 				.cra_module = THIS_MODULE,
1855b471e4b9SOfer Heifetz 			},
1856b471e4b9SOfer Heifetz 		},
1857b471e4b9SOfer Heifetz 	},
1858b471e4b9SOfer Heifetz };
1859a7cf8658SPascal van Leeuwen 
1860a7cf8658SPascal van Leeuwen static int safexcel_crc32_cra_init(struct crypto_tfm *tfm)
1861a7cf8658SPascal van Leeuwen {
1862a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
1863a7cf8658SPascal van Leeuwen 	int ret = safexcel_ahash_cra_init(tfm);
1864a7cf8658SPascal van Leeuwen 
1865a7cf8658SPascal van Leeuwen 	/* Default 'key' is all zeroes */
1866a7cf8658SPascal van Leeuwen 	memset(ctx->ipad, 0, sizeof(u32));
1867a7cf8658SPascal van Leeuwen 	return ret;
1868a7cf8658SPascal van Leeuwen }
1869a7cf8658SPascal van Leeuwen 
1870a7cf8658SPascal van Leeuwen static int safexcel_crc32_init(struct ahash_request *areq)
1871a7cf8658SPascal van Leeuwen {
1872a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1873a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1874a7cf8658SPascal van Leeuwen 
1875a7cf8658SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1876a7cf8658SPascal van Leeuwen 
1877a7cf8658SPascal van Leeuwen 	/* Start from loaded key */
1878a7cf8658SPascal van Leeuwen 	req->state[0]	= cpu_to_le32(~ctx->ipad[0]);
1879a7cf8658SPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
1880a7cf8658SPascal van Leeuwen 	req->len	= sizeof(u32);
1881a7cf8658SPascal van Leeuwen 	req->processed	= sizeof(u32);
1882a7cf8658SPascal van Leeuwen 
1883a7cf8658SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32;
1884a7cf8658SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_XCM;
1885a7cf8658SPascal van Leeuwen 	req->state_sz = sizeof(u32);
1886a7cf8658SPascal van Leeuwen 	req->block_sz = sizeof(u32);
1887a7cf8658SPascal van Leeuwen 
1888a7cf8658SPascal van Leeuwen 	return 0;
1889a7cf8658SPascal van Leeuwen }
1890a7cf8658SPascal van Leeuwen 
1891a7cf8658SPascal van Leeuwen static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key,
1892a7cf8658SPascal van Leeuwen 				 unsigned int keylen)
1893a7cf8658SPascal van Leeuwen {
1894a7cf8658SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1895a7cf8658SPascal van Leeuwen 
1896a7cf8658SPascal van Leeuwen 	if (keylen != sizeof(u32)) {
1897a7cf8658SPascal van Leeuwen 		crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
1898a7cf8658SPascal van Leeuwen 		return -EINVAL;
1899a7cf8658SPascal van Leeuwen 	}
1900a7cf8658SPascal van Leeuwen 
1901a7cf8658SPascal van Leeuwen 	memcpy(ctx->ipad, key, sizeof(u32));
1902a7cf8658SPascal van Leeuwen 	return 0;
1903a7cf8658SPascal van Leeuwen }
1904a7cf8658SPascal van Leeuwen 
1905a7cf8658SPascal van Leeuwen static int safexcel_crc32_digest(struct ahash_request *areq)
1906a7cf8658SPascal van Leeuwen {
1907a7cf8658SPascal van Leeuwen 	return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq);
1908a7cf8658SPascal van Leeuwen }
1909a7cf8658SPascal van Leeuwen 
1910a7cf8658SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_crc32 = {
1911a7cf8658SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
1912a7cf8658SPascal van Leeuwen 	.algo_mask = 0,
1913a7cf8658SPascal van Leeuwen 	.alg.ahash = {
1914a7cf8658SPascal van Leeuwen 		.init = safexcel_crc32_init,
1915a7cf8658SPascal van Leeuwen 		.update = safexcel_ahash_update,
1916a7cf8658SPascal van Leeuwen 		.final = safexcel_ahash_final,
1917a7cf8658SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
1918a7cf8658SPascal van Leeuwen 		.digest = safexcel_crc32_digest,
1919a7cf8658SPascal van Leeuwen 		.setkey = safexcel_crc32_setkey,
1920a7cf8658SPascal van Leeuwen 		.export = safexcel_ahash_export,
1921a7cf8658SPascal van Leeuwen 		.import = safexcel_ahash_import,
1922a7cf8658SPascal van Leeuwen 		.halg = {
1923a7cf8658SPascal van Leeuwen 			.digestsize = sizeof(u32),
1924a7cf8658SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
1925a7cf8658SPascal van Leeuwen 			.base = {
1926a7cf8658SPascal van Leeuwen 				.cra_name = "crc32",
1927a7cf8658SPascal van Leeuwen 				.cra_driver_name = "safexcel-crc32",
1928a7cf8658SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
1929a7cf8658SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_OPTIONAL_KEY |
1930a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_ASYNC |
1931a7cf8658SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
1932a7cf8658SPascal van Leeuwen 				.cra_blocksize = 1,
1933a7cf8658SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
1934a7cf8658SPascal van Leeuwen 				.cra_init = safexcel_crc32_cra_init,
1935a7cf8658SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
1936a7cf8658SPascal van Leeuwen 				.cra_module = THIS_MODULE,
1937a7cf8658SPascal van Leeuwen 			},
1938a7cf8658SPascal van Leeuwen 		},
1939a7cf8658SPascal van Leeuwen 	},
1940a7cf8658SPascal van Leeuwen };
1941b98687bbSPascal van Leeuwen 
1942b98687bbSPascal van Leeuwen static int safexcel_cbcmac_init(struct ahash_request *areq)
1943b98687bbSPascal van Leeuwen {
1944b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1945b98687bbSPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1946b98687bbSPascal van Leeuwen 
1947b98687bbSPascal van Leeuwen 	memset(req, 0, sizeof(*req));
1948b98687bbSPascal van Leeuwen 
1949b98687bbSPascal van Leeuwen 	/* Start from loaded keys */
1950b98687bbSPascal van Leeuwen 	memcpy(req->state, ctx->ipad, ctx->key_sz);
1951b98687bbSPascal van Leeuwen 	/* Set processed to non-zero to enable invalidation detection */
1952b98687bbSPascal van Leeuwen 	req->len	= AES_BLOCK_SIZE;
1953b98687bbSPascal van Leeuwen 	req->processed	= AES_BLOCK_SIZE;
1954b98687bbSPascal van Leeuwen 
1955b98687bbSPascal van Leeuwen 	req->digest   = CONTEXT_CONTROL_DIGEST_XCM;
1956b98687bbSPascal van Leeuwen 	req->state_sz = ctx->key_sz;
1957b98687bbSPascal van Leeuwen 	req->block_sz = AES_BLOCK_SIZE;
1958b98687bbSPascal van Leeuwen 	req->xcbcmac  = true;
1959b98687bbSPascal van Leeuwen 
1960b98687bbSPascal van Leeuwen 	return 0;
1961b98687bbSPascal van Leeuwen }
1962b98687bbSPascal van Leeuwen 
1963b98687bbSPascal van Leeuwen static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
1964b98687bbSPascal van Leeuwen 				 unsigned int len)
1965b98687bbSPascal van Leeuwen {
1966b98687bbSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1967b98687bbSPascal van Leeuwen 	struct crypto_aes_ctx aes;
1968b98687bbSPascal van Leeuwen 	int ret, i;
1969b98687bbSPascal van Leeuwen 
1970b98687bbSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
1971b98687bbSPascal van Leeuwen 	if (ret) {
1972b98687bbSPascal van Leeuwen 		crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
1973b98687bbSPascal van Leeuwen 		return ret;
1974b98687bbSPascal van Leeuwen 	}
1975b98687bbSPascal van Leeuwen 
1976b98687bbSPascal van Leeuwen 	memset(ctx->ipad, 0, 2 * AES_BLOCK_SIZE);
1977b98687bbSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
1978b98687bbSPascal van Leeuwen 		ctx->ipad[i + 8] = cpu_to_be32(aes.key_enc[i]);
1979b98687bbSPascal van Leeuwen 
1980b98687bbSPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
1981b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
1982b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
1983b98687bbSPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
1984b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
1985b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
1986b98687bbSPascal van Leeuwen 	} else {
1987b98687bbSPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
1988b98687bbSPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
1989b98687bbSPascal van Leeuwen 	}
199038f21b4bSPascal van Leeuwen 	ctx->cbcmac  = true;
1991b98687bbSPascal van Leeuwen 
1992b98687bbSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
1993b98687bbSPascal van Leeuwen 	return 0;
1994b98687bbSPascal van Leeuwen }
1995b98687bbSPascal van Leeuwen 
1996b98687bbSPascal van Leeuwen static int safexcel_cbcmac_digest(struct ahash_request *areq)
1997b98687bbSPascal van Leeuwen {
1998b98687bbSPascal van Leeuwen 	return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq);
1999b98687bbSPascal van Leeuwen }
2000b98687bbSPascal van Leeuwen 
2001b98687bbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbcmac = {
2002b98687bbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
2003b98687bbSPascal van Leeuwen 	.algo_mask = 0,
2004b98687bbSPascal van Leeuwen 	.alg.ahash = {
2005b98687bbSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
2006b98687bbSPascal van Leeuwen 		.update = safexcel_ahash_update,
2007b98687bbSPascal van Leeuwen 		.final = safexcel_ahash_final,
2008b98687bbSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
2009b98687bbSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
2010b98687bbSPascal van Leeuwen 		.setkey = safexcel_cbcmac_setkey,
2011b98687bbSPascal van Leeuwen 		.export = safexcel_ahash_export,
2012b98687bbSPascal van Leeuwen 		.import = safexcel_ahash_import,
2013b98687bbSPascal van Leeuwen 		.halg = {
2014b98687bbSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
2015b98687bbSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
2016b98687bbSPascal van Leeuwen 			.base = {
2017b98687bbSPascal van Leeuwen 				.cra_name = "cbcmac(aes)",
2018b98687bbSPascal van Leeuwen 				.cra_driver_name = "safexcel-cbcmac-aes",
2019b98687bbSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
2020b98687bbSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
2021b98687bbSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
2022b98687bbSPascal van Leeuwen 				.cra_blocksize = 1,
2023b98687bbSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
2024b98687bbSPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
2025b98687bbSPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
2026b98687bbSPascal van Leeuwen 				.cra_module = THIS_MODULE,
2027b98687bbSPascal van Leeuwen 			},
2028b98687bbSPascal van Leeuwen 		},
2029b98687bbSPascal van Leeuwen 	},
2030b98687bbSPascal van Leeuwen };
203138f21b4bSPascal van Leeuwen 
203238f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
203338f21b4bSPascal van Leeuwen 				 unsigned int len)
203438f21b4bSPascal van Leeuwen {
203538f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
203638f21b4bSPascal van Leeuwen 	struct crypto_aes_ctx aes;
203738f21b4bSPascal van Leeuwen 	u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)];
203838f21b4bSPascal van Leeuwen 	int ret, i;
203938f21b4bSPascal van Leeuwen 
204038f21b4bSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
204138f21b4bSPascal van Leeuwen 	if (ret) {
204238f21b4bSPascal van Leeuwen 		crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
204338f21b4bSPascal van Leeuwen 		return ret;
204438f21b4bSPascal van Leeuwen 	}
204538f21b4bSPascal van Leeuwen 
204638f21b4bSPascal van Leeuwen 	/* precompute the XCBC key material */
204738f21b4bSPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK);
204838f21b4bSPascal van Leeuwen 	crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) &
204938f21b4bSPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
205038f21b4bSPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->kaes, key, len);
205138f21b4bSPascal van Leeuwen 	crypto_ahash_set_flags(tfm, crypto_cipher_get_flags(ctx->kaes) &
205238f21b4bSPascal van Leeuwen 			       CRYPTO_TFM_RES_MASK);
205338f21b4bSPascal van Leeuwen 	if (ret)
205438f21b4bSPascal van Leeuwen 		return ret;
205538f21b4bSPascal van Leeuwen 
205638f21b4bSPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
205738f21b4bSPascal van Leeuwen 		"\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1");
205838f21b4bSPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp,
205938f21b4bSPascal van Leeuwen 		"\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2");
206038f21b4bSPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + AES_BLOCK_SIZE,
206138f21b4bSPascal van Leeuwen 		"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3");
206238f21b4bSPascal van Leeuwen 	for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++)
206338f21b4bSPascal van Leeuwen 		ctx->ipad[i] = cpu_to_be32(key_tmp[i]);
206438f21b4bSPascal van Leeuwen 
206538f21b4bSPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK);
206638f21b4bSPascal van Leeuwen 	crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) &
206738f21b4bSPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
206838f21b4bSPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->kaes,
206938f21b4bSPascal van Leeuwen 				   (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
207038f21b4bSPascal van Leeuwen 				   AES_MIN_KEY_SIZE);
207138f21b4bSPascal van Leeuwen 	crypto_ahash_set_flags(tfm, crypto_cipher_get_flags(ctx->kaes) &
207238f21b4bSPascal van Leeuwen 			       CRYPTO_TFM_RES_MASK);
207338f21b4bSPascal van Leeuwen 	if (ret)
207438f21b4bSPascal van Leeuwen 		return ret;
207538f21b4bSPascal van Leeuwen 
207638f21b4bSPascal van Leeuwen 	ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
207738f21b4bSPascal van Leeuwen 	ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
207838f21b4bSPascal van Leeuwen 	ctx->cbcmac = false;
207938f21b4bSPascal van Leeuwen 
208038f21b4bSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
208138f21b4bSPascal van Leeuwen 	return 0;
208238f21b4bSPascal van Leeuwen }
208338f21b4bSPascal van Leeuwen 
208438f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm)
208538f21b4bSPascal van Leeuwen {
208638f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
208738f21b4bSPascal van Leeuwen 
208838f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_init(tfm);
208938f21b4bSPascal van Leeuwen 	ctx->kaes = crypto_alloc_cipher("aes", 0, 0);
209038f21b4bSPascal van Leeuwen 	if (IS_ERR(ctx->kaes))
209138f21b4bSPascal van Leeuwen 		return PTR_ERR(ctx->kaes);
209238f21b4bSPascal van Leeuwen 
209338f21b4bSPascal van Leeuwen 	return 0;
209438f21b4bSPascal van Leeuwen }
209538f21b4bSPascal van Leeuwen 
209638f21b4bSPascal van Leeuwen static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm)
209738f21b4bSPascal van Leeuwen {
209838f21b4bSPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
209938f21b4bSPascal van Leeuwen 
210038f21b4bSPascal van Leeuwen 	crypto_free_cipher(ctx->kaes);
210138f21b4bSPascal van Leeuwen 	safexcel_ahash_cra_exit(tfm);
210238f21b4bSPascal van Leeuwen }
210338f21b4bSPascal van Leeuwen 
210438f21b4bSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xcbcmac = {
210538f21b4bSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
210638f21b4bSPascal van Leeuwen 	.algo_mask = 0,
210738f21b4bSPascal van Leeuwen 	.alg.ahash = {
210838f21b4bSPascal van Leeuwen 		.init = safexcel_cbcmac_init,
210938f21b4bSPascal van Leeuwen 		.update = safexcel_ahash_update,
211038f21b4bSPascal van Leeuwen 		.final = safexcel_ahash_final,
211138f21b4bSPascal van Leeuwen 		.finup = safexcel_ahash_finup,
211238f21b4bSPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
211338f21b4bSPascal van Leeuwen 		.setkey = safexcel_xcbcmac_setkey,
211438f21b4bSPascal van Leeuwen 		.export = safexcel_ahash_export,
211538f21b4bSPascal van Leeuwen 		.import = safexcel_ahash_import,
211638f21b4bSPascal van Leeuwen 		.halg = {
211738f21b4bSPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
211838f21b4bSPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
211938f21b4bSPascal van Leeuwen 			.base = {
212038f21b4bSPascal van Leeuwen 				.cra_name = "xcbc(aes)",
212138f21b4bSPascal van Leeuwen 				.cra_driver_name = "safexcel-xcbc-aes",
212238f21b4bSPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
212338f21b4bSPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
212438f21b4bSPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
212538f21b4bSPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
212638f21b4bSPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
212738f21b4bSPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
212838f21b4bSPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
212938f21b4bSPascal van Leeuwen 				.cra_module = THIS_MODULE,
213038f21b4bSPascal van Leeuwen 			},
213138f21b4bSPascal van Leeuwen 		},
213238f21b4bSPascal van Leeuwen 	},
213338f21b4bSPascal van Leeuwen };
21347a627db9SPascal van Leeuwen 
21357a627db9SPascal van Leeuwen static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
21367a627db9SPascal van Leeuwen 				unsigned int len)
21377a627db9SPascal van Leeuwen {
21387a627db9SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
21397a627db9SPascal van Leeuwen 	struct crypto_aes_ctx aes;
21407a627db9SPascal van Leeuwen 	__be64 consts[4];
21417a627db9SPascal van Leeuwen 	u64 _const[2];
21427a627db9SPascal van Leeuwen 	u8 msb_mask, gfmask;
21437a627db9SPascal van Leeuwen 	int ret, i;
21447a627db9SPascal van Leeuwen 
21457a627db9SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
21467a627db9SPascal van Leeuwen 	if (ret) {
21477a627db9SPascal van Leeuwen 		crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
21487a627db9SPascal van Leeuwen 		return ret;
21497a627db9SPascal van Leeuwen 	}
21507a627db9SPascal van Leeuwen 
21517a627db9SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
21527a627db9SPascal van Leeuwen 		ctx->ipad[i + 8] = cpu_to_be32(aes.key_enc[i]);
21537a627db9SPascal van Leeuwen 
21547a627db9SPascal van Leeuwen 	/* precompute the CMAC key material */
21557a627db9SPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK);
21567a627db9SPascal van Leeuwen 	crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) &
21577a627db9SPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
21587a627db9SPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->kaes, key, len);
21597a627db9SPascal van Leeuwen 	crypto_ahash_set_flags(tfm, crypto_cipher_get_flags(ctx->kaes) &
21607a627db9SPascal van Leeuwen 			       CRYPTO_TFM_RES_MASK);
21617a627db9SPascal van Leeuwen 	if (ret)
21627a627db9SPascal van Leeuwen 		return ret;
21637a627db9SPascal van Leeuwen 
21647a627db9SPascal van Leeuwen 	/* code below borrowed from crypto/cmac.c */
21657a627db9SPascal van Leeuwen 	/* encrypt the zero block */
21667a627db9SPascal van Leeuwen 	memset(consts, 0, AES_BLOCK_SIZE);
21677a627db9SPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->kaes, (u8 *)consts, (u8 *)consts);
21687a627db9SPascal van Leeuwen 
21697a627db9SPascal van Leeuwen 	gfmask = 0x87;
21707a627db9SPascal van Leeuwen 	_const[0] = be64_to_cpu(consts[1]);
21717a627db9SPascal van Leeuwen 	_const[1] = be64_to_cpu(consts[0]);
21727a627db9SPascal van Leeuwen 
21737a627db9SPascal van Leeuwen 	/* gf(2^128) multiply zero-ciphertext with u and u^2 */
21747a627db9SPascal van Leeuwen 	for (i = 0; i < 4; i += 2) {
21757a627db9SPascal van Leeuwen 		msb_mask = ((s64)_const[1] >> 63) & gfmask;
21767a627db9SPascal van Leeuwen 		_const[1] = (_const[1] << 1) | (_const[0] >> 63);
21777a627db9SPascal van Leeuwen 		_const[0] = (_const[0] << 1) ^ msb_mask;
21787a627db9SPascal van Leeuwen 
21797a627db9SPascal van Leeuwen 		consts[i + 0] = cpu_to_be64(_const[1]);
21807a627db9SPascal van Leeuwen 		consts[i + 1] = cpu_to_be64(_const[0]);
21817a627db9SPascal van Leeuwen 	}
21827a627db9SPascal van Leeuwen 	/* end of code borrowed from crypto/cmac.c */
21837a627db9SPascal van Leeuwen 
21847a627db9SPascal van Leeuwen 	for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++)
21857a627db9SPascal van Leeuwen 		ctx->ipad[i] = cpu_to_be32(((u32 *)consts)[i]);
21867a627db9SPascal van Leeuwen 
21877a627db9SPascal van Leeuwen 	if (len == AES_KEYSIZE_192) {
21887a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
21897a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
21907a627db9SPascal van Leeuwen 	} else if (len == AES_KEYSIZE_256) {
21917a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
21927a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
21937a627db9SPascal van Leeuwen 	} else {
21947a627db9SPascal van Leeuwen 		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
21957a627db9SPascal van Leeuwen 		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
21967a627db9SPascal van Leeuwen 	}
21977a627db9SPascal van Leeuwen 	ctx->cbcmac = false;
21987a627db9SPascal van Leeuwen 
21997a627db9SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
22007a627db9SPascal van Leeuwen 	return 0;
22017a627db9SPascal van Leeuwen }
22027a627db9SPascal van Leeuwen 
22037a627db9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cmac = {
22047a627db9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
22057a627db9SPascal van Leeuwen 	.algo_mask = 0,
22067a627db9SPascal van Leeuwen 	.alg.ahash = {
22077a627db9SPascal van Leeuwen 		.init = safexcel_cbcmac_init,
22087a627db9SPascal van Leeuwen 		.update = safexcel_ahash_update,
22097a627db9SPascal van Leeuwen 		.final = safexcel_ahash_final,
22107a627db9SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22117a627db9SPascal van Leeuwen 		.digest = safexcel_cbcmac_digest,
22127a627db9SPascal van Leeuwen 		.setkey = safexcel_cmac_setkey,
22137a627db9SPascal van Leeuwen 		.export = safexcel_ahash_export,
22147a627db9SPascal van Leeuwen 		.import = safexcel_ahash_import,
22157a627db9SPascal van Leeuwen 		.halg = {
22167a627db9SPascal van Leeuwen 			.digestsize = AES_BLOCK_SIZE,
22177a627db9SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
22187a627db9SPascal van Leeuwen 			.base = {
22197a627db9SPascal van Leeuwen 				.cra_name = "cmac(aes)",
22207a627db9SPascal van Leeuwen 				.cra_driver_name = "safexcel-cmac-aes",
22217a627db9SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
22227a627db9SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
22237a627db9SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
22247a627db9SPascal van Leeuwen 				.cra_blocksize = AES_BLOCK_SIZE,
22257a627db9SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
22267a627db9SPascal van Leeuwen 				.cra_init = safexcel_xcbcmac_cra_init,
22277a627db9SPascal van Leeuwen 				.cra_exit = safexcel_xcbcmac_cra_exit,
22287a627db9SPascal van Leeuwen 				.cra_module = THIS_MODULE,
22297a627db9SPascal van Leeuwen 			},
22307a627db9SPascal van Leeuwen 		},
22317a627db9SPascal van Leeuwen 	},
22327a627db9SPascal van Leeuwen };
22330f2bc131SPascal van Leeuwen 
22340f2bc131SPascal van Leeuwen static int safexcel_sm3_init(struct ahash_request *areq)
22350f2bc131SPascal van Leeuwen {
22360f2bc131SPascal van Leeuwen 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
22370f2bc131SPascal van Leeuwen 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
22380f2bc131SPascal van Leeuwen 
22390f2bc131SPascal van Leeuwen 	memset(req, 0, sizeof(*req));
22400f2bc131SPascal van Leeuwen 
22410f2bc131SPascal van Leeuwen 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
22420f2bc131SPascal van Leeuwen 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
22430f2bc131SPascal van Leeuwen 	req->state_sz = SM3_DIGEST_SIZE;
22440f2bc131SPascal van Leeuwen 	req->block_sz = SM3_BLOCK_SIZE;
22450f2bc131SPascal van Leeuwen 
22460f2bc131SPascal van Leeuwen 	return 0;
22470f2bc131SPascal van Leeuwen }
22480f2bc131SPascal van Leeuwen 
22490f2bc131SPascal van Leeuwen static int safexcel_sm3_digest(struct ahash_request *areq)
22500f2bc131SPascal van Leeuwen {
22510f2bc131SPascal van Leeuwen 	int ret = safexcel_sm3_init(areq);
22520f2bc131SPascal van Leeuwen 
22530f2bc131SPascal van Leeuwen 	if (ret)
22540f2bc131SPascal van Leeuwen 		return ret;
22550f2bc131SPascal van Leeuwen 
22560f2bc131SPascal van Leeuwen 	return safexcel_ahash_finup(areq);
22570f2bc131SPascal van Leeuwen }
22580f2bc131SPascal van Leeuwen 
22590f2bc131SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sm3 = {
22600f2bc131SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AHASH,
22610f2bc131SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM3,
22620f2bc131SPascal van Leeuwen 	.alg.ahash = {
22630f2bc131SPascal van Leeuwen 		.init = safexcel_sm3_init,
22640f2bc131SPascal van Leeuwen 		.update = safexcel_ahash_update,
22650f2bc131SPascal van Leeuwen 		.final = safexcel_ahash_final,
22660f2bc131SPascal van Leeuwen 		.finup = safexcel_ahash_finup,
22670f2bc131SPascal van Leeuwen 		.digest = safexcel_sm3_digest,
22680f2bc131SPascal van Leeuwen 		.export = safexcel_ahash_export,
22690f2bc131SPascal van Leeuwen 		.import = safexcel_ahash_import,
22700f2bc131SPascal van Leeuwen 		.halg = {
22710f2bc131SPascal van Leeuwen 			.digestsize = SM3_DIGEST_SIZE,
22720f2bc131SPascal van Leeuwen 			.statesize = sizeof(struct safexcel_ahash_export_state),
22730f2bc131SPascal van Leeuwen 			.base = {
22740f2bc131SPascal van Leeuwen 				.cra_name = "sm3",
22750f2bc131SPascal van Leeuwen 				.cra_driver_name = "safexcel-sm3",
22760f2bc131SPascal van Leeuwen 				.cra_priority = SAFEXCEL_CRA_PRIORITY,
22770f2bc131SPascal van Leeuwen 				.cra_flags = CRYPTO_ALG_ASYNC |
22780f2bc131SPascal van Leeuwen 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
22790f2bc131SPascal van Leeuwen 				.cra_blocksize = SM3_BLOCK_SIZE,
22800f2bc131SPascal van Leeuwen 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
22810f2bc131SPascal van Leeuwen 				.cra_init = safexcel_ahash_cra_init,
22820f2bc131SPascal van Leeuwen 				.cra_exit = safexcel_ahash_cra_exit,
22830f2bc131SPascal van Leeuwen 				.cra_module = THIS_MODULE,
22840f2bc131SPascal van Leeuwen 			},
22850f2bc131SPascal van Leeuwen 		},
22860f2bc131SPascal van Leeuwen 	},
22870f2bc131SPascal van Leeuwen };
2288