11b44c5a6SAntoine Ténart /*
21b44c5a6SAntoine Ténart  * Copyright (C) 2017 Marvell
31b44c5a6SAntoine Ténart  *
41b44c5a6SAntoine Ténart  * Antoine Tenart <antoine.tenart@free-electrons.com>
51b44c5a6SAntoine Ténart  *
61b44c5a6SAntoine Ténart  * This file is licensed under the terms of the GNU General Public
71b44c5a6SAntoine Ténart  * License version 2. This program is licensed "as is" without any
81b44c5a6SAntoine Ténart  * warranty of any kind, whether express or implied.
91b44c5a6SAntoine Ténart  */
101b44c5a6SAntoine Ténart 
11aed3731eSAntoine Ténart #include <crypto/hmac.h>
121b44c5a6SAntoine Ténart #include <crypto/sha.h>
131b44c5a6SAntoine Ténart #include <linux/device.h>
141b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
151b44c5a6SAntoine Ténart #include <linux/dmapool.h>
161b44c5a6SAntoine Ténart 
171b44c5a6SAntoine Ténart #include "safexcel.h"
181b44c5a6SAntoine Ténart 
191b44c5a6SAntoine Ténart struct safexcel_ahash_ctx {
201b44c5a6SAntoine Ténart 	struct safexcel_context base;
211b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
221b44c5a6SAntoine Ténart 
231b44c5a6SAntoine Ténart 	u32 alg;
241b44c5a6SAntoine Ténart 
2573f36ea7SAntoine Tenart 	u32 ipad[SHA256_DIGEST_SIZE / sizeof(u32)];
2673f36ea7SAntoine Tenart 	u32 opad[SHA256_DIGEST_SIZE / sizeof(u32)];
271b44c5a6SAntoine Ténart };
281b44c5a6SAntoine Ténart 
291b44c5a6SAntoine Ténart struct safexcel_ahash_req {
301b44c5a6SAntoine Ténart 	bool last_req;
311b44c5a6SAntoine Ténart 	bool finish;
321b44c5a6SAntoine Ténart 	bool hmac;
331eb7b403SOfer Heifetz 	bool needs_inv;
341b44c5a6SAntoine Ténart 
35c957f8b3SAntoine Ténart 	int nents;
36b8592027SOfer Heifetz 	dma_addr_t result_dma;
37c957f8b3SAntoine Ténart 
38b869648cSAntoine Tenart 	u32 digest;
39b869648cSAntoine Tenart 
401b44c5a6SAntoine Ténart 	u8 state_sz;    /* expected sate size, only set once */
412973633eSAntoine Ténart 	u32 state[SHA256_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32));
421b44c5a6SAntoine Ténart 
431b44c5a6SAntoine Ténart 	u64 len;
441b44c5a6SAntoine Ténart 	u64 processed;
451b44c5a6SAntoine Ténart 
461b44c5a6SAntoine Ténart 	u8 cache[SHA256_BLOCK_SIZE] __aligned(sizeof(u32));
47cff9a175SAntoine Tenart 	dma_addr_t cache_dma;
48cff9a175SAntoine Tenart 	unsigned int cache_sz;
49cff9a175SAntoine Tenart 
501b44c5a6SAntoine Ténart 	u8 cache_next[SHA256_BLOCK_SIZE] __aligned(sizeof(u32));
511b44c5a6SAntoine Ténart };
521b44c5a6SAntoine Ténart 
531b44c5a6SAntoine Ténart struct safexcel_ahash_export_state {
541b44c5a6SAntoine Ténart 	u64 len;
551b44c5a6SAntoine Ténart 	u64 processed;
561b44c5a6SAntoine Ténart 
57b869648cSAntoine Tenart 	u32 digest;
58b869648cSAntoine Tenart 
591b44c5a6SAntoine Ténart 	u32 state[SHA256_DIGEST_SIZE / sizeof(u32)];
601b44c5a6SAntoine Ténart 	u8 cache[SHA256_BLOCK_SIZE];
611b44c5a6SAntoine Ténart };
621b44c5a6SAntoine Ténart 
631b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc,
641b44c5a6SAntoine Ténart 				u32 input_length, u32 result_length)
651b44c5a6SAntoine Ténart {
661b44c5a6SAntoine Ténart 	struct safexcel_token *token =
671b44c5a6SAntoine Ténart 		(struct safexcel_token *)cdesc->control_data.token;
681b44c5a6SAntoine Ténart 
691b44c5a6SAntoine Ténart 	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
701b44c5a6SAntoine Ténart 	token[0].packet_length = input_length;
711b44c5a6SAntoine Ténart 	token[0].stat = EIP197_TOKEN_STAT_LAST_HASH;
721b44c5a6SAntoine Ténart 	token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH;
731b44c5a6SAntoine Ténart 
741b44c5a6SAntoine Ténart 	token[1].opcode = EIP197_TOKEN_OPCODE_INSERT;
751b44c5a6SAntoine Ténart 	token[1].packet_length = result_length;
761b44c5a6SAntoine Ténart 	token[1].stat = EIP197_TOKEN_STAT_LAST_HASH |
771b44c5a6SAntoine Ténart 			EIP197_TOKEN_STAT_LAST_PACKET;
781b44c5a6SAntoine Ténart 	token[1].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
791b44c5a6SAntoine Ténart 				EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
801b44c5a6SAntoine Ténart }
811b44c5a6SAntoine Ténart 
821b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx,
831b44c5a6SAntoine Ténart 				     struct safexcel_ahash_req *req,
841b44c5a6SAntoine Ténart 				     struct safexcel_command_desc *cdesc,
851b44c5a6SAntoine Ténart 				     unsigned int digestsize,
861b44c5a6SAntoine Ténart 				     unsigned int blocksize)
871b44c5a6SAntoine Ténart {
881b44c5a6SAntoine Ténart 	int i;
891b44c5a6SAntoine Ténart 
901b44c5a6SAntoine Ténart 	cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_HASH_OUT;
911b44c5a6SAntoine Ténart 	cdesc->control_data.control0 |= ctx->alg;
92b869648cSAntoine Tenart 	cdesc->control_data.control0 |= req->digest;
931b44c5a6SAntoine Ténart 
94b869648cSAntoine Tenart 	if (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) {
951b44c5a6SAntoine Ténart 		if (req->processed) {
961b44c5a6SAntoine Ténart 			if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1)
971b44c5a6SAntoine Ténart 				cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(6);
981b44c5a6SAntoine Ténart 			else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224 ||
991b44c5a6SAntoine Ténart 				 ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256)
1001b44c5a6SAntoine Ténart 				cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(9);
1011b44c5a6SAntoine Ténart 
1021b44c5a6SAntoine Ténart 			cdesc->control_data.control1 |= CONTEXT_CONTROL_DIGEST_CNT;
1031b44c5a6SAntoine Ténart 		} else {
1041b44c5a6SAntoine Ténart 			cdesc->control_data.control0 |= CONTEXT_CONTROL_RESTART_HASH;
1051b44c5a6SAntoine Ténart 		}
1061b44c5a6SAntoine Ténart 
1071b44c5a6SAntoine Ténart 		if (!req->finish)
1081b44c5a6SAntoine Ténart 			cdesc->control_data.control0 |= CONTEXT_CONTROL_NO_FINISH_HASH;
1091b44c5a6SAntoine Ténart 
1101b44c5a6SAntoine Ténart 		/*
1111b44c5a6SAntoine Ténart 		 * Copy the input digest if needed, and setup the context
1121b44c5a6SAntoine Ténart 		 * fields. Do this now as we need it to setup the first command
1131b44c5a6SAntoine Ténart 		 * descriptor.
1141b44c5a6SAntoine Ténart 		 */
1151b44c5a6SAntoine Ténart 		if (req->processed) {
1161b44c5a6SAntoine Ténart 			for (i = 0; i < digestsize / sizeof(u32); i++)
1171b44c5a6SAntoine Ténart 				ctx->base.ctxr->data[i] = cpu_to_le32(req->state[i]);
1181b44c5a6SAntoine Ténart 
1191b44c5a6SAntoine Ténart 			if (req->finish)
1201b44c5a6SAntoine Ténart 				ctx->base.ctxr->data[i] = cpu_to_le32(req->processed / blocksize);
1211b44c5a6SAntoine Ténart 		}
122b869648cSAntoine Tenart 	} else if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC) {
1234505bb02SAntoine Tenart 		cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(2 * req->state_sz / sizeof(u32));
1241b44c5a6SAntoine Ténart 
1254505bb02SAntoine Tenart 		memcpy(ctx->base.ctxr->data, ctx->ipad, req->state_sz);
1264505bb02SAntoine Tenart 		memcpy(ctx->base.ctxr->data + req->state_sz / sizeof(u32),
1274505bb02SAntoine Tenart 		       ctx->opad, req->state_sz);
1281b44c5a6SAntoine Ténart 	}
1291b44c5a6SAntoine Ténart }
1301b44c5a6SAntoine Ténart 
1311eb7b403SOfer Heifetz static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int ring,
1321b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
1331b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
1341b44c5a6SAntoine Ténart {
1351b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
1361b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
1371b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
1381b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *sreq = ahash_request_ctx(areq);
1392973633eSAntoine Ténart 	int cache_len;
1401b44c5a6SAntoine Ténart 
1411b44c5a6SAntoine Ténart 	*ret = 0;
1421b44c5a6SAntoine Ténart 
1431b44c5a6SAntoine Ténart 	spin_lock_bh(&priv->ring[ring].egress_lock);
1441b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
1451b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
1461b44c5a6SAntoine Ténart 		dev_err(priv->dev,
1471b44c5a6SAntoine Ténart 			"hash: result: could not retrieve the result descriptor\n");
1481b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
149bdfd1909SAntoine Tenart 	} else {
150bdfd1909SAntoine Tenart 		*ret = safexcel_rdesc_check_errors(priv, rdesc);
1511b44c5a6SAntoine Ténart 	}
1521b44c5a6SAntoine Ténart 
1531b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
1541b44c5a6SAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].egress_lock);
1551b44c5a6SAntoine Ténart 
156c957f8b3SAntoine Ténart 	if (sreq->nents) {
157c957f8b3SAntoine Ténart 		dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE);
158c957f8b3SAntoine Ténart 		sreq->nents = 0;
159c957f8b3SAntoine Ténart 	}
1601b44c5a6SAntoine Ténart 
161b8592027SOfer Heifetz 	if (sreq->result_dma) {
162b8592027SOfer Heifetz 		dma_unmap_single(priv->dev, sreq->result_dma, sreq->state_sz,
163b8592027SOfer Heifetz 				 DMA_FROM_DEVICE);
164b8592027SOfer Heifetz 		sreq->result_dma = 0;
165b8592027SOfer Heifetz 	}
166b8592027SOfer Heifetz 
167cff9a175SAntoine Tenart 	if (sreq->cache_dma) {
168cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz,
169cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
170cff9a175SAntoine Tenart 		sreq->cache_dma = 0;
171cff9a175SAntoine Tenart 	}
1721b44c5a6SAntoine Ténart 
173b89a8159SAntoine Tenart 	if (sreq->finish)
174b89a8159SAntoine Tenart 		memcpy(areq->result, sreq->state,
175b89a8159SAntoine Tenart 		       crypto_ahash_digestsize(ahash));
176b89a8159SAntoine Tenart 
1771b44c5a6SAntoine Ténart 	cache_len = sreq->len - sreq->processed;
1781b44c5a6SAntoine Ténart 	if (cache_len)
1791b44c5a6SAntoine Ténart 		memcpy(sreq->cache, sreq->cache_next, cache_len);
1801b44c5a6SAntoine Ténart 
1811b44c5a6SAntoine Ténart 	*should_complete = true;
1821b44c5a6SAntoine Ténart 
1831b44c5a6SAntoine Ténart 	return 1;
1841b44c5a6SAntoine Ténart }
1851b44c5a6SAntoine Ténart 
1861eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring,
1871eb7b403SOfer Heifetz 				   struct safexcel_request *request,
1881eb7b403SOfer Heifetz 				   int *commands, int *results)
1891b44c5a6SAntoine Ténart {
1901b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
1911b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
1921b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
1931b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
1941b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
1951b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc, *first_cdesc = NULL;
1961b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
1971b44c5a6SAntoine Ténart 	struct scatterlist *sg;
198c957f8b3SAntoine Ténart 	int i, queued, len, cache_len, extra, n_cdesc = 0, ret = 0;
1991b44c5a6SAntoine Ténart 
2001b44c5a6SAntoine Ténart 	queued = len = req->len - req->processed;
201666a9c70SAntoine Tenart 	if (queued <= crypto_ahash_blocksize(ahash))
2021b44c5a6SAntoine Ténart 		cache_len = queued;
2031b44c5a6SAntoine Ténart 	else
2041b44c5a6SAntoine Ténart 		cache_len = queued - areq->nbytes;
2051b44c5a6SAntoine Ténart 
206809778e0SAntoine Ténart 	if (!req->last_req) {
207809778e0SAntoine Ténart 		/* If this is not the last request and the queued data does not
208809778e0SAntoine Ténart 		 * fit into full blocks, cache it for the next send() call.
2091b44c5a6SAntoine Ténart 		 */
2101b44c5a6SAntoine Ténart 		extra = queued & (crypto_ahash_blocksize(ahash) - 1);
211809778e0SAntoine Ténart 		if (!extra)
212809778e0SAntoine Ténart 			/* If this is not the last request and the queued data
213809778e0SAntoine Ténart 			 * is a multiple of a block, cache the last one for now.
214809778e0SAntoine Ténart 			 */
215c1a8fa6eSAntoine Tenart 			extra = crypto_ahash_blocksize(ahash);
216809778e0SAntoine Ténart 
217809778e0SAntoine Ténart 		if (extra) {
2181b44c5a6SAntoine Ténart 			sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
219809778e0SAntoine Ténart 					   req->cache_next, extra,
220809778e0SAntoine Ténart 					   areq->nbytes - extra);
2211b44c5a6SAntoine Ténart 
2221b44c5a6SAntoine Ténart 			queued -= extra;
2231b44c5a6SAntoine Ténart 			len -= extra;
224809778e0SAntoine Ténart 
225809778e0SAntoine Ténart 			if (!queued) {
226809778e0SAntoine Ténart 				*commands = 0;
227809778e0SAntoine Ténart 				*results = 0;
228809778e0SAntoine Ténart 				return 0;
229809778e0SAntoine Ténart 			}
230809778e0SAntoine Ténart 		}
2311b44c5a6SAntoine Ténart 	}
2321b44c5a6SAntoine Ténart 
2331b44c5a6SAntoine Ténart 	spin_lock_bh(&priv->ring[ring].egress_lock);
2341b44c5a6SAntoine Ténart 
2351b44c5a6SAntoine Ténart 	/* Add a command descriptor for the cached data, if any */
2361b44c5a6SAntoine Ténart 	if (cache_len) {
237cff9a175SAntoine Tenart 		req->cache_dma = dma_map_single(priv->dev, req->cache,
2381b44c5a6SAntoine Ténart 						cache_len, DMA_TO_DEVICE);
239efa94457Sweiyongjun \(A\) 		if (dma_mapping_error(priv->dev, req->cache_dma)) {
240efa94457Sweiyongjun \(A\) 			spin_unlock_bh(&priv->ring[ring].egress_lock);
241cff9a175SAntoine Tenart 			return -EINVAL;
242efa94457Sweiyongjun \(A\) 		}
2431b44c5a6SAntoine Ténart 
244cff9a175SAntoine Tenart 		req->cache_sz = cache_len;
2451b44c5a6SAntoine Ténart 		first_cdesc = safexcel_add_cdesc(priv, ring, 1,
2461b44c5a6SAntoine Ténart 						 (cache_len == len),
247cff9a175SAntoine Tenart 						 req->cache_dma, cache_len, len,
2481b44c5a6SAntoine Ténart 						 ctx->base.ctxr_dma);
2491b44c5a6SAntoine Ténart 		if (IS_ERR(first_cdesc)) {
2501b44c5a6SAntoine Ténart 			ret = PTR_ERR(first_cdesc);
2511b44c5a6SAntoine Ténart 			goto unmap_cache;
2521b44c5a6SAntoine Ténart 		}
2531b44c5a6SAntoine Ténart 		n_cdesc++;
2541b44c5a6SAntoine Ténart 
2551b44c5a6SAntoine Ténart 		queued -= cache_len;
2561b44c5a6SAntoine Ténart 		if (!queued)
2571b44c5a6SAntoine Ténart 			goto send_command;
2581b44c5a6SAntoine Ténart 	}
2591b44c5a6SAntoine Ténart 
2601b44c5a6SAntoine Ténart 	/* Now handle the current ahash request buffer(s) */
261c957f8b3SAntoine Ténart 	req->nents = dma_map_sg(priv->dev, areq->src,
2621b44c5a6SAntoine Ténart 				sg_nents_for_len(areq->src, areq->nbytes),
2631b44c5a6SAntoine Ténart 				DMA_TO_DEVICE);
264c957f8b3SAntoine Ténart 	if (!req->nents) {
2651b44c5a6SAntoine Ténart 		ret = -ENOMEM;
2661b44c5a6SAntoine Ténart 		goto cdesc_rollback;
2671b44c5a6SAntoine Ténart 	}
2681b44c5a6SAntoine Ténart 
269c957f8b3SAntoine Ténart 	for_each_sg(areq->src, sg, req->nents, i) {
2701b44c5a6SAntoine Ténart 		int sglen = sg_dma_len(sg);
2711b44c5a6SAntoine Ténart 
2721b44c5a6SAntoine Ténart 		/* Do not overflow the request */
2731b44c5a6SAntoine Ténart 		if (queued - sglen < 0)
2741b44c5a6SAntoine Ténart 			sglen = queued;
2751b44c5a6SAntoine Ténart 
2761b44c5a6SAntoine Ténart 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
2771b44c5a6SAntoine Ténart 					   !(queued - sglen), sg_dma_address(sg),
2781b44c5a6SAntoine Ténart 					   sglen, len, ctx->base.ctxr_dma);
2791b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
2801b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
28157433b58SAntoine Tenart 			goto unmap_sg;
2821b44c5a6SAntoine Ténart 		}
2831b44c5a6SAntoine Ténart 		n_cdesc++;
2841b44c5a6SAntoine Ténart 
2851b44c5a6SAntoine Ténart 		if (n_cdesc == 1)
2861b44c5a6SAntoine Ténart 			first_cdesc = cdesc;
2871b44c5a6SAntoine Ténart 
2881b44c5a6SAntoine Ténart 		queued -= sglen;
2891b44c5a6SAntoine Ténart 		if (!queued)
2901b44c5a6SAntoine Ténart 			break;
2911b44c5a6SAntoine Ténart 	}
2921b44c5a6SAntoine Ténart 
2931b44c5a6SAntoine Ténart send_command:
2941b44c5a6SAntoine Ténart 	/* Setup the context options */
2951b44c5a6SAntoine Ténart 	safexcel_context_control(ctx, req, first_cdesc, req->state_sz,
2961b44c5a6SAntoine Ténart 				 crypto_ahash_blocksize(ahash));
2971b44c5a6SAntoine Ténart 
2981b44c5a6SAntoine Ténart 	/* Add the token */
2991b44c5a6SAntoine Ténart 	safexcel_hash_token(first_cdesc, len, req->state_sz);
3001b44c5a6SAntoine Ténart 
301b8592027SOfer Heifetz 	req->result_dma = dma_map_single(priv->dev, req->state, req->state_sz,
302b8592027SOfer Heifetz 					 DMA_FROM_DEVICE);
303b8592027SOfer Heifetz 	if (dma_mapping_error(priv->dev, req->result_dma)) {
3041b44c5a6SAntoine Ténart 		ret = -EINVAL;
30557433b58SAntoine Tenart 		goto unmap_sg;
3061b44c5a6SAntoine Ténart 	}
3071b44c5a6SAntoine Ténart 
3081b44c5a6SAntoine Ténart 	/* Add a result descriptor */
309b8592027SOfer Heifetz 	rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma,
3101b44c5a6SAntoine Ténart 				   req->state_sz);
3111b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
3121b44c5a6SAntoine Ténart 		ret = PTR_ERR(rdesc);
31357240a78SAntoine Tenart 		goto unmap_result;
3141b44c5a6SAntoine Ténart 	}
3151b44c5a6SAntoine Ténart 
3161b44c5a6SAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].egress_lock);
3171b44c5a6SAntoine Ténart 
31897858434SAntoine Ténart 	req->processed += len;
31997858434SAntoine Ténart 	request->req = &areq->base;
32097858434SAntoine Ténart 
3211b44c5a6SAntoine Ténart 	*commands = n_cdesc;
3221b44c5a6SAntoine Ténart 	*results = 1;
3231b44c5a6SAntoine Ténart 	return 0;
3241b44c5a6SAntoine Ténart 
32557240a78SAntoine Tenart unmap_result:
32657433b58SAntoine Tenart 	dma_unmap_single(priv->dev, req->result_dma, req->state_sz,
32757433b58SAntoine Tenart 			 DMA_FROM_DEVICE);
32857433b58SAntoine Tenart unmap_sg:
32957240a78SAntoine Tenart 	dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE);
3301b44c5a6SAntoine Ténart cdesc_rollback:
3311b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
3321b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
3331b44c5a6SAntoine Ténart unmap_cache:
334cff9a175SAntoine Tenart 	if (req->cache_dma) {
335cff9a175SAntoine Tenart 		dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz,
336cff9a175SAntoine Tenart 				 DMA_TO_DEVICE);
337cff9a175SAntoine Tenart 		req->cache_sz = 0;
3381b44c5a6SAntoine Ténart 	}
3391b44c5a6SAntoine Ténart 
3401b44c5a6SAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].egress_lock);
3411b44c5a6SAntoine Ténart 	return ret;
3421b44c5a6SAntoine Ténart }
3431b44c5a6SAntoine Ténart 
3441b44c5a6SAntoine Ténart static inline bool safexcel_ahash_needs_inv_get(struct ahash_request *areq)
3451b44c5a6SAntoine Ténart {
3461b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
3471b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
3481b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
3491b44c5a6SAntoine Ténart 	unsigned int state_w_sz = req->state_sz / sizeof(u32);
3501b44c5a6SAntoine Ténart 	int i;
3511b44c5a6SAntoine Ténart 
3521b44c5a6SAntoine Ténart 	for (i = 0; i < state_w_sz; i++)
3531b44c5a6SAntoine Ténart 		if (ctx->base.ctxr->data[i] != cpu_to_le32(req->state[i]))
3541b44c5a6SAntoine Ténart 			return true;
3551b44c5a6SAntoine Ténart 
3561b44c5a6SAntoine Ténart 	if (ctx->base.ctxr->data[state_w_sz] !=
3571b44c5a6SAntoine Ténart 	    cpu_to_le32(req->processed / crypto_ahash_blocksize(ahash)))
3581b44c5a6SAntoine Ténart 		return true;
3591b44c5a6SAntoine Ténart 
3601b44c5a6SAntoine Ténart 	return false;
3611b44c5a6SAntoine Ténart }
3621b44c5a6SAntoine Ténart 
3631b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
3641b44c5a6SAntoine Ténart 				      int ring,
3651b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
3661b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
3671b44c5a6SAntoine Ténart {
3681b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
3691b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
3701b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
3711b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
3721b44c5a6SAntoine Ténart 	int enq_ret;
3731b44c5a6SAntoine Ténart 
3741b44c5a6SAntoine Ténart 	*ret = 0;
3751b44c5a6SAntoine Ténart 
3761b44c5a6SAntoine Ténart 	spin_lock_bh(&priv->ring[ring].egress_lock);
3771b44c5a6SAntoine Ténart 	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
3781b44c5a6SAntoine Ténart 	if (IS_ERR(rdesc)) {
3791b44c5a6SAntoine Ténart 		dev_err(priv->dev,
3801b44c5a6SAntoine Ténart 			"hash: invalidate: could not retrieve the result descriptor\n");
3811b44c5a6SAntoine Ténart 		*ret = PTR_ERR(rdesc);
3821b44c5a6SAntoine Ténart 	} else if (rdesc->result_data.error_code) {
3831b44c5a6SAntoine Ténart 		dev_err(priv->dev,
3841b44c5a6SAntoine Ténart 			"hash: invalidate: result descriptor error (%d)\n",
3851b44c5a6SAntoine Ténart 			rdesc->result_data.error_code);
3861b44c5a6SAntoine Ténart 		*ret = -EINVAL;
3871b44c5a6SAntoine Ténart 	}
3881b44c5a6SAntoine Ténart 
3891b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
3901b44c5a6SAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].egress_lock);
3911b44c5a6SAntoine Ténart 
3921b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
3931b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
3941b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
3951b44c5a6SAntoine Ténart 
3961b44c5a6SAntoine Ténart 		*should_complete = true;
3971b44c5a6SAntoine Ténart 		return 1;
3981b44c5a6SAntoine Ténart 	}
3991b44c5a6SAntoine Ténart 
40086671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
40186671abbSAntoine Ténart 	ctx->base.ring = ring;
4021b44c5a6SAntoine Ténart 
40386671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
40486671abbSAntoine Ténart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async);
40586671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
4061b44c5a6SAntoine Ténart 
4071b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
4081b44c5a6SAntoine Ténart 		*ret = enq_ret;
4091b44c5a6SAntoine Ténart 
4108472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
4118472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
41286671abbSAntoine Ténart 
4131b44c5a6SAntoine Ténart 	*should_complete = false;
4141b44c5a6SAntoine Ténart 
4151b44c5a6SAntoine Ténart 	return 1;
4161b44c5a6SAntoine Ténart }
4171b44c5a6SAntoine Ténart 
4181eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring,
4191eb7b403SOfer Heifetz 				  struct crypto_async_request *async,
4201eb7b403SOfer Heifetz 				  bool *should_complete, int *ret)
4211eb7b403SOfer Heifetz {
4221eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
4231eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
4241eb7b403SOfer Heifetz 	int err;
4251eb7b403SOfer Heifetz 
426871df319SAntoine Ténart 	BUG_ON(priv->version == EIP97 && req->needs_inv);
427871df319SAntoine Ténart 
4281eb7b403SOfer Heifetz 	if (req->needs_inv) {
4291eb7b403SOfer Heifetz 		req->needs_inv = false;
4301eb7b403SOfer Heifetz 		err = safexcel_handle_inv_result(priv, ring, async,
4311eb7b403SOfer Heifetz 						 should_complete, ret);
4321eb7b403SOfer Heifetz 	} else {
4331eb7b403SOfer Heifetz 		err = safexcel_handle_req_result(priv, ring, async,
4341eb7b403SOfer Heifetz 						 should_complete, ret);
4351eb7b403SOfer Heifetz 	}
4361eb7b403SOfer Heifetz 
4371eb7b403SOfer Heifetz 	return err;
4381eb7b403SOfer Heifetz }
4391eb7b403SOfer Heifetz 
4401b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async,
4411b44c5a6SAntoine Ténart 				   int ring, struct safexcel_request *request,
4421b44c5a6SAntoine Ténart 				   int *commands, int *results)
4431b44c5a6SAntoine Ténart {
4441b44c5a6SAntoine Ténart 	struct ahash_request *areq = ahash_request_cast(async);
4451b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
4461b44c5a6SAntoine Ténart 	int ret;
4471b44c5a6SAntoine Ténart 
4485290ad6eSOfer Heifetz 	ret = safexcel_invalidate_cache(async, ctx->priv,
4491b44c5a6SAntoine Ténart 					ctx->base.ctxr_dma, ring, request);
4501b44c5a6SAntoine Ténart 	if (unlikely(ret))
4511b44c5a6SAntoine Ténart 		return ret;
4521b44c5a6SAntoine Ténart 
4531b44c5a6SAntoine Ténart 	*commands = 1;
4541b44c5a6SAntoine Ténart 	*results = 1;
4551b44c5a6SAntoine Ténart 
4561b44c5a6SAntoine Ténart 	return 0;
4571b44c5a6SAntoine Ténart }
4581b44c5a6SAntoine Ténart 
4591eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async,
4601eb7b403SOfer Heifetz 			       int ring, struct safexcel_request *request,
4611eb7b403SOfer Heifetz 			       int *commands, int *results)
4621eb7b403SOfer Heifetz {
4631eb7b403SOfer Heifetz 	struct ahash_request *areq = ahash_request_cast(async);
4641eb7b403SOfer Heifetz 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
4651eb7b403SOfer Heifetz 	int ret;
4661eb7b403SOfer Heifetz 
4671eb7b403SOfer Heifetz 	if (req->needs_inv)
4681eb7b403SOfer Heifetz 		ret = safexcel_ahash_send_inv(async, ring, request,
4691eb7b403SOfer Heifetz 					      commands, results);
4701eb7b403SOfer Heifetz 	else
4711eb7b403SOfer Heifetz 		ret = safexcel_ahash_send_req(async, ring, request,
4721eb7b403SOfer Heifetz 					      commands, results);
4731eb7b403SOfer Heifetz 	return ret;
4741eb7b403SOfer Heifetz }
4751eb7b403SOfer Heifetz 
4761b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm)
4771b44c5a6SAntoine Ténart {
4781b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
4791b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
48061824806SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE);
4817cad2fabSAntoine Ténart 	struct safexcel_ahash_req *rctx = ahash_request_ctx(req);
4823e1166b9SArnd Bergmann 	struct safexcel_inv_result result = {};
48386671abbSAntoine Ténart 	int ring = ctx->base.ring;
4841b44c5a6SAntoine Ténart 
4857cad2fabSAntoine Ténart 	memset(req, 0, sizeof(struct ahash_request));
4861b44c5a6SAntoine Ténart 
4871b44c5a6SAntoine Ténart 	/* create invalidation request */
4881b44c5a6SAntoine Ténart 	init_completion(&result.completion);
4897cad2fabSAntoine Ténart 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
4901b44c5a6SAntoine Ténart 				   safexcel_inv_complete, &result);
4911b44c5a6SAntoine Ténart 
4927cad2fabSAntoine Ténart 	ahash_request_set_tfm(req, __crypto_ahash_cast(tfm));
4937cad2fabSAntoine Ténart 	ctx = crypto_tfm_ctx(req->base.tfm);
4941b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
4951eb7b403SOfer Heifetz 	rctx->needs_inv = true;
4961b44c5a6SAntoine Ténart 
49786671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
4987cad2fabSAntoine Ténart 	crypto_enqueue_request(&priv->ring[ring].queue, &req->base);
49986671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
5001b44c5a6SAntoine Ténart 
5018472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
5028472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
5031b44c5a6SAntoine Ténart 
504b7007dbcSAntoine Tenart 	wait_for_completion(&result.completion);
5051b44c5a6SAntoine Ténart 
5061b44c5a6SAntoine Ténart 	if (result.error) {
5071b44c5a6SAntoine Ténart 		dev_warn(priv->dev, "hash: completion error (%d)\n",
5081b44c5a6SAntoine Ténart 			 result.error);
5091b44c5a6SAntoine Ténart 		return result.error;
5101b44c5a6SAntoine Ténart 	}
5111b44c5a6SAntoine Ténart 
5121b44c5a6SAntoine Ténart 	return 0;
5131b44c5a6SAntoine Ténart }
5141b44c5a6SAntoine Ténart 
515cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to
516cc75f5ceSAntoine Ténart  * the engine, aka. when there is at least 1 block size in the pipe.
517cc75f5ceSAntoine Ténart  */
5181b44c5a6SAntoine Ténart static int safexcel_ahash_cache(struct ahash_request *areq)
5191b44c5a6SAntoine Ténart {
5201b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5211b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
5221b44c5a6SAntoine Ténart 	int queued, cache_len;
5231b44c5a6SAntoine Ténart 
524cc75f5ceSAntoine Ténart 	/* cache_len: everyting accepted by the driver but not sent yet,
525cc75f5ceSAntoine Ténart 	 * tot sz handled by update() - last req sz - tot sz handled by send()
526cc75f5ceSAntoine Ténart 	 */
5271b44c5a6SAntoine Ténart 	cache_len = req->len - areq->nbytes - req->processed;
528cc75f5ceSAntoine Ténart 	/* queued: everything accepted by the driver which will be handled by
529cc75f5ceSAntoine Ténart 	 * the next send() calls.
530cc75f5ceSAntoine Ténart 	 * tot sz handled by update() - tot sz handled by send()
531cc75f5ceSAntoine Ténart 	 */
5321b44c5a6SAntoine Ténart 	queued = req->len - req->processed;
5331b44c5a6SAntoine Ténart 
5341b44c5a6SAntoine Ténart 	/*
5351b44c5a6SAntoine Ténart 	 * In case there isn't enough bytes to proceed (less than a
5361b44c5a6SAntoine Ténart 	 * block size), cache the data until we have enough.
5371b44c5a6SAntoine Ténart 	 */
5381b44c5a6SAntoine Ténart 	if (cache_len + areq->nbytes <= crypto_ahash_blocksize(ahash)) {
5391b44c5a6SAntoine Ténart 		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
5401b44c5a6SAntoine Ténart 				   req->cache + cache_len,
5411b44c5a6SAntoine Ténart 				   areq->nbytes, 0);
5421b44c5a6SAntoine Ténart 		return areq->nbytes;
5431b44c5a6SAntoine Ténart 	}
5441b44c5a6SAntoine Ténart 
545dfbcc08fSAntoine Ténart 	/* We couldn't cache all the data */
5461b44c5a6SAntoine Ténart 	return -E2BIG;
5471b44c5a6SAntoine Ténart }
5481b44c5a6SAntoine Ténart 
5491b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq)
5501b44c5a6SAntoine Ténart {
5511b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
5521b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5531b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
55486671abbSAntoine Ténart 	int ret, ring;
5551b44c5a6SAntoine Ténart 
5561eb7b403SOfer Heifetz 	req->needs_inv = false;
5571b44c5a6SAntoine Ténart 
558c4daf4ccSOfer Heifetz 	if (ctx->base.ctxr) {
559871df319SAntoine Ténart 		if (priv->version == EIP197 &&
560871df319SAntoine Ténart 		    !ctx->base.needs_inv && req->processed &&
561b869648cSAntoine Tenart 		    req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED)
562c4daf4ccSOfer Heifetz 			/* We're still setting needs_inv here, even though it is
563c4daf4ccSOfer Heifetz 			 * cleared right away, because the needs_inv flag can be
564c4daf4ccSOfer Heifetz 			 * set in other functions and we want to keep the same
565c4daf4ccSOfer Heifetz 			 * logic.
566c4daf4ccSOfer Heifetz 			 */
5671b44c5a6SAntoine Ténart 			ctx->base.needs_inv = safexcel_ahash_needs_inv_get(areq);
5681b44c5a6SAntoine Ténart 
5691eb7b403SOfer Heifetz 		if (ctx->base.needs_inv) {
5701eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
5711eb7b403SOfer Heifetz 			req->needs_inv = true;
5721eb7b403SOfer Heifetz 		}
5731b44c5a6SAntoine Ténart 	} else {
5741b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
5751b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
5761b44c5a6SAntoine Ténart 						 EIP197_GFP_FLAGS(areq->base),
5771b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
5781b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
5791b44c5a6SAntoine Ténart 			return -ENOMEM;
5801b44c5a6SAntoine Ténart 	}
5811b44c5a6SAntoine Ténart 
58286671abbSAntoine Ténart 	ring = ctx->base.ring;
5831b44c5a6SAntoine Ténart 
58486671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
58586671abbSAntoine Ténart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base);
58686671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
58786671abbSAntoine Ténart 
5888472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
5898472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
5901b44c5a6SAntoine Ténart 
5911b44c5a6SAntoine Ténart 	return ret;
5921b44c5a6SAntoine Ténart }
5931b44c5a6SAntoine Ténart 
5941b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq)
5951b44c5a6SAntoine Ténart {
5961b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
5971b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
5981b44c5a6SAntoine Ténart 
5991b44c5a6SAntoine Ténart 	/* If the request is 0 length, do nothing */
6001b44c5a6SAntoine Ténart 	if (!areq->nbytes)
6011b44c5a6SAntoine Ténart 		return 0;
6021b44c5a6SAntoine Ténart 
6031b44c5a6SAntoine Ténart 	req->len += areq->nbytes;
6041b44c5a6SAntoine Ténart 
6051b44c5a6SAntoine Ténart 	safexcel_ahash_cache(areq);
6061b44c5a6SAntoine Ténart 
6071b44c5a6SAntoine Ténart 	/*
6081b44c5a6SAntoine Ténart 	 * We're not doing partial updates when performing an hmac request.
6091b44c5a6SAntoine Ténart 	 * Everything will be handled by the final() call.
6101b44c5a6SAntoine Ténart 	 */
611b869648cSAntoine Tenart 	if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC)
6121b44c5a6SAntoine Ténart 		return 0;
6131b44c5a6SAntoine Ténart 
6141b44c5a6SAntoine Ténart 	if (req->hmac)
6151b44c5a6SAntoine Ténart 		return safexcel_ahash_enqueue(areq);
6161b44c5a6SAntoine Ténart 
6171b44c5a6SAntoine Ténart 	if (!req->last_req &&
6181b44c5a6SAntoine Ténart 	    req->len - req->processed > crypto_ahash_blocksize(ahash))
6191b44c5a6SAntoine Ténart 		return safexcel_ahash_enqueue(areq);
6201b44c5a6SAntoine Ténart 
6211b44c5a6SAntoine Ténart 	return 0;
6221b44c5a6SAntoine Ténart }
6231b44c5a6SAntoine Ténart 
6241b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq)
6251b44c5a6SAntoine Ténart {
6261b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6271b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
6281b44c5a6SAntoine Ténart 
6291b44c5a6SAntoine Ténart 	req->last_req = true;
6301b44c5a6SAntoine Ténart 	req->finish = true;
6311b44c5a6SAntoine Ténart 
6321b44c5a6SAntoine Ténart 	/* If we have an overall 0 length request */
6331b44c5a6SAntoine Ténart 	if (!(req->len + areq->nbytes)) {
6341b44c5a6SAntoine Ténart 		if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1)
6351b44c5a6SAntoine Ténart 			memcpy(areq->result, sha1_zero_message_hash,
6361b44c5a6SAntoine Ténart 			       SHA1_DIGEST_SIZE);
6371b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224)
6381b44c5a6SAntoine Ténart 			memcpy(areq->result, sha224_zero_message_hash,
6391b44c5a6SAntoine Ténart 			       SHA224_DIGEST_SIZE);
6401b44c5a6SAntoine Ténart 		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256)
6411b44c5a6SAntoine Ténart 			memcpy(areq->result, sha256_zero_message_hash,
6421b44c5a6SAntoine Ténart 			       SHA256_DIGEST_SIZE);
6431b44c5a6SAntoine Ténart 
6441b44c5a6SAntoine Ténart 		return 0;
6451b44c5a6SAntoine Ténart 	}
6461b44c5a6SAntoine Ténart 
6471b44c5a6SAntoine Ténart 	return safexcel_ahash_enqueue(areq);
6481b44c5a6SAntoine Ténart }
6491b44c5a6SAntoine Ténart 
6501b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq)
6511b44c5a6SAntoine Ténart {
6521b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6531b44c5a6SAntoine Ténart 
6541b44c5a6SAntoine Ténart 	req->last_req = true;
6551b44c5a6SAntoine Ténart 	req->finish = true;
6561b44c5a6SAntoine Ténart 
6571b44c5a6SAntoine Ténart 	safexcel_ahash_update(areq);
6581b44c5a6SAntoine Ténart 	return safexcel_ahash_final(areq);
6591b44c5a6SAntoine Ténart }
6601b44c5a6SAntoine Ténart 
6611b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out)
6621b44c5a6SAntoine Ténart {
6631b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
6641b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6651b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state *export = out;
6661b44c5a6SAntoine Ténart 
6671b44c5a6SAntoine Ténart 	export->len = req->len;
6681b44c5a6SAntoine Ténart 	export->processed = req->processed;
6691b44c5a6SAntoine Ténart 
670b869648cSAntoine Tenart 	export->digest = req->digest;
671b869648cSAntoine Tenart 
6721b44c5a6SAntoine Ténart 	memcpy(export->state, req->state, req->state_sz);
6731b44c5a6SAntoine Ténart 	memcpy(export->cache, req->cache, crypto_ahash_blocksize(ahash));
6741b44c5a6SAntoine Ténart 
6751b44c5a6SAntoine Ténart 	return 0;
6761b44c5a6SAntoine Ténart }
6771b44c5a6SAntoine Ténart 
6781b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in)
6791b44c5a6SAntoine Ténart {
6801b44c5a6SAntoine Ténart 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
6811b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
6821b44c5a6SAntoine Ténart 	const struct safexcel_ahash_export_state *export = in;
6831b44c5a6SAntoine Ténart 	int ret;
6841b44c5a6SAntoine Ténart 
6851b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
6861b44c5a6SAntoine Ténart 	if (ret)
6871b44c5a6SAntoine Ténart 		return ret;
6881b44c5a6SAntoine Ténart 
6891b44c5a6SAntoine Ténart 	req->len = export->len;
6901b44c5a6SAntoine Ténart 	req->processed = export->processed;
6911b44c5a6SAntoine Ténart 
692b869648cSAntoine Tenart 	req->digest = export->digest;
693b869648cSAntoine Tenart 
6941b44c5a6SAntoine Ténart 	memcpy(req->cache, export->cache, crypto_ahash_blocksize(ahash));
6951b44c5a6SAntoine Ténart 	memcpy(req->state, export->state, req->state_sz);
6961b44c5a6SAntoine Ténart 
6971b44c5a6SAntoine Ténart 	return 0;
6981b44c5a6SAntoine Ténart }
6991b44c5a6SAntoine Ténart 
7001b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm)
7011b44c5a6SAntoine Ténart {
7021b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
7031b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
7041b44c5a6SAntoine Ténart 		container_of(__crypto_ahash_alg(tfm->__crt_alg),
7051b44c5a6SAntoine Ténart 			     struct safexcel_alg_template, alg.ahash);
7061b44c5a6SAntoine Ténart 
7071b44c5a6SAntoine Ténart 	ctx->priv = tmpl->priv;
7081eb7b403SOfer Heifetz 	ctx->base.send = safexcel_ahash_send;
7091eb7b403SOfer Heifetz 	ctx->base.handle_result = safexcel_handle_result;
7101b44c5a6SAntoine Ténart 
7111b44c5a6SAntoine Ténart 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
7121b44c5a6SAntoine Ténart 				 sizeof(struct safexcel_ahash_req));
7131b44c5a6SAntoine Ténart 	return 0;
7141b44c5a6SAntoine Ténart }
7151b44c5a6SAntoine Ténart 
7161b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq)
7171b44c5a6SAntoine Ténart {
7181b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
7191b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
7201b44c5a6SAntoine Ténart 
7211b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
7221b44c5a6SAntoine Ténart 
7231b44c5a6SAntoine Ténart 	req->state[0] = SHA1_H0;
7241b44c5a6SAntoine Ténart 	req->state[1] = SHA1_H1;
7251b44c5a6SAntoine Ténart 	req->state[2] = SHA1_H2;
7261b44c5a6SAntoine Ténart 	req->state[3] = SHA1_H3;
7271b44c5a6SAntoine Ténart 	req->state[4] = SHA1_H4;
7281b44c5a6SAntoine Ténart 
7291b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
730b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
7311b44c5a6SAntoine Ténart 	req->state_sz = SHA1_DIGEST_SIZE;
7321b44c5a6SAntoine Ténart 
7331b44c5a6SAntoine Ténart 	return 0;
7341b44c5a6SAntoine Ténart }
7351b44c5a6SAntoine Ténart 
7361b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq)
7371b44c5a6SAntoine Ténart {
7381b44c5a6SAntoine Ténart 	int ret = safexcel_sha1_init(areq);
7391b44c5a6SAntoine Ténart 
7401b44c5a6SAntoine Ténart 	if (ret)
7411b44c5a6SAntoine Ténart 		return ret;
7421b44c5a6SAntoine Ténart 
7431b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
7441b44c5a6SAntoine Ténart }
7451b44c5a6SAntoine Ténart 
7461b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm)
7471b44c5a6SAntoine Ténart {
7481b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
7491b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
7501b44c5a6SAntoine Ténart 	int ret;
7511b44c5a6SAntoine Ténart 
7521b44c5a6SAntoine Ténart 	/* context not allocated, skip invalidation */
7531b44c5a6SAntoine Ténart 	if (!ctx->base.ctxr)
7541b44c5a6SAntoine Ténart 		return;
7551b44c5a6SAntoine Ténart 
756871df319SAntoine Ténart 	if (priv->version == EIP197) {
7571b44c5a6SAntoine Ténart 		ret = safexcel_ahash_exit_inv(tfm);
7581b44c5a6SAntoine Ténart 		if (ret)
7591b44c5a6SAntoine Ténart 			dev_warn(priv->dev, "hash: invalidation error %d\n", ret);
760871df319SAntoine Ténart 	} else {
761871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
762871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
763871df319SAntoine Ténart 	}
7641b44c5a6SAntoine Ténart }
7651b44c5a6SAntoine Ténart 
7661b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = {
7671b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
7681b44c5a6SAntoine Ténart 	.alg.ahash = {
7691b44c5a6SAntoine Ténart 		.init = safexcel_sha1_init,
7701b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
7711b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
7721b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
7731b44c5a6SAntoine Ténart 		.digest = safexcel_sha1_digest,
7741b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
7751b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
7761b44c5a6SAntoine Ténart 		.halg = {
7771b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
7781b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
7791b44c5a6SAntoine Ténart 			.base = {
7801b44c5a6SAntoine Ténart 				.cra_name = "sha1",
7811b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha1",
7821b44c5a6SAntoine Ténart 				.cra_priority = 300,
7831b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
7841b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
7851b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
7861b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
7871b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
7881b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
7891b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
7901b44c5a6SAntoine Ténart 			},
7911b44c5a6SAntoine Ténart 		},
7921b44c5a6SAntoine Ténart 	},
7931b44c5a6SAntoine Ténart };
7941b44c5a6SAntoine Ténart 
7951b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq)
7961b44c5a6SAntoine Ténart {
797b869648cSAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
7981b44c5a6SAntoine Ténart 
7991b44c5a6SAntoine Ténart 	safexcel_sha1_init(areq);
800b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
8011b44c5a6SAntoine Ténart 	return 0;
8021b44c5a6SAntoine Ténart }
8031b44c5a6SAntoine Ténart 
8041b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq)
8051b44c5a6SAntoine Ténart {
8061b44c5a6SAntoine Ténart 	int ret = safexcel_hmac_sha1_init(areq);
8071b44c5a6SAntoine Ténart 
8081b44c5a6SAntoine Ténart 	if (ret)
8091b44c5a6SAntoine Ténart 		return ret;
8101b44c5a6SAntoine Ténart 
8111b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
8121b44c5a6SAntoine Ténart }
8131b44c5a6SAntoine Ténart 
8141b44c5a6SAntoine Ténart struct safexcel_ahash_result {
8151b44c5a6SAntoine Ténart 	struct completion completion;
8161b44c5a6SAntoine Ténart 	int error;
8171b44c5a6SAntoine Ténart };
8181b44c5a6SAntoine Ténart 
8191b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error)
8201b44c5a6SAntoine Ténart {
8211b44c5a6SAntoine Ténart 	struct safexcel_ahash_result *result = req->data;
8221b44c5a6SAntoine Ténart 
8231b44c5a6SAntoine Ténart 	if (error == -EINPROGRESS)
8241b44c5a6SAntoine Ténart 		return;
8251b44c5a6SAntoine Ténart 
8261b44c5a6SAntoine Ténart 	result->error = error;
8271b44c5a6SAntoine Ténart 	complete(&result->completion);
8281b44c5a6SAntoine Ténart }
8291b44c5a6SAntoine Ténart 
8301b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq,
8311b44c5a6SAntoine Ténart 				  unsigned int blocksize, const u8 *key,
8321b44c5a6SAntoine Ténart 				  unsigned int keylen, u8 *ipad, u8 *opad)
8331b44c5a6SAntoine Ténart {
8341b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
8351b44c5a6SAntoine Ténart 	struct scatterlist sg;
8361b44c5a6SAntoine Ténart 	int ret, i;
8371b44c5a6SAntoine Ténart 	u8 *keydup;
8381b44c5a6SAntoine Ténart 
8391b44c5a6SAntoine Ténart 	if (keylen <= blocksize) {
8401b44c5a6SAntoine Ténart 		memcpy(ipad, key, keylen);
8411b44c5a6SAntoine Ténart 	} else {
8421b44c5a6SAntoine Ténart 		keydup = kmemdup(key, keylen, GFP_KERNEL);
8431b44c5a6SAntoine Ténart 		if (!keydup)
8441b44c5a6SAntoine Ténart 			return -ENOMEM;
8451b44c5a6SAntoine Ténart 
8461b44c5a6SAntoine Ténart 		ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
8471b44c5a6SAntoine Ténart 					   safexcel_ahash_complete, &result);
8481b44c5a6SAntoine Ténart 		sg_init_one(&sg, keydup, keylen);
8491b44c5a6SAntoine Ténart 		ahash_request_set_crypt(areq, &sg, ipad, keylen);
8501b44c5a6SAntoine Ténart 		init_completion(&result.completion);
8511b44c5a6SAntoine Ténart 
8521b44c5a6SAntoine Ténart 		ret = crypto_ahash_digest(areq);
8534dc5475aSAntoine Tenart 		if (ret == -EINPROGRESS || ret == -EBUSY) {
8541b44c5a6SAntoine Ténart 			wait_for_completion_interruptible(&result.completion);
8551b44c5a6SAntoine Ténart 			ret = result.error;
8561b44c5a6SAntoine Ténart 		}
8571b44c5a6SAntoine Ténart 
8581b44c5a6SAntoine Ténart 		/* Avoid leaking */
8591b44c5a6SAntoine Ténart 		memzero_explicit(keydup, keylen);
8601b44c5a6SAntoine Ténart 		kfree(keydup);
8611b44c5a6SAntoine Ténart 
8621b44c5a6SAntoine Ténart 		if (ret)
8631b44c5a6SAntoine Ténart 			return ret;
8641b44c5a6SAntoine Ténart 
8651b44c5a6SAntoine Ténart 		keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq));
8661b44c5a6SAntoine Ténart 	}
8671b44c5a6SAntoine Ténart 
8681b44c5a6SAntoine Ténart 	memset(ipad + keylen, 0, blocksize - keylen);
8691b44c5a6SAntoine Ténart 	memcpy(opad, ipad, blocksize);
8701b44c5a6SAntoine Ténart 
8711b44c5a6SAntoine Ténart 	for (i = 0; i < blocksize; i++) {
872aed3731eSAntoine Ténart 		ipad[i] ^= HMAC_IPAD_VALUE;
873aed3731eSAntoine Ténart 		opad[i] ^= HMAC_OPAD_VALUE;
8741b44c5a6SAntoine Ténart 	}
8751b44c5a6SAntoine Ténart 
8761b44c5a6SAntoine Ténart 	return 0;
8771b44c5a6SAntoine Ténart }
8781b44c5a6SAntoine Ténart 
8791b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq,
8801b44c5a6SAntoine Ténart 				 unsigned int blocksize, u8 *pad, void *state)
8811b44c5a6SAntoine Ténart {
8821b44c5a6SAntoine Ténart 	struct safexcel_ahash_result result;
8831b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req;
8841b44c5a6SAntoine Ténart 	struct scatterlist sg;
8851b44c5a6SAntoine Ténart 	int ret;
8861b44c5a6SAntoine Ténart 
8871b44c5a6SAntoine Ténart 	ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
8881b44c5a6SAntoine Ténart 				   safexcel_ahash_complete, &result);
8891b44c5a6SAntoine Ténart 	sg_init_one(&sg, pad, blocksize);
8901b44c5a6SAntoine Ténart 	ahash_request_set_crypt(areq, &sg, pad, blocksize);
8911b44c5a6SAntoine Ténart 	init_completion(&result.completion);
8921b44c5a6SAntoine Ténart 
8931b44c5a6SAntoine Ténart 	ret = crypto_ahash_init(areq);
8941b44c5a6SAntoine Ténart 	if (ret)
8951b44c5a6SAntoine Ténart 		return ret;
8961b44c5a6SAntoine Ténart 
8971b44c5a6SAntoine Ténart 	req = ahash_request_ctx(areq);
8981b44c5a6SAntoine Ténart 	req->hmac = true;
8991b44c5a6SAntoine Ténart 	req->last_req = true;
9001b44c5a6SAntoine Ténart 
9011b44c5a6SAntoine Ténart 	ret = crypto_ahash_update(areq);
90212bf4142SOfer Heifetz 	if (ret && ret != -EINPROGRESS && ret != -EBUSY)
9031b44c5a6SAntoine Ténart 		return ret;
9041b44c5a6SAntoine Ténart 
9051b44c5a6SAntoine Ténart 	wait_for_completion_interruptible(&result.completion);
9061b44c5a6SAntoine Ténart 	if (result.error)
9071b44c5a6SAntoine Ténart 		return result.error;
9081b44c5a6SAntoine Ténart 
9091b44c5a6SAntoine Ténart 	return crypto_ahash_export(areq, state);
9101b44c5a6SAntoine Ténart }
9111b44c5a6SAntoine Ténart 
9121b44c5a6SAntoine Ténart static int safexcel_hmac_setkey(const char *alg, const u8 *key,
9131b44c5a6SAntoine Ténart 				unsigned int keylen, void *istate, void *ostate)
9141b44c5a6SAntoine Ténart {
9151b44c5a6SAntoine Ténart 	struct ahash_request *areq;
9161b44c5a6SAntoine Ténart 	struct crypto_ahash *tfm;
9171b44c5a6SAntoine Ténart 	unsigned int blocksize;
9181b44c5a6SAntoine Ténart 	u8 *ipad, *opad;
9191b44c5a6SAntoine Ténart 	int ret;
9201b44c5a6SAntoine Ténart 
9211b44c5a6SAntoine Ténart 	tfm = crypto_alloc_ahash(alg, CRYPTO_ALG_TYPE_AHASH,
9221b44c5a6SAntoine Ténart 				 CRYPTO_ALG_TYPE_AHASH_MASK);
9231b44c5a6SAntoine Ténart 	if (IS_ERR(tfm))
9241b44c5a6SAntoine Ténart 		return PTR_ERR(tfm);
9251b44c5a6SAntoine Ténart 
9261b44c5a6SAntoine Ténart 	areq = ahash_request_alloc(tfm, GFP_KERNEL);
9271b44c5a6SAntoine Ténart 	if (!areq) {
9281b44c5a6SAntoine Ténart 		ret = -ENOMEM;
9291b44c5a6SAntoine Ténart 		goto free_ahash;
9301b44c5a6SAntoine Ténart 	}
9311b44c5a6SAntoine Ténart 
9321b44c5a6SAntoine Ténart 	crypto_ahash_clear_flags(tfm, ~0);
9331b44c5a6SAntoine Ténart 	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
9341b44c5a6SAntoine Ténart 
9351b44c5a6SAntoine Ténart 	ipad = kzalloc(2 * blocksize, GFP_KERNEL);
9361b44c5a6SAntoine Ténart 	if (!ipad) {
9371b44c5a6SAntoine Ténart 		ret = -ENOMEM;
9381b44c5a6SAntoine Ténart 		goto free_request;
9391b44c5a6SAntoine Ténart 	}
9401b44c5a6SAntoine Ténart 
9411b44c5a6SAntoine Ténart 	opad = ipad + blocksize;
9421b44c5a6SAntoine Ténart 
9431b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad);
9441b44c5a6SAntoine Ténart 	if (ret)
9451b44c5a6SAntoine Ténart 		goto free_ipad;
9461b44c5a6SAntoine Ténart 
9471b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate);
9481b44c5a6SAntoine Ténart 	if (ret)
9491b44c5a6SAntoine Ténart 		goto free_ipad;
9501b44c5a6SAntoine Ténart 
9511b44c5a6SAntoine Ténart 	ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate);
9521b44c5a6SAntoine Ténart 
9531b44c5a6SAntoine Ténart free_ipad:
9541b44c5a6SAntoine Ténart 	kfree(ipad);
9551b44c5a6SAntoine Ténart free_request:
9561b44c5a6SAntoine Ténart 	ahash_request_free(areq);
9571b44c5a6SAntoine Ténart free_ahash:
9581b44c5a6SAntoine Ténart 	crypto_free_ahash(tfm);
9591b44c5a6SAntoine Ténart 
9601b44c5a6SAntoine Ténart 	return ret;
9611b44c5a6SAntoine Ténart }
9621b44c5a6SAntoine Ténart 
96373f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key,
96473f36ea7SAntoine Tenart 				    unsigned int keylen, const char *alg,
96573f36ea7SAntoine Tenart 				    unsigned int state_sz)
9661b44c5a6SAntoine Ténart {
9671b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
968871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
9691b44c5a6SAntoine Ténart 	struct safexcel_ahash_export_state istate, ostate;
9701b44c5a6SAntoine Ténart 	int ret, i;
9711b44c5a6SAntoine Ténart 
97273f36ea7SAntoine Tenart 	ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate);
9731b44c5a6SAntoine Ténart 	if (ret)
9741b44c5a6SAntoine Ténart 		return ret;
9751b44c5a6SAntoine Ténart 
976871df319SAntoine Ténart 	if (priv->version == EIP197 && ctx->base.ctxr) {
97773f36ea7SAntoine Tenart 		for (i = 0; i < state_sz / sizeof(u32); i++) {
9781b44c5a6SAntoine Ténart 			if (ctx->ipad[i] != le32_to_cpu(istate.state[i]) ||
9791b44c5a6SAntoine Ténart 			    ctx->opad[i] != le32_to_cpu(ostate.state[i])) {
9801b44c5a6SAntoine Ténart 				ctx->base.needs_inv = true;
9811b44c5a6SAntoine Ténart 				break;
9821b44c5a6SAntoine Ténart 			}
9831b44c5a6SAntoine Ténart 		}
984c4daf4ccSOfer Heifetz 	}
9851b44c5a6SAntoine Ténart 
98673f36ea7SAntoine Tenart 	memcpy(ctx->ipad, &istate.state, state_sz);
98773f36ea7SAntoine Tenart 	memcpy(ctx->opad, &ostate.state, state_sz);
98842ef3bedSAntoine Ténart 
9891b44c5a6SAntoine Ténart 	return 0;
9901b44c5a6SAntoine Ténart }
9911b44c5a6SAntoine Ténart 
99273f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
99373f36ea7SAntoine Tenart 				     unsigned int keylen)
99473f36ea7SAntoine Tenart {
99573f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1",
99673f36ea7SAntoine Tenart 					SHA1_DIGEST_SIZE);
99773f36ea7SAntoine Tenart }
99873f36ea7SAntoine Tenart 
9991b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = {
10001b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
10011b44c5a6SAntoine Ténart 	.alg.ahash = {
10021b44c5a6SAntoine Ténart 		.init = safexcel_hmac_sha1_init,
10031b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
10041b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
10051b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
10061b44c5a6SAntoine Ténart 		.digest = safexcel_hmac_sha1_digest,
10071b44c5a6SAntoine Ténart 		.setkey = safexcel_hmac_sha1_setkey,
10081b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
10091b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
10101b44c5a6SAntoine Ténart 		.halg = {
10111b44c5a6SAntoine Ténart 			.digestsize = SHA1_DIGEST_SIZE,
10121b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
10131b44c5a6SAntoine Ténart 			.base = {
10141b44c5a6SAntoine Ténart 				.cra_name = "hmac(sha1)",
10151b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-hmac-sha1",
10161b44c5a6SAntoine Ténart 				.cra_priority = 300,
10171b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
10181b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
10191b44c5a6SAntoine Ténart 				.cra_blocksize = SHA1_BLOCK_SIZE,
10201b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
10211b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
10221b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
10231b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
10241b44c5a6SAntoine Ténart 			},
10251b44c5a6SAntoine Ténart 		},
10261b44c5a6SAntoine Ténart 	},
10271b44c5a6SAntoine Ténart };
10281b44c5a6SAntoine Ténart 
10291b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq)
10301b44c5a6SAntoine Ténart {
10311b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
10321b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
10331b44c5a6SAntoine Ténart 
10341b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
10351b44c5a6SAntoine Ténart 
10361b44c5a6SAntoine Ténart 	req->state[0] = SHA256_H0;
10371b44c5a6SAntoine Ténart 	req->state[1] = SHA256_H1;
10381b44c5a6SAntoine Ténart 	req->state[2] = SHA256_H2;
10391b44c5a6SAntoine Ténart 	req->state[3] = SHA256_H3;
10401b44c5a6SAntoine Ténart 	req->state[4] = SHA256_H4;
10411b44c5a6SAntoine Ténart 	req->state[5] = SHA256_H5;
10421b44c5a6SAntoine Ténart 	req->state[6] = SHA256_H6;
10431b44c5a6SAntoine Ténart 	req->state[7] = SHA256_H7;
10441b44c5a6SAntoine Ténart 
10451b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1046b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
10471b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
10481b44c5a6SAntoine Ténart 
10491b44c5a6SAntoine Ténart 	return 0;
10501b44c5a6SAntoine Ténart }
10511b44c5a6SAntoine Ténart 
10521b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq)
10531b44c5a6SAntoine Ténart {
10541b44c5a6SAntoine Ténart 	int ret = safexcel_sha256_init(areq);
10551b44c5a6SAntoine Ténart 
10561b44c5a6SAntoine Ténart 	if (ret)
10571b44c5a6SAntoine Ténart 		return ret;
10581b44c5a6SAntoine Ténart 
10591b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
10601b44c5a6SAntoine Ténart }
10611b44c5a6SAntoine Ténart 
10621b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = {
10631b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
10641b44c5a6SAntoine Ténart 	.alg.ahash = {
10651b44c5a6SAntoine Ténart 		.init = safexcel_sha256_init,
10661b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
10671b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
10681b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
10691b44c5a6SAntoine Ténart 		.digest = safexcel_sha256_digest,
10701b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
10711b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
10721b44c5a6SAntoine Ténart 		.halg = {
10731b44c5a6SAntoine Ténart 			.digestsize = SHA256_DIGEST_SIZE,
10741b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
10751b44c5a6SAntoine Ténart 			.base = {
10761b44c5a6SAntoine Ténart 				.cra_name = "sha256",
10771b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha256",
10781b44c5a6SAntoine Ténart 				.cra_priority = 300,
10791b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
10801b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
10811b44c5a6SAntoine Ténart 				.cra_blocksize = SHA256_BLOCK_SIZE,
10821b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
10831b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
10841b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
10851b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
10861b44c5a6SAntoine Ténart 			},
10871b44c5a6SAntoine Ténart 		},
10881b44c5a6SAntoine Ténart 	},
10891b44c5a6SAntoine Ténart };
10901b44c5a6SAntoine Ténart 
10911b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq)
10921b44c5a6SAntoine Ténart {
10931b44c5a6SAntoine Ténart 	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
10941b44c5a6SAntoine Ténart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
10951b44c5a6SAntoine Ténart 
10961b44c5a6SAntoine Ténart 	memset(req, 0, sizeof(*req));
10971b44c5a6SAntoine Ténart 
10981b44c5a6SAntoine Ténart 	req->state[0] = SHA224_H0;
10991b44c5a6SAntoine Ténart 	req->state[1] = SHA224_H1;
11001b44c5a6SAntoine Ténart 	req->state[2] = SHA224_H2;
11011b44c5a6SAntoine Ténart 	req->state[3] = SHA224_H3;
11021b44c5a6SAntoine Ténart 	req->state[4] = SHA224_H4;
11031b44c5a6SAntoine Ténart 	req->state[5] = SHA224_H5;
11041b44c5a6SAntoine Ténart 	req->state[6] = SHA224_H6;
11051b44c5a6SAntoine Ténart 	req->state[7] = SHA224_H7;
11061b44c5a6SAntoine Ténart 
11071b44c5a6SAntoine Ténart 	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1108b869648cSAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
11091b44c5a6SAntoine Ténart 	req->state_sz = SHA256_DIGEST_SIZE;
11101b44c5a6SAntoine Ténart 
11111b44c5a6SAntoine Ténart 	return 0;
11121b44c5a6SAntoine Ténart }
11131b44c5a6SAntoine Ténart 
11141b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq)
11151b44c5a6SAntoine Ténart {
11161b44c5a6SAntoine Ténart 	int ret = safexcel_sha224_init(areq);
11171b44c5a6SAntoine Ténart 
11181b44c5a6SAntoine Ténart 	if (ret)
11191b44c5a6SAntoine Ténart 		return ret;
11201b44c5a6SAntoine Ténart 
11211b44c5a6SAntoine Ténart 	return safexcel_ahash_finup(areq);
11221b44c5a6SAntoine Ténart }
11231b44c5a6SAntoine Ténart 
11241b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = {
11251b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
11261b44c5a6SAntoine Ténart 	.alg.ahash = {
11271b44c5a6SAntoine Ténart 		.init = safexcel_sha224_init,
11281b44c5a6SAntoine Ténart 		.update = safexcel_ahash_update,
11291b44c5a6SAntoine Ténart 		.final = safexcel_ahash_final,
11301b44c5a6SAntoine Ténart 		.finup = safexcel_ahash_finup,
11311b44c5a6SAntoine Ténart 		.digest = safexcel_sha224_digest,
11321b44c5a6SAntoine Ténart 		.export = safexcel_ahash_export,
11331b44c5a6SAntoine Ténart 		.import = safexcel_ahash_import,
11341b44c5a6SAntoine Ténart 		.halg = {
11351b44c5a6SAntoine Ténart 			.digestsize = SHA224_DIGEST_SIZE,
11361b44c5a6SAntoine Ténart 			.statesize = sizeof(struct safexcel_ahash_export_state),
11371b44c5a6SAntoine Ténart 			.base = {
11381b44c5a6SAntoine Ténart 				.cra_name = "sha224",
11391b44c5a6SAntoine Ténart 				.cra_driver_name = "safexcel-sha224",
11401b44c5a6SAntoine Ténart 				.cra_priority = 300,
11411b44c5a6SAntoine Ténart 				.cra_flags = CRYPTO_ALG_ASYNC |
11421b44c5a6SAntoine Ténart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
11431b44c5a6SAntoine Ténart 				.cra_blocksize = SHA224_BLOCK_SIZE,
11441b44c5a6SAntoine Ténart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
11451b44c5a6SAntoine Ténart 				.cra_init = safexcel_ahash_cra_init,
11461b44c5a6SAntoine Ténart 				.cra_exit = safexcel_ahash_cra_exit,
11471b44c5a6SAntoine Ténart 				.cra_module = THIS_MODULE,
11481b44c5a6SAntoine Ténart 			},
11491b44c5a6SAntoine Ténart 		},
11501b44c5a6SAntoine Ténart 	},
11511b44c5a6SAntoine Ténart };
115273f36ea7SAntoine Tenart 
11533ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key,
11543ad618d8SAntoine Tenart 				       unsigned int keylen)
11553ad618d8SAntoine Tenart {
11563ad618d8SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224",
11573ad618d8SAntoine Tenart 					SHA256_DIGEST_SIZE);
11583ad618d8SAntoine Tenart }
11593ad618d8SAntoine Tenart 
11603ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq)
11613ad618d8SAntoine Tenart {
11623ad618d8SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
11633ad618d8SAntoine Tenart 
11643ad618d8SAntoine Tenart 	safexcel_sha224_init(areq);
11653ad618d8SAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
11663ad618d8SAntoine Tenart 	return 0;
11673ad618d8SAntoine Tenart }
11683ad618d8SAntoine Tenart 
11693ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq)
11703ad618d8SAntoine Tenart {
11713ad618d8SAntoine Tenart 	int ret = safexcel_hmac_sha224_init(areq);
11723ad618d8SAntoine Tenart 
11733ad618d8SAntoine Tenart 	if (ret)
11743ad618d8SAntoine Tenart 		return ret;
11753ad618d8SAntoine Tenart 
11763ad618d8SAntoine Tenart 	return safexcel_ahash_finup(areq);
11773ad618d8SAntoine Tenart }
11783ad618d8SAntoine Tenart 
11793ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = {
11803ad618d8SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
11813ad618d8SAntoine Tenart 	.alg.ahash = {
11823ad618d8SAntoine Tenart 		.init = safexcel_hmac_sha224_init,
11833ad618d8SAntoine Tenart 		.update = safexcel_ahash_update,
11843ad618d8SAntoine Tenart 		.final = safexcel_ahash_final,
11853ad618d8SAntoine Tenart 		.finup = safexcel_ahash_finup,
11863ad618d8SAntoine Tenart 		.digest = safexcel_hmac_sha224_digest,
11873ad618d8SAntoine Tenart 		.setkey = safexcel_hmac_sha224_setkey,
11883ad618d8SAntoine Tenart 		.export = safexcel_ahash_export,
11893ad618d8SAntoine Tenart 		.import = safexcel_ahash_import,
11903ad618d8SAntoine Tenart 		.halg = {
11913ad618d8SAntoine Tenart 			.digestsize = SHA224_DIGEST_SIZE,
11923ad618d8SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
11933ad618d8SAntoine Tenart 			.base = {
11943ad618d8SAntoine Tenart 				.cra_name = "hmac(sha224)",
11953ad618d8SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha224",
11963ad618d8SAntoine Tenart 				.cra_priority = 300,
11973ad618d8SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
11983ad618d8SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
11993ad618d8SAntoine Tenart 				.cra_blocksize = SHA224_BLOCK_SIZE,
12003ad618d8SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
12013ad618d8SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
12023ad618d8SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
12033ad618d8SAntoine Tenart 				.cra_module = THIS_MODULE,
12043ad618d8SAntoine Tenart 			},
12053ad618d8SAntoine Tenart 		},
12063ad618d8SAntoine Tenart 	},
12073ad618d8SAntoine Tenart };
12083ad618d8SAntoine Tenart 
120973f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
121073f36ea7SAntoine Tenart 				     unsigned int keylen)
121173f36ea7SAntoine Tenart {
121273f36ea7SAntoine Tenart 	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256",
121373f36ea7SAntoine Tenart 					SHA256_DIGEST_SIZE);
121473f36ea7SAntoine Tenart }
121573f36ea7SAntoine Tenart 
121673f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq)
121773f36ea7SAntoine Tenart {
121873f36ea7SAntoine Tenart 	struct safexcel_ahash_req *req = ahash_request_ctx(areq);
121973f36ea7SAntoine Tenart 
122073f36ea7SAntoine Tenart 	safexcel_sha256_init(areq);
122173f36ea7SAntoine Tenart 	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
122273f36ea7SAntoine Tenart 	return 0;
122373f36ea7SAntoine Tenart }
122473f36ea7SAntoine Tenart 
122573f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq)
122673f36ea7SAntoine Tenart {
122773f36ea7SAntoine Tenart 	int ret = safexcel_hmac_sha256_init(areq);
122873f36ea7SAntoine Tenart 
122973f36ea7SAntoine Tenart 	if (ret)
123073f36ea7SAntoine Tenart 		return ret;
123173f36ea7SAntoine Tenart 
123273f36ea7SAntoine Tenart 	return safexcel_ahash_finup(areq);
123373f36ea7SAntoine Tenart }
123473f36ea7SAntoine Tenart 
123573f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = {
123673f36ea7SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AHASH,
123773f36ea7SAntoine Tenart 	.alg.ahash = {
123873f36ea7SAntoine Tenart 		.init = safexcel_hmac_sha256_init,
123973f36ea7SAntoine Tenart 		.update = safexcel_ahash_update,
124073f36ea7SAntoine Tenart 		.final = safexcel_ahash_final,
124173f36ea7SAntoine Tenart 		.finup = safexcel_ahash_finup,
124273f36ea7SAntoine Tenart 		.digest = safexcel_hmac_sha256_digest,
124373f36ea7SAntoine Tenart 		.setkey = safexcel_hmac_sha256_setkey,
124473f36ea7SAntoine Tenart 		.export = safexcel_ahash_export,
124573f36ea7SAntoine Tenart 		.import = safexcel_ahash_import,
124673f36ea7SAntoine Tenart 		.halg = {
124773f36ea7SAntoine Tenart 			.digestsize = SHA256_DIGEST_SIZE,
124873f36ea7SAntoine Tenart 			.statesize = sizeof(struct safexcel_ahash_export_state),
124973f36ea7SAntoine Tenart 			.base = {
125073f36ea7SAntoine Tenart 				.cra_name = "hmac(sha256)",
125173f36ea7SAntoine Tenart 				.cra_driver_name = "safexcel-hmac-sha256",
125273f36ea7SAntoine Tenart 				.cra_priority = 300,
125373f36ea7SAntoine Tenart 				.cra_flags = CRYPTO_ALG_ASYNC |
125473f36ea7SAntoine Tenart 					     CRYPTO_ALG_KERN_DRIVER_ONLY,
125573f36ea7SAntoine Tenart 				.cra_blocksize = SHA256_BLOCK_SIZE,
125673f36ea7SAntoine Tenart 				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
125773f36ea7SAntoine Tenart 				.cra_init = safexcel_ahash_cra_init,
125873f36ea7SAntoine Tenart 				.cra_exit = safexcel_ahash_cra_exit,
125973f36ea7SAntoine Tenart 				.cra_module = THIS_MODULE,
126073f36ea7SAntoine Tenart 			},
126173f36ea7SAntoine Tenart 		},
126273f36ea7SAntoine Tenart 	},
126373f36ea7SAntoine Tenart };
1264