162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2017 Marvell
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Antoine Tenart <antoine.tenart@free-electrons.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <crypto/aes.h>
962306a36Sopenharmony_ci#include <crypto/hmac.h>
1062306a36Sopenharmony_ci#include <crypto/md5.h>
1162306a36Sopenharmony_ci#include <crypto/sha1.h>
1262306a36Sopenharmony_ci#include <crypto/sha2.h>
1362306a36Sopenharmony_ci#include <crypto/sha3.h>
1462306a36Sopenharmony_ci#include <crypto/skcipher.h>
1562306a36Sopenharmony_ci#include <crypto/sm3.h>
1662306a36Sopenharmony_ci#include <crypto/internal/cipher.h>
1762306a36Sopenharmony_ci#include <linux/device.h>
1862306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1962306a36Sopenharmony_ci#include <linux/dmapool.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include "safexcel.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct safexcel_ahash_ctx {
2462306a36Sopenharmony_ci	struct safexcel_context base;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	u32 alg;
2762306a36Sopenharmony_ci	u8  key_sz;
2862306a36Sopenharmony_ci	bool cbcmac;
2962306a36Sopenharmony_ci	bool do_fallback;
3062306a36Sopenharmony_ci	bool fb_init_done;
3162306a36Sopenharmony_ci	bool fb_do_setkey;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	struct crypto_aes_ctx *aes;
3462306a36Sopenharmony_ci	struct crypto_ahash *fback;
3562306a36Sopenharmony_ci	struct crypto_shash *shpre;
3662306a36Sopenharmony_ci	struct shash_desc *shdesc;
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistruct safexcel_ahash_req {
4062306a36Sopenharmony_ci	bool last_req;
4162306a36Sopenharmony_ci	bool finish;
4262306a36Sopenharmony_ci	bool hmac;
4362306a36Sopenharmony_ci	bool needs_inv;
4462306a36Sopenharmony_ci	bool hmac_zlen;
4562306a36Sopenharmony_ci	bool len_is_le;
4662306a36Sopenharmony_ci	bool not_first;
4762306a36Sopenharmony_ci	bool xcbcmac;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	int nents;
5062306a36Sopenharmony_ci	dma_addr_t result_dma;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	u32 digest;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	u8 state_sz;    /* expected state size, only set once */
5562306a36Sopenharmony_ci	u8 block_sz;    /* block size, only set once */
5662306a36Sopenharmony_ci	u8 digest_sz;   /* output digest size, only set once */
5762306a36Sopenharmony_ci	__le32 state[SHA3_512_BLOCK_SIZE /
5862306a36Sopenharmony_ci		     sizeof(__le32)] __aligned(sizeof(__le32));
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	u64 len;
6162306a36Sopenharmony_ci	u64 processed;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32));
6462306a36Sopenharmony_ci	dma_addr_t cache_dma;
6562306a36Sopenharmony_ci	unsigned int cache_sz;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32));
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic inline u64 safexcel_queued_len(struct safexcel_ahash_req *req)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	return req->len - req->processed;
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic void safexcel_hash_token(struct safexcel_command_desc *cdesc,
7662306a36Sopenharmony_ci				u32 input_length, u32 result_length,
7762306a36Sopenharmony_ci				bool cbcmac)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	struct safexcel_token *token =
8062306a36Sopenharmony_ci		(struct safexcel_token *)cdesc->control_data.token;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
8362306a36Sopenharmony_ci	token[0].packet_length = input_length;
8462306a36Sopenharmony_ci	token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	input_length &= 15;
8762306a36Sopenharmony_ci	if (unlikely(cbcmac && input_length)) {
8862306a36Sopenharmony_ci		token[0].stat =  0;
8962306a36Sopenharmony_ci		token[1].opcode = EIP197_TOKEN_OPCODE_INSERT;
9062306a36Sopenharmony_ci		token[1].packet_length = 16 - input_length;
9162306a36Sopenharmony_ci		token[1].stat = EIP197_TOKEN_STAT_LAST_HASH;
9262306a36Sopenharmony_ci		token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH;
9362306a36Sopenharmony_ci	} else {
9462306a36Sopenharmony_ci		token[0].stat = EIP197_TOKEN_STAT_LAST_HASH;
9562306a36Sopenharmony_ci		eip197_noop_token(&token[1]);
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	token[2].opcode = EIP197_TOKEN_OPCODE_INSERT;
9962306a36Sopenharmony_ci	token[2].stat = EIP197_TOKEN_STAT_LAST_HASH |
10062306a36Sopenharmony_ci			EIP197_TOKEN_STAT_LAST_PACKET;
10162306a36Sopenharmony_ci	token[2].packet_length = result_length;
10262306a36Sopenharmony_ci	token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
10362306a36Sopenharmony_ci				EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	eip197_noop_token(&token[3]);
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic void safexcel_context_control(struct safexcel_ahash_ctx *ctx,
10962306a36Sopenharmony_ci				     struct safexcel_ahash_req *req,
11062306a36Sopenharmony_ci				     struct safexcel_command_desc *cdesc)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	struct safexcel_crypto_priv *priv = ctx->base.priv;
11362306a36Sopenharmony_ci	u64 count = 0;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	cdesc->control_data.control0 = ctx->alg;
11662306a36Sopenharmony_ci	cdesc->control_data.control1 = 0;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	/*
11962306a36Sopenharmony_ci	 * Copy the input digest if needed, and setup the context
12062306a36Sopenharmony_ci	 * fields. Do this now as we need it to setup the first command
12162306a36Sopenharmony_ci	 * descriptor.
12262306a36Sopenharmony_ci	 */
12362306a36Sopenharmony_ci	if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) {
12462306a36Sopenharmony_ci		if (req->xcbcmac)
12562306a36Sopenharmony_ci			memcpy(ctx->base.ctxr->data, &ctx->base.ipad, ctx->key_sz);
12662306a36Sopenharmony_ci		else
12762306a36Sopenharmony_ci			memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		if (!req->finish && req->xcbcmac)
13062306a36Sopenharmony_ci			cdesc->control_data.control0 |=
13162306a36Sopenharmony_ci				CONTEXT_CONTROL_DIGEST_XCM |
13262306a36Sopenharmony_ci				CONTEXT_CONTROL_TYPE_HASH_OUT  |
13362306a36Sopenharmony_ci				CONTEXT_CONTROL_NO_FINISH_HASH |
13462306a36Sopenharmony_ci				CONTEXT_CONTROL_SIZE(req->state_sz /
13562306a36Sopenharmony_ci						     sizeof(u32));
13662306a36Sopenharmony_ci		else
13762306a36Sopenharmony_ci			cdesc->control_data.control0 |=
13862306a36Sopenharmony_ci				CONTEXT_CONTROL_DIGEST_XCM |
13962306a36Sopenharmony_ci				CONTEXT_CONTROL_TYPE_HASH_OUT  |
14062306a36Sopenharmony_ci				CONTEXT_CONTROL_SIZE(req->state_sz /
14162306a36Sopenharmony_ci						     sizeof(u32));
14262306a36Sopenharmony_ci		return;
14362306a36Sopenharmony_ci	} else if (!req->processed) {
14462306a36Sopenharmony_ci		/* First - and possibly only - block of basic hash only */
14562306a36Sopenharmony_ci		if (req->finish)
14662306a36Sopenharmony_ci			cdesc->control_data.control0 |= req->digest |
14762306a36Sopenharmony_ci				CONTEXT_CONTROL_TYPE_HASH_OUT |
14862306a36Sopenharmony_ci				CONTEXT_CONTROL_RESTART_HASH  |
14962306a36Sopenharmony_ci				/* ensure its not 0! */
15062306a36Sopenharmony_ci				CONTEXT_CONTROL_SIZE(1);
15162306a36Sopenharmony_ci		else
15262306a36Sopenharmony_ci			cdesc->control_data.control0 |= req->digest |
15362306a36Sopenharmony_ci				CONTEXT_CONTROL_TYPE_HASH_OUT  |
15462306a36Sopenharmony_ci				CONTEXT_CONTROL_RESTART_HASH   |
15562306a36Sopenharmony_ci				CONTEXT_CONTROL_NO_FINISH_HASH |
15662306a36Sopenharmony_ci				/* ensure its not 0! */
15762306a36Sopenharmony_ci				CONTEXT_CONTROL_SIZE(1);
15862306a36Sopenharmony_ci		return;
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	/* Hash continuation or HMAC, setup (inner) digest from state */
16262306a36Sopenharmony_ci	memcpy(ctx->base.ctxr->data, req->state, req->state_sz);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	if (req->finish) {
16562306a36Sopenharmony_ci		/* Compute digest count for hash/HMAC finish operations */
16662306a36Sopenharmony_ci		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
16762306a36Sopenharmony_ci		    req->hmac_zlen || (req->processed != req->block_sz)) {
16862306a36Sopenharmony_ci			count = req->processed / EIP197_COUNTER_BLOCK_SIZE;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci			/* This is a hardware limitation, as the
17162306a36Sopenharmony_ci			 * counter must fit into an u32. This represents
17262306a36Sopenharmony_ci			 * a fairly big amount of input data, so we
17362306a36Sopenharmony_ci			 * shouldn't see this.
17462306a36Sopenharmony_ci			 */
17562306a36Sopenharmony_ci			if (unlikely(count & 0xffffffff00000000ULL)) {
17662306a36Sopenharmony_ci				dev_warn(priv->dev,
17762306a36Sopenharmony_ci					 "Input data is too big\n");
17862306a36Sopenharmony_ci				return;
17962306a36Sopenharmony_ci			}
18062306a36Sopenharmony_ci		}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci		if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) ||
18362306a36Sopenharmony_ci		    /* Special case: zero length HMAC */
18462306a36Sopenharmony_ci		    req->hmac_zlen ||
18562306a36Sopenharmony_ci		    /* PE HW < 4.4 cannot do HMAC continue, fake using hash */
18662306a36Sopenharmony_ci		    (req->processed != req->block_sz)) {
18762306a36Sopenharmony_ci			/* Basic hash continue operation, need digest + cnt */
18862306a36Sopenharmony_ci			cdesc->control_data.control0 |=
18962306a36Sopenharmony_ci				CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) |
19062306a36Sopenharmony_ci				CONTEXT_CONTROL_TYPE_HASH_OUT |
19162306a36Sopenharmony_ci				CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
19262306a36Sopenharmony_ci			/* For zero-len HMAC, don't finalize, already padded! */
19362306a36Sopenharmony_ci			if (req->hmac_zlen)
19462306a36Sopenharmony_ci				cdesc->control_data.control0 |=
19562306a36Sopenharmony_ci					CONTEXT_CONTROL_NO_FINISH_HASH;
19662306a36Sopenharmony_ci			cdesc->control_data.control1 |=
19762306a36Sopenharmony_ci				CONTEXT_CONTROL_DIGEST_CNT;
19862306a36Sopenharmony_ci			ctx->base.ctxr->data[req->state_sz >> 2] =
19962306a36Sopenharmony_ci				cpu_to_le32(count);
20062306a36Sopenharmony_ci			req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci			/* Clear zero-length HMAC flag for next operation! */
20362306a36Sopenharmony_ci			req->hmac_zlen = false;
20462306a36Sopenharmony_ci		} else { /* HMAC */
20562306a36Sopenharmony_ci			/* Need outer digest for HMAC finalization */
20662306a36Sopenharmony_ci			memcpy(ctx->base.ctxr->data + (req->state_sz >> 2),
20762306a36Sopenharmony_ci			       &ctx->base.opad, req->state_sz);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci			/* Single pass HMAC - no digest count */
21062306a36Sopenharmony_ci			cdesc->control_data.control0 |=
21162306a36Sopenharmony_ci				CONTEXT_CONTROL_SIZE(req->state_sz >> 1) |
21262306a36Sopenharmony_ci				CONTEXT_CONTROL_TYPE_HASH_OUT |
21362306a36Sopenharmony_ci				CONTEXT_CONTROL_DIGEST_HMAC;
21462306a36Sopenharmony_ci		}
21562306a36Sopenharmony_ci	} else { /* Hash continuation, do not finish yet */
21662306a36Sopenharmony_ci		cdesc->control_data.control0 |=
21762306a36Sopenharmony_ci			CONTEXT_CONTROL_SIZE(req->state_sz >> 2) |
21862306a36Sopenharmony_ci			CONTEXT_CONTROL_DIGEST_PRECOMPUTED |
21962306a36Sopenharmony_ci			CONTEXT_CONTROL_TYPE_HASH_OUT |
22062306a36Sopenharmony_ci			CONTEXT_CONTROL_NO_FINISH_HASH;
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic int safexcel_ahash_enqueue(struct ahash_request *areq);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistatic int safexcel_handle_req_result(struct safexcel_crypto_priv *priv,
22762306a36Sopenharmony_ci				      int ring,
22862306a36Sopenharmony_ci				      struct crypto_async_request *async,
22962306a36Sopenharmony_ci				      bool *should_complete, int *ret)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	struct safexcel_result_desc *rdesc;
23262306a36Sopenharmony_ci	struct ahash_request *areq = ahash_request_cast(async);
23362306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
23462306a36Sopenharmony_ci	struct safexcel_ahash_req *sreq = ahash_request_ctx_dma(areq);
23562306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
23662306a36Sopenharmony_ci	u64 cache_len;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	*ret = 0;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
24162306a36Sopenharmony_ci	if (IS_ERR(rdesc)) {
24262306a36Sopenharmony_ci		dev_err(priv->dev,
24362306a36Sopenharmony_ci			"hash: result: could not retrieve the result descriptor\n");
24462306a36Sopenharmony_ci		*ret = PTR_ERR(rdesc);
24562306a36Sopenharmony_ci	} else {
24662306a36Sopenharmony_ci		*ret = safexcel_rdesc_check_errors(priv, rdesc);
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	safexcel_complete(priv, ring);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	if (sreq->nents) {
25262306a36Sopenharmony_ci		dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE);
25362306a36Sopenharmony_ci		sreq->nents = 0;
25462306a36Sopenharmony_ci	}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	if (sreq->result_dma) {
25762306a36Sopenharmony_ci		dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz,
25862306a36Sopenharmony_ci				 DMA_FROM_DEVICE);
25962306a36Sopenharmony_ci		sreq->result_dma = 0;
26062306a36Sopenharmony_ci	}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	if (sreq->cache_dma) {
26362306a36Sopenharmony_ci		dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz,
26462306a36Sopenharmony_ci				 DMA_TO_DEVICE);
26562306a36Sopenharmony_ci		sreq->cache_dma = 0;
26662306a36Sopenharmony_ci		sreq->cache_sz = 0;
26762306a36Sopenharmony_ci	}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	if (sreq->finish) {
27062306a36Sopenharmony_ci		if (sreq->hmac &&
27162306a36Sopenharmony_ci		    (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) {
27262306a36Sopenharmony_ci			/* Faking HMAC using hash - need to do outer hash */
27362306a36Sopenharmony_ci			memcpy(sreq->cache, sreq->state,
27462306a36Sopenharmony_ci			       crypto_ahash_digestsize(ahash));
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci			memcpy(sreq->state, &ctx->base.opad, sreq->digest_sz);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci			sreq->len = sreq->block_sz +
27962306a36Sopenharmony_ci				    crypto_ahash_digestsize(ahash);
28062306a36Sopenharmony_ci			sreq->processed = sreq->block_sz;
28162306a36Sopenharmony_ci			sreq->hmac = 0;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci			if (priv->flags & EIP197_TRC_CACHE)
28462306a36Sopenharmony_ci				ctx->base.needs_inv = true;
28562306a36Sopenharmony_ci			areq->nbytes = 0;
28662306a36Sopenharmony_ci			safexcel_ahash_enqueue(areq);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci			*should_complete = false; /* Not done yet */
28962306a36Sopenharmony_ci			return 1;
29062306a36Sopenharmony_ci		}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci		if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM &&
29362306a36Sopenharmony_ci			     ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) {
29462306a36Sopenharmony_ci			/* Undo final XOR with 0xffffffff ...*/
29562306a36Sopenharmony_ci			*(__le32 *)areq->result = ~sreq->state[0];
29662306a36Sopenharmony_ci		} else {
29762306a36Sopenharmony_ci			memcpy(areq->result, sreq->state,
29862306a36Sopenharmony_ci			       crypto_ahash_digestsize(ahash));
29962306a36Sopenharmony_ci		}
30062306a36Sopenharmony_ci	}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	cache_len = safexcel_queued_len(sreq);
30362306a36Sopenharmony_ci	if (cache_len)
30462306a36Sopenharmony_ci		memcpy(sreq->cache, sreq->cache_next, cache_len);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	*should_complete = true;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	return 1;
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_cistatic int safexcel_ahash_send_req(struct crypto_async_request *async, int ring,
31262306a36Sopenharmony_ci				   int *commands, int *results)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	struct ahash_request *areq = ahash_request_cast(async);
31562306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
31662306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
31762306a36Sopenharmony_ci	struct safexcel_crypto_priv *priv = ctx->base.priv;
31862306a36Sopenharmony_ci	struct safexcel_command_desc *cdesc, *first_cdesc = NULL;
31962306a36Sopenharmony_ci	struct safexcel_result_desc *rdesc;
32062306a36Sopenharmony_ci	struct scatterlist *sg;
32162306a36Sopenharmony_ci	struct safexcel_token *dmmy;
32262306a36Sopenharmony_ci	int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0;
32362306a36Sopenharmony_ci	u64 queued, len;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	queued = safexcel_queued_len(req);
32662306a36Sopenharmony_ci	if (queued <= HASH_CACHE_SIZE)
32762306a36Sopenharmony_ci		cache_len = queued;
32862306a36Sopenharmony_ci	else
32962306a36Sopenharmony_ci		cache_len = queued - areq->nbytes;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	if (!req->finish && !req->last_req) {
33262306a36Sopenharmony_ci		/* If this is not the last request and the queued data does not
33362306a36Sopenharmony_ci		 * fit into full cache blocks, cache it for the next send call.
33462306a36Sopenharmony_ci		 */
33562306a36Sopenharmony_ci		extra = queued & (HASH_CACHE_SIZE - 1);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci		/* If this is not the last request and the queued data
33862306a36Sopenharmony_ci		 * is a multiple of a block, cache the last one for now.
33962306a36Sopenharmony_ci		 */
34062306a36Sopenharmony_ci		if (!extra)
34162306a36Sopenharmony_ci			extra = HASH_CACHE_SIZE;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
34462306a36Sopenharmony_ci				   req->cache_next, extra,
34562306a36Sopenharmony_ci				   areq->nbytes - extra);
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci		queued -= extra;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci		if (!queued) {
35062306a36Sopenharmony_ci			*commands = 0;
35162306a36Sopenharmony_ci			*results = 0;
35262306a36Sopenharmony_ci			return 0;
35362306a36Sopenharmony_ci		}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci		extra = 0;
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) {
35962306a36Sopenharmony_ci		if (unlikely(cache_len < AES_BLOCK_SIZE)) {
36062306a36Sopenharmony_ci			/*
36162306a36Sopenharmony_ci			 * Cache contains less than 1 full block, complete.
36262306a36Sopenharmony_ci			 */
36362306a36Sopenharmony_ci			extra = AES_BLOCK_SIZE - cache_len;
36462306a36Sopenharmony_ci			if (queued > cache_len) {
36562306a36Sopenharmony_ci				/* More data follows: borrow bytes */
36662306a36Sopenharmony_ci				u64 tmp = queued - cache_len;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci				skip = min_t(u64, tmp, extra);
36962306a36Sopenharmony_ci				sg_pcopy_to_buffer(areq->src,
37062306a36Sopenharmony_ci					sg_nents(areq->src),
37162306a36Sopenharmony_ci					req->cache + cache_len,
37262306a36Sopenharmony_ci					skip, 0);
37362306a36Sopenharmony_ci			}
37462306a36Sopenharmony_ci			extra -= skip;
37562306a36Sopenharmony_ci			memset(req->cache + cache_len + skip, 0, extra);
37662306a36Sopenharmony_ci			if (!ctx->cbcmac && extra) {
37762306a36Sopenharmony_ci				// 10- padding for XCBCMAC & CMAC
37862306a36Sopenharmony_ci				req->cache[cache_len + skip] = 0x80;
37962306a36Sopenharmony_ci				// HW will use K2 iso K3 - compensate!
38062306a36Sopenharmony_ci				for (i = 0; i < AES_BLOCK_SIZE / 4; i++) {
38162306a36Sopenharmony_ci					u32 *cache = (void *)req->cache;
38262306a36Sopenharmony_ci					u32 *ipad = ctx->base.ipad.word;
38362306a36Sopenharmony_ci					u32 x;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci					x = ipad[i] ^ ipad[i + 4];
38662306a36Sopenharmony_ci					cache[i] ^= swab32(x);
38762306a36Sopenharmony_ci				}
38862306a36Sopenharmony_ci			}
38962306a36Sopenharmony_ci			cache_len = AES_BLOCK_SIZE;
39062306a36Sopenharmony_ci			queued = queued + extra;
39162306a36Sopenharmony_ci		}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci		/* XCBC continue: XOR previous result into 1st word */
39462306a36Sopenharmony_ci		crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE);
39562306a36Sopenharmony_ci	}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	len = queued;
39862306a36Sopenharmony_ci	/* Add a command descriptor for the cached data, if any */
39962306a36Sopenharmony_ci	if (cache_len) {
40062306a36Sopenharmony_ci		req->cache_dma = dma_map_single(priv->dev, req->cache,
40162306a36Sopenharmony_ci						cache_len, DMA_TO_DEVICE);
40262306a36Sopenharmony_ci		if (dma_mapping_error(priv->dev, req->cache_dma))
40362306a36Sopenharmony_ci			return -EINVAL;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci		req->cache_sz = cache_len;
40662306a36Sopenharmony_ci		first_cdesc = safexcel_add_cdesc(priv, ring, 1,
40762306a36Sopenharmony_ci						 (cache_len == len),
40862306a36Sopenharmony_ci						 req->cache_dma, cache_len,
40962306a36Sopenharmony_ci						 len, ctx->base.ctxr_dma,
41062306a36Sopenharmony_ci						 &dmmy);
41162306a36Sopenharmony_ci		if (IS_ERR(first_cdesc)) {
41262306a36Sopenharmony_ci			ret = PTR_ERR(first_cdesc);
41362306a36Sopenharmony_ci			goto unmap_cache;
41462306a36Sopenharmony_ci		}
41562306a36Sopenharmony_ci		n_cdesc++;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci		queued -= cache_len;
41862306a36Sopenharmony_ci		if (!queued)
41962306a36Sopenharmony_ci			goto send_command;
42062306a36Sopenharmony_ci	}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	/* Now handle the current ahash request buffer(s) */
42362306a36Sopenharmony_ci	req->nents = dma_map_sg(priv->dev, areq->src,
42462306a36Sopenharmony_ci				sg_nents_for_len(areq->src,
42562306a36Sopenharmony_ci						 areq->nbytes),
42662306a36Sopenharmony_ci				DMA_TO_DEVICE);
42762306a36Sopenharmony_ci	if (!req->nents) {
42862306a36Sopenharmony_ci		ret = -ENOMEM;
42962306a36Sopenharmony_ci		goto cdesc_rollback;
43062306a36Sopenharmony_ci	}
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	for_each_sg(areq->src, sg, req->nents, i) {
43362306a36Sopenharmony_ci		int sglen = sg_dma_len(sg);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci		if (unlikely(sglen <= skip)) {
43662306a36Sopenharmony_ci			skip -= sglen;
43762306a36Sopenharmony_ci			continue;
43862306a36Sopenharmony_ci		}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci		/* Do not overflow the request */
44162306a36Sopenharmony_ci		if ((queued + skip) <= sglen)
44262306a36Sopenharmony_ci			sglen = queued;
44362306a36Sopenharmony_ci		else
44462306a36Sopenharmony_ci			sglen -= skip;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
44762306a36Sopenharmony_ci					   !(queued - sglen),
44862306a36Sopenharmony_ci					   sg_dma_address(sg) + skip, sglen,
44962306a36Sopenharmony_ci					   len, ctx->base.ctxr_dma, &dmmy);
45062306a36Sopenharmony_ci		if (IS_ERR(cdesc)) {
45162306a36Sopenharmony_ci			ret = PTR_ERR(cdesc);
45262306a36Sopenharmony_ci			goto unmap_sg;
45362306a36Sopenharmony_ci		}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci		if (!n_cdesc)
45662306a36Sopenharmony_ci			first_cdesc = cdesc;
45762306a36Sopenharmony_ci		n_cdesc++;
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci		queued -= sglen;
46062306a36Sopenharmony_ci		if (!queued)
46162306a36Sopenharmony_ci			break;
46262306a36Sopenharmony_ci		skip = 0;
46362306a36Sopenharmony_ci	}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_cisend_command:
46662306a36Sopenharmony_ci	/* Setup the context options */
46762306a36Sopenharmony_ci	safexcel_context_control(ctx, req, first_cdesc);
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	/* Add the token */
47062306a36Sopenharmony_ci	safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz,
47362306a36Sopenharmony_ci					 DMA_FROM_DEVICE);
47462306a36Sopenharmony_ci	if (dma_mapping_error(priv->dev, req->result_dma)) {
47562306a36Sopenharmony_ci		ret = -EINVAL;
47662306a36Sopenharmony_ci		goto unmap_sg;
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	/* Add a result descriptor */
48062306a36Sopenharmony_ci	rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma,
48162306a36Sopenharmony_ci				   req->digest_sz);
48262306a36Sopenharmony_ci	if (IS_ERR(rdesc)) {
48362306a36Sopenharmony_ci		ret = PTR_ERR(rdesc);
48462306a36Sopenharmony_ci		goto unmap_result;
48562306a36Sopenharmony_ci	}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	safexcel_rdr_req_set(priv, ring, rdesc, &areq->base);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	req->processed += len - extra;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	*commands = n_cdesc;
49262306a36Sopenharmony_ci	*results = 1;
49362306a36Sopenharmony_ci	return 0;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ciunmap_result:
49662306a36Sopenharmony_ci	dma_unmap_single(priv->dev, req->result_dma, req->digest_sz,
49762306a36Sopenharmony_ci			 DMA_FROM_DEVICE);
49862306a36Sopenharmony_ciunmap_sg:
49962306a36Sopenharmony_ci	if (req->nents) {
50062306a36Sopenharmony_ci		dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE);
50162306a36Sopenharmony_ci		req->nents = 0;
50262306a36Sopenharmony_ci	}
50362306a36Sopenharmony_cicdesc_rollback:
50462306a36Sopenharmony_ci	for (i = 0; i < n_cdesc; i++)
50562306a36Sopenharmony_ci		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
50662306a36Sopenharmony_ciunmap_cache:
50762306a36Sopenharmony_ci	if (req->cache_dma) {
50862306a36Sopenharmony_ci		dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz,
50962306a36Sopenharmony_ci				 DMA_TO_DEVICE);
51062306a36Sopenharmony_ci		req->cache_dma = 0;
51162306a36Sopenharmony_ci		req->cache_sz = 0;
51262306a36Sopenharmony_ci	}
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	return ret;
51562306a36Sopenharmony_ci}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_cistatic int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
51862306a36Sopenharmony_ci				      int ring,
51962306a36Sopenharmony_ci				      struct crypto_async_request *async,
52062306a36Sopenharmony_ci				      bool *should_complete, int *ret)
52162306a36Sopenharmony_ci{
52262306a36Sopenharmony_ci	struct safexcel_result_desc *rdesc;
52362306a36Sopenharmony_ci	struct ahash_request *areq = ahash_request_cast(async);
52462306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
52562306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash);
52662306a36Sopenharmony_ci	int enq_ret;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	*ret = 0;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
53162306a36Sopenharmony_ci	if (IS_ERR(rdesc)) {
53262306a36Sopenharmony_ci		dev_err(priv->dev,
53362306a36Sopenharmony_ci			"hash: invalidate: could not retrieve the result descriptor\n");
53462306a36Sopenharmony_ci		*ret = PTR_ERR(rdesc);
53562306a36Sopenharmony_ci	} else {
53662306a36Sopenharmony_ci		*ret = safexcel_rdesc_check_errors(priv, rdesc);
53762306a36Sopenharmony_ci	}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	safexcel_complete(priv, ring);
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	if (ctx->base.exit_inv) {
54262306a36Sopenharmony_ci		dma_pool_free(priv->context_pool, ctx->base.ctxr,
54362306a36Sopenharmony_ci			      ctx->base.ctxr_dma);
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci		*should_complete = true;
54662306a36Sopenharmony_ci		return 1;
54762306a36Sopenharmony_ci	}
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	ring = safexcel_select_ring(priv);
55062306a36Sopenharmony_ci	ctx->base.ring = ring;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	spin_lock_bh(&priv->ring[ring].queue_lock);
55362306a36Sopenharmony_ci	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async);
55462306a36Sopenharmony_ci	spin_unlock_bh(&priv->ring[ring].queue_lock);
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	if (enq_ret != -EINPROGRESS)
55762306a36Sopenharmony_ci		*ret = enq_ret;
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	queue_work(priv->ring[ring].workqueue,
56062306a36Sopenharmony_ci		   &priv->ring[ring].work_data.work);
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	*should_complete = false;
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	return 1;
56562306a36Sopenharmony_ci}
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_cistatic int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring,
56862306a36Sopenharmony_ci				  struct crypto_async_request *async,
56962306a36Sopenharmony_ci				  bool *should_complete, int *ret)
57062306a36Sopenharmony_ci{
57162306a36Sopenharmony_ci	struct ahash_request *areq = ahash_request_cast(async);
57262306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
57362306a36Sopenharmony_ci	int err;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv);
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	if (req->needs_inv) {
57862306a36Sopenharmony_ci		req->needs_inv = false;
57962306a36Sopenharmony_ci		err = safexcel_handle_inv_result(priv, ring, async,
58062306a36Sopenharmony_ci						 should_complete, ret);
58162306a36Sopenharmony_ci	} else {
58262306a36Sopenharmony_ci		err = safexcel_handle_req_result(priv, ring, async,
58362306a36Sopenharmony_ci						 should_complete, ret);
58462306a36Sopenharmony_ci	}
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	return err;
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_cistatic int safexcel_ahash_send_inv(struct crypto_async_request *async,
59062306a36Sopenharmony_ci				   int ring, int *commands, int *results)
59162306a36Sopenharmony_ci{
59262306a36Sopenharmony_ci	struct ahash_request *areq = ahash_request_cast(async);
59362306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
59462306a36Sopenharmony_ci	int ret;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	ret = safexcel_invalidate_cache(async, ctx->base.priv,
59762306a36Sopenharmony_ci					ctx->base.ctxr_dma, ring);
59862306a36Sopenharmony_ci	if (unlikely(ret))
59962306a36Sopenharmony_ci		return ret;
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	*commands = 1;
60262306a36Sopenharmony_ci	*results = 1;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	return 0;
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_cistatic int safexcel_ahash_send(struct crypto_async_request *async,
60862306a36Sopenharmony_ci			       int ring, int *commands, int *results)
60962306a36Sopenharmony_ci{
61062306a36Sopenharmony_ci	struct ahash_request *areq = ahash_request_cast(async);
61162306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
61262306a36Sopenharmony_ci	int ret;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	if (req->needs_inv)
61562306a36Sopenharmony_ci		ret = safexcel_ahash_send_inv(async, ring, commands, results);
61662306a36Sopenharmony_ci	else
61762306a36Sopenharmony_ci		ret = safexcel_ahash_send_req(async, ring, commands, results);
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	return ret;
62062306a36Sopenharmony_ci}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_cistatic int safexcel_ahash_exit_inv(struct crypto_tfm *tfm)
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
62562306a36Sopenharmony_ci	struct safexcel_crypto_priv *priv = ctx->base.priv;
62662306a36Sopenharmony_ci	EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE);
62762306a36Sopenharmony_ci	struct safexcel_ahash_req *rctx = ahash_request_ctx_dma(req);
62862306a36Sopenharmony_ci	DECLARE_CRYPTO_WAIT(result);
62962306a36Sopenharmony_ci	int ring = ctx->base.ring;
63062306a36Sopenharmony_ci	int err;
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	memset(req, 0, EIP197_AHASH_REQ_SIZE);
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	/* create invalidation request */
63562306a36Sopenharmony_ci	init_completion(&result.completion);
63662306a36Sopenharmony_ci	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
63762306a36Sopenharmony_ci				   crypto_req_done, &result);
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	ahash_request_set_tfm(req, __crypto_ahash_cast(tfm));
64062306a36Sopenharmony_ci	ctx = crypto_tfm_ctx(req->base.tfm);
64162306a36Sopenharmony_ci	ctx->base.exit_inv = true;
64262306a36Sopenharmony_ci	rctx->needs_inv = true;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	spin_lock_bh(&priv->ring[ring].queue_lock);
64562306a36Sopenharmony_ci	crypto_enqueue_request(&priv->ring[ring].queue, &req->base);
64662306a36Sopenharmony_ci	spin_unlock_bh(&priv->ring[ring].queue_lock);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	queue_work(priv->ring[ring].workqueue,
64962306a36Sopenharmony_ci		   &priv->ring[ring].work_data.work);
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	err = crypto_wait_req(-EINPROGRESS, &result);
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	if (err) {
65462306a36Sopenharmony_ci		dev_warn(priv->dev, "hash: completion error (%d)\n", err);
65562306a36Sopenharmony_ci		return err;
65662306a36Sopenharmony_ci	}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	return 0;
65962306a36Sopenharmony_ci}
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci/* safexcel_ahash_cache: cache data until at least one request can be sent to
66262306a36Sopenharmony_ci * the engine, aka. when there is at least 1 block size in the pipe.
66362306a36Sopenharmony_ci */
66462306a36Sopenharmony_cistatic int safexcel_ahash_cache(struct ahash_request *areq)
66562306a36Sopenharmony_ci{
66662306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
66762306a36Sopenharmony_ci	u64 cache_len;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	/* cache_len: everything accepted by the driver but not sent yet,
67062306a36Sopenharmony_ci	 * tot sz handled by update() - last req sz - tot sz handled by send()
67162306a36Sopenharmony_ci	 */
67262306a36Sopenharmony_ci	cache_len = safexcel_queued_len(req);
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	/*
67562306a36Sopenharmony_ci	 * In case there isn't enough bytes to proceed (less than a
67662306a36Sopenharmony_ci	 * block size), cache the data until we have enough.
67762306a36Sopenharmony_ci	 */
67862306a36Sopenharmony_ci	if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) {
67962306a36Sopenharmony_ci		sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
68062306a36Sopenharmony_ci				   req->cache + cache_len,
68162306a36Sopenharmony_ci				   areq->nbytes, 0);
68262306a36Sopenharmony_ci		return 0;
68362306a36Sopenharmony_ci	}
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	/* We couldn't cache all the data */
68662306a36Sopenharmony_ci	return -E2BIG;
68762306a36Sopenharmony_ci}
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_cistatic int safexcel_ahash_enqueue(struct ahash_request *areq)
69062306a36Sopenharmony_ci{
69162306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
69262306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
69362306a36Sopenharmony_ci	struct safexcel_crypto_priv *priv = ctx->base.priv;
69462306a36Sopenharmony_ci	int ret, ring;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	req->needs_inv = false;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	if (ctx->base.ctxr) {
69962306a36Sopenharmony_ci		if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv &&
70062306a36Sopenharmony_ci		     /* invalidate for *any* non-XCBC continuation */
70162306a36Sopenharmony_ci		   ((req->not_first && !req->xcbcmac) ||
70262306a36Sopenharmony_ci		     /* invalidate if (i)digest changed */
70362306a36Sopenharmony_ci		     memcmp(ctx->base.ctxr->data, req->state, req->state_sz) ||
70462306a36Sopenharmony_ci		     /* invalidate for HMAC finish with odigest changed */
70562306a36Sopenharmony_ci		     (req->finish && req->hmac &&
70662306a36Sopenharmony_ci		      memcmp(ctx->base.ctxr->data + (req->state_sz>>2),
70762306a36Sopenharmony_ci			     &ctx->base.opad, req->state_sz))))
70862306a36Sopenharmony_ci			/*
70962306a36Sopenharmony_ci			 * We're still setting needs_inv here, even though it is
71062306a36Sopenharmony_ci			 * cleared right away, because the needs_inv flag can be
71162306a36Sopenharmony_ci			 * set in other functions and we want to keep the same
71262306a36Sopenharmony_ci			 * logic.
71362306a36Sopenharmony_ci			 */
71462306a36Sopenharmony_ci			ctx->base.needs_inv = true;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci		if (ctx->base.needs_inv) {
71762306a36Sopenharmony_ci			ctx->base.needs_inv = false;
71862306a36Sopenharmony_ci			req->needs_inv = true;
71962306a36Sopenharmony_ci		}
72062306a36Sopenharmony_ci	} else {
72162306a36Sopenharmony_ci		ctx->base.ring = safexcel_select_ring(priv);
72262306a36Sopenharmony_ci		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
72362306a36Sopenharmony_ci						 EIP197_GFP_FLAGS(areq->base),
72462306a36Sopenharmony_ci						 &ctx->base.ctxr_dma);
72562306a36Sopenharmony_ci		if (!ctx->base.ctxr)
72662306a36Sopenharmony_ci			return -ENOMEM;
72762306a36Sopenharmony_ci	}
72862306a36Sopenharmony_ci	req->not_first = true;
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	ring = ctx->base.ring;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	spin_lock_bh(&priv->ring[ring].queue_lock);
73362306a36Sopenharmony_ci	ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base);
73462306a36Sopenharmony_ci	spin_unlock_bh(&priv->ring[ring].queue_lock);
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	queue_work(priv->ring[ring].workqueue,
73762306a36Sopenharmony_ci		   &priv->ring[ring].work_data.work);
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	return ret;
74062306a36Sopenharmony_ci}
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_cistatic int safexcel_ahash_update(struct ahash_request *areq)
74362306a36Sopenharmony_ci{
74462306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
74562306a36Sopenharmony_ci	int ret;
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	/* If the request is 0 length, do nothing */
74862306a36Sopenharmony_ci	if (!areq->nbytes)
74962306a36Sopenharmony_ci		return 0;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	/* Add request to the cache if it fits */
75262306a36Sopenharmony_ci	ret = safexcel_ahash_cache(areq);
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	/* Update total request length */
75562306a36Sopenharmony_ci	req->len += areq->nbytes;
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	/* If not all data could fit into the cache, go process the excess.
75862306a36Sopenharmony_ci	 * Also go process immediately for an HMAC IV precompute, which
75962306a36Sopenharmony_ci	 * will never be finished at all, but needs to be processed anyway.
76062306a36Sopenharmony_ci	 */
76162306a36Sopenharmony_ci	if ((ret && !req->finish) || req->last_req)
76262306a36Sopenharmony_ci		return safexcel_ahash_enqueue(areq);
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	return 0;
76562306a36Sopenharmony_ci}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_cistatic int safexcel_ahash_final(struct ahash_request *areq)
76862306a36Sopenharmony_ci{
76962306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
77062306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	req->finish = true;
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	if (unlikely(!req->len && !areq->nbytes)) {
77562306a36Sopenharmony_ci		/*
77662306a36Sopenharmony_ci		 * If we have an overall 0 length *hash* request:
77762306a36Sopenharmony_ci		 * The HW cannot do 0 length hash, so we provide the correct
77862306a36Sopenharmony_ci		 * result directly here.
77962306a36Sopenharmony_ci		 */
78062306a36Sopenharmony_ci		if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5)
78162306a36Sopenharmony_ci			memcpy(areq->result, md5_zero_message_hash,
78262306a36Sopenharmony_ci			       MD5_DIGEST_SIZE);
78362306a36Sopenharmony_ci		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1)
78462306a36Sopenharmony_ci			memcpy(areq->result, sha1_zero_message_hash,
78562306a36Sopenharmony_ci			       SHA1_DIGEST_SIZE);
78662306a36Sopenharmony_ci		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224)
78762306a36Sopenharmony_ci			memcpy(areq->result, sha224_zero_message_hash,
78862306a36Sopenharmony_ci			       SHA224_DIGEST_SIZE);
78962306a36Sopenharmony_ci		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256)
79062306a36Sopenharmony_ci			memcpy(areq->result, sha256_zero_message_hash,
79162306a36Sopenharmony_ci			       SHA256_DIGEST_SIZE);
79262306a36Sopenharmony_ci		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384)
79362306a36Sopenharmony_ci			memcpy(areq->result, sha384_zero_message_hash,
79462306a36Sopenharmony_ci			       SHA384_DIGEST_SIZE);
79562306a36Sopenharmony_ci		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512)
79662306a36Sopenharmony_ci			memcpy(areq->result, sha512_zero_message_hash,
79762306a36Sopenharmony_ci			       SHA512_DIGEST_SIZE);
79862306a36Sopenharmony_ci		else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) {
79962306a36Sopenharmony_ci			memcpy(areq->result,
80062306a36Sopenharmony_ci			       EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE);
80162306a36Sopenharmony_ci		}
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci		return 0;
80462306a36Sopenharmony_ci	} else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM &&
80562306a36Sopenharmony_ci			    ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 &&
80662306a36Sopenharmony_ci			    req->len == sizeof(u32) && !areq->nbytes)) {
80762306a36Sopenharmony_ci		/* Zero length CRC32 */
80862306a36Sopenharmony_ci		memcpy(areq->result, &ctx->base.ipad, sizeof(u32));
80962306a36Sopenharmony_ci		return 0;
81062306a36Sopenharmony_ci	} else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE &&
81162306a36Sopenharmony_ci			    !areq->nbytes)) {
81262306a36Sopenharmony_ci		/* Zero length CBC MAC */
81362306a36Sopenharmony_ci		memset(areq->result, 0, AES_BLOCK_SIZE);
81462306a36Sopenharmony_ci		return 0;
81562306a36Sopenharmony_ci	} else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE &&
81662306a36Sopenharmony_ci			    !areq->nbytes)) {
81762306a36Sopenharmony_ci		/* Zero length (X)CBC/CMAC */
81862306a36Sopenharmony_ci		int i;
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) {
82162306a36Sopenharmony_ci			u32 *result = (void *)areq->result;
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci			/* K3 */
82462306a36Sopenharmony_ci			result[i] = swab32(ctx->base.ipad.word[i + 4]);
82562306a36Sopenharmony_ci		}
82662306a36Sopenharmony_ci		areq->result[0] ^= 0x80;			// 10- padding
82762306a36Sopenharmony_ci		aes_encrypt(ctx->aes, areq->result, areq->result);
82862306a36Sopenharmony_ci		return 0;
82962306a36Sopenharmony_ci	} else if (unlikely(req->hmac &&
83062306a36Sopenharmony_ci			    (req->len == req->block_sz) &&
83162306a36Sopenharmony_ci			    !areq->nbytes)) {
83262306a36Sopenharmony_ci		/*
83362306a36Sopenharmony_ci		 * If we have an overall 0 length *HMAC* request:
83462306a36Sopenharmony_ci		 * For HMAC, we need to finalize the inner digest
83562306a36Sopenharmony_ci		 * and then perform the outer hash.
83662306a36Sopenharmony_ci		 */
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci		/* generate pad block in the cache */
83962306a36Sopenharmony_ci		/* start with a hash block of all zeroes */
84062306a36Sopenharmony_ci		memset(req->cache, 0, req->block_sz);
84162306a36Sopenharmony_ci		/* set the first byte to 0x80 to 'append a 1 bit' */
84262306a36Sopenharmony_ci		req->cache[0] = 0x80;
84362306a36Sopenharmony_ci		/* add the length in bits in the last 2 bytes */
84462306a36Sopenharmony_ci		if (req->len_is_le) {
84562306a36Sopenharmony_ci			/* Little endian length word (e.g. MD5) */
84662306a36Sopenharmony_ci			req->cache[req->block_sz-8] = (req->block_sz << 3) &
84762306a36Sopenharmony_ci						      255;
84862306a36Sopenharmony_ci			req->cache[req->block_sz-7] = (req->block_sz >> 5);
84962306a36Sopenharmony_ci		} else {
85062306a36Sopenharmony_ci			/* Big endian length word (e.g. any SHA) */
85162306a36Sopenharmony_ci			req->cache[req->block_sz-2] = (req->block_sz >> 5);
85262306a36Sopenharmony_ci			req->cache[req->block_sz-1] = (req->block_sz << 3) &
85362306a36Sopenharmony_ci						      255;
85462306a36Sopenharmony_ci		}
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci		req->len += req->block_sz; /* plus 1 hash block */
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci		/* Set special zero-length HMAC flag */
85962306a36Sopenharmony_ci		req->hmac_zlen = true;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci		/* Finalize HMAC */
86262306a36Sopenharmony_ci		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
86362306a36Sopenharmony_ci	} else if (req->hmac) {
86462306a36Sopenharmony_ci		/* Finalize HMAC */
86562306a36Sopenharmony_ci		req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
86662306a36Sopenharmony_ci	}
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	return safexcel_ahash_enqueue(areq);
86962306a36Sopenharmony_ci}
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_cistatic int safexcel_ahash_finup(struct ahash_request *areq)
87262306a36Sopenharmony_ci{
87362306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	req->finish = true;
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	safexcel_ahash_update(areq);
87862306a36Sopenharmony_ci	return safexcel_ahash_final(areq);
87962306a36Sopenharmony_ci}
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_cistatic int safexcel_ahash_export(struct ahash_request *areq, void *out)
88262306a36Sopenharmony_ci{
88362306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
88462306a36Sopenharmony_ci	struct safexcel_ahash_export_state *export = out;
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	export->len = req->len;
88762306a36Sopenharmony_ci	export->processed = req->processed;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	export->digest = req->digest;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	memcpy(export->state, req->state, req->state_sz);
89262306a36Sopenharmony_ci	memcpy(export->cache, req->cache, HASH_CACHE_SIZE);
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	return 0;
89562306a36Sopenharmony_ci}
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_cistatic int safexcel_ahash_import(struct ahash_request *areq, const void *in)
89862306a36Sopenharmony_ci{
89962306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
90062306a36Sopenharmony_ci	const struct safexcel_ahash_export_state *export = in;
90162306a36Sopenharmony_ci	int ret;
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	ret = crypto_ahash_init(areq);
90462306a36Sopenharmony_ci	if (ret)
90562306a36Sopenharmony_ci		return ret;
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	req->len = export->len;
90862306a36Sopenharmony_ci	req->processed = export->processed;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	req->digest = export->digest;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	memcpy(req->cache, export->cache, HASH_CACHE_SIZE);
91362306a36Sopenharmony_ci	memcpy(req->state, export->state, req->state_sz);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	return 0;
91662306a36Sopenharmony_ci}
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_cistatic int safexcel_ahash_cra_init(struct crypto_tfm *tfm)
91962306a36Sopenharmony_ci{
92062306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
92162306a36Sopenharmony_ci	struct safexcel_alg_template *tmpl =
92262306a36Sopenharmony_ci		container_of(__crypto_ahash_alg(tfm->__crt_alg),
92362306a36Sopenharmony_ci			     struct safexcel_alg_template, alg.ahash);
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	ctx->base.priv = tmpl->priv;
92662306a36Sopenharmony_ci	ctx->base.send = safexcel_ahash_send;
92762306a36Sopenharmony_ci	ctx->base.handle_result = safexcel_handle_result;
92862306a36Sopenharmony_ci	ctx->fb_do_setkey = false;
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	crypto_ahash_set_reqsize_dma(__crypto_ahash_cast(tfm),
93162306a36Sopenharmony_ci				     sizeof(struct safexcel_ahash_req));
93262306a36Sopenharmony_ci	return 0;
93362306a36Sopenharmony_ci}
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_cistatic int safexcel_sha1_init(struct ahash_request *areq)
93662306a36Sopenharmony_ci{
93762306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
93862306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
94362306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
94462306a36Sopenharmony_ci	req->state_sz = SHA1_DIGEST_SIZE;
94562306a36Sopenharmony_ci	req->digest_sz = SHA1_DIGEST_SIZE;
94662306a36Sopenharmony_ci	req->block_sz = SHA1_BLOCK_SIZE;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	return 0;
94962306a36Sopenharmony_ci}
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_cistatic int safexcel_sha1_digest(struct ahash_request *areq)
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	int ret = safexcel_sha1_init(areq);
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci	if (ret)
95662306a36Sopenharmony_ci		return ret;
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
95962306a36Sopenharmony_ci}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_cistatic void safexcel_ahash_cra_exit(struct crypto_tfm *tfm)
96262306a36Sopenharmony_ci{
96362306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
96462306a36Sopenharmony_ci	struct safexcel_crypto_priv *priv = ctx->base.priv;
96562306a36Sopenharmony_ci	int ret;
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci	/* context not allocated, skip invalidation */
96862306a36Sopenharmony_ci	if (!ctx->base.ctxr)
96962306a36Sopenharmony_ci		return;
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	if (priv->flags & EIP197_TRC_CACHE) {
97262306a36Sopenharmony_ci		ret = safexcel_ahash_exit_inv(tfm);
97362306a36Sopenharmony_ci		if (ret)
97462306a36Sopenharmony_ci			dev_warn(priv->dev, "hash: invalidation error %d\n", ret);
97562306a36Sopenharmony_ci	} else {
97662306a36Sopenharmony_ci		dma_pool_free(priv->context_pool, ctx->base.ctxr,
97762306a36Sopenharmony_ci			      ctx->base.ctxr_dma);
97862306a36Sopenharmony_ci	}
97962306a36Sopenharmony_ci}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha1 = {
98262306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
98362306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA1,
98462306a36Sopenharmony_ci	.alg.ahash = {
98562306a36Sopenharmony_ci		.init = safexcel_sha1_init,
98662306a36Sopenharmony_ci		.update = safexcel_ahash_update,
98762306a36Sopenharmony_ci		.final = safexcel_ahash_final,
98862306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
98962306a36Sopenharmony_ci		.digest = safexcel_sha1_digest,
99062306a36Sopenharmony_ci		.export = safexcel_ahash_export,
99162306a36Sopenharmony_ci		.import = safexcel_ahash_import,
99262306a36Sopenharmony_ci		.halg = {
99362306a36Sopenharmony_ci			.digestsize = SHA1_DIGEST_SIZE,
99462306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
99562306a36Sopenharmony_ci			.base = {
99662306a36Sopenharmony_ci				.cra_name = "sha1",
99762306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sha1",
99862306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
99962306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
100062306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
100162306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
100262306a36Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
100362306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
100462306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
100562306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
100662306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
100762306a36Sopenharmony_ci			},
100862306a36Sopenharmony_ci		},
100962306a36Sopenharmony_ci	},
101062306a36Sopenharmony_ci};
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_cistatic int safexcel_hmac_sha1_init(struct ahash_request *areq)
101362306a36Sopenharmony_ci{
101462306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
101562306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	/* Start from ipad precompute */
102062306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SHA1_DIGEST_SIZE);
102162306a36Sopenharmony_ci	/* Already processed the key^ipad part now! */
102262306a36Sopenharmony_ci	req->len	= SHA1_BLOCK_SIZE;
102362306a36Sopenharmony_ci	req->processed	= SHA1_BLOCK_SIZE;
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
102662306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
102762306a36Sopenharmony_ci	req->state_sz = SHA1_DIGEST_SIZE;
102862306a36Sopenharmony_ci	req->digest_sz = SHA1_DIGEST_SIZE;
102962306a36Sopenharmony_ci	req->block_sz = SHA1_BLOCK_SIZE;
103062306a36Sopenharmony_ci	req->hmac = true;
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	return 0;
103362306a36Sopenharmony_ci}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_cistatic int safexcel_hmac_sha1_digest(struct ahash_request *areq)
103662306a36Sopenharmony_ci{
103762306a36Sopenharmony_ci	int ret = safexcel_hmac_sha1_init(areq);
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	if (ret)
104062306a36Sopenharmony_ci		return ret;
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
104362306a36Sopenharmony_ci}
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_cistatic int safexcel_hmac_init_pad(struct ahash_request *areq,
104662306a36Sopenharmony_ci				  unsigned int blocksize, const u8 *key,
104762306a36Sopenharmony_ci				  unsigned int keylen, u8 *ipad, u8 *opad)
104862306a36Sopenharmony_ci{
104962306a36Sopenharmony_ci	DECLARE_CRYPTO_WAIT(result);
105062306a36Sopenharmony_ci	struct scatterlist sg;
105162306a36Sopenharmony_ci	int ret, i;
105262306a36Sopenharmony_ci	u8 *keydup;
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	if (keylen <= blocksize) {
105562306a36Sopenharmony_ci		memcpy(ipad, key, keylen);
105662306a36Sopenharmony_ci	} else {
105762306a36Sopenharmony_ci		keydup = kmemdup(key, keylen, GFP_KERNEL);
105862306a36Sopenharmony_ci		if (!keydup)
105962306a36Sopenharmony_ci			return -ENOMEM;
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci		ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
106262306a36Sopenharmony_ci					   crypto_req_done, &result);
106362306a36Sopenharmony_ci		sg_init_one(&sg, keydup, keylen);
106462306a36Sopenharmony_ci		ahash_request_set_crypt(areq, &sg, ipad, keylen);
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci		ret = crypto_ahash_digest(areq);
106762306a36Sopenharmony_ci		ret = crypto_wait_req(ret, &result);
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci		/* Avoid leaking */
107062306a36Sopenharmony_ci		kfree_sensitive(keydup);
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci		if (ret)
107362306a36Sopenharmony_ci			return ret;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci		keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq));
107662306a36Sopenharmony_ci	}
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	memset(ipad + keylen, 0, blocksize - keylen);
107962306a36Sopenharmony_ci	memcpy(opad, ipad, blocksize);
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	for (i = 0; i < blocksize; i++) {
108262306a36Sopenharmony_ci		ipad[i] ^= HMAC_IPAD_VALUE;
108362306a36Sopenharmony_ci		opad[i] ^= HMAC_OPAD_VALUE;
108462306a36Sopenharmony_ci	}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	return 0;
108762306a36Sopenharmony_ci}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_cistatic int safexcel_hmac_init_iv(struct ahash_request *areq,
109062306a36Sopenharmony_ci				 unsigned int blocksize, u8 *pad, void *state)
109162306a36Sopenharmony_ci{
109262306a36Sopenharmony_ci	struct safexcel_ahash_req *req;
109362306a36Sopenharmony_ci	DECLARE_CRYPTO_WAIT(result);
109462306a36Sopenharmony_ci	struct scatterlist sg;
109562306a36Sopenharmony_ci	int ret;
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG,
109862306a36Sopenharmony_ci				   crypto_req_done, &result);
109962306a36Sopenharmony_ci	sg_init_one(&sg, pad, blocksize);
110062306a36Sopenharmony_ci	ahash_request_set_crypt(areq, &sg, pad, blocksize);
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	ret = crypto_ahash_init(areq);
110362306a36Sopenharmony_ci	if (ret)
110462306a36Sopenharmony_ci		return ret;
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	req = ahash_request_ctx_dma(areq);
110762306a36Sopenharmony_ci	req->hmac = true;
110862306a36Sopenharmony_ci	req->last_req = true;
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	ret = crypto_ahash_update(areq);
111162306a36Sopenharmony_ci	ret = crypto_wait_req(ret, &result);
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	return ret ?: crypto_ahash_export(areq, state);
111462306a36Sopenharmony_ci}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_cistatic int __safexcel_hmac_setkey(const char *alg, const u8 *key,
111762306a36Sopenharmony_ci				  unsigned int keylen,
111862306a36Sopenharmony_ci				  void *istate, void *ostate)
111962306a36Sopenharmony_ci{
112062306a36Sopenharmony_ci	struct ahash_request *areq;
112162306a36Sopenharmony_ci	struct crypto_ahash *tfm;
112262306a36Sopenharmony_ci	unsigned int blocksize;
112362306a36Sopenharmony_ci	u8 *ipad, *opad;
112462306a36Sopenharmony_ci	int ret;
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	tfm = crypto_alloc_ahash(alg, 0, 0);
112762306a36Sopenharmony_ci	if (IS_ERR(tfm))
112862306a36Sopenharmony_ci		return PTR_ERR(tfm);
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	areq = ahash_request_alloc(tfm, GFP_KERNEL);
113162306a36Sopenharmony_ci	if (!areq) {
113262306a36Sopenharmony_ci		ret = -ENOMEM;
113362306a36Sopenharmony_ci		goto free_ahash;
113462306a36Sopenharmony_ci	}
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	crypto_ahash_clear_flags(tfm, ~0);
113762306a36Sopenharmony_ci	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	ipad = kcalloc(2, blocksize, GFP_KERNEL);
114062306a36Sopenharmony_ci	if (!ipad) {
114162306a36Sopenharmony_ci		ret = -ENOMEM;
114262306a36Sopenharmony_ci		goto free_request;
114362306a36Sopenharmony_ci	}
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	opad = ipad + blocksize;
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad);
114862306a36Sopenharmony_ci	if (ret)
114962306a36Sopenharmony_ci		goto free_ipad;
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate);
115262306a36Sopenharmony_ci	if (ret)
115362306a36Sopenharmony_ci		goto free_ipad;
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate);
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_cifree_ipad:
115862306a36Sopenharmony_ci	kfree(ipad);
115962306a36Sopenharmony_cifree_request:
116062306a36Sopenharmony_ci	ahash_request_free(areq);
116162306a36Sopenharmony_cifree_ahash:
116262306a36Sopenharmony_ci	crypto_free_ahash(tfm);
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	return ret;
116562306a36Sopenharmony_ci}
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ciint safexcel_hmac_setkey(struct safexcel_context *base, const u8 *key,
116862306a36Sopenharmony_ci			 unsigned int keylen, const char *alg,
116962306a36Sopenharmony_ci			 unsigned int state_sz)
117062306a36Sopenharmony_ci{
117162306a36Sopenharmony_ci	struct safexcel_crypto_priv *priv = base->priv;
117262306a36Sopenharmony_ci	struct safexcel_ahash_export_state istate, ostate;
117362306a36Sopenharmony_ci	int ret;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	ret = __safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate);
117662306a36Sopenharmony_ci	if (ret)
117762306a36Sopenharmony_ci		return ret;
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	if (priv->flags & EIP197_TRC_CACHE && base->ctxr &&
118062306a36Sopenharmony_ci	    (memcmp(&base->ipad, istate.state, state_sz) ||
118162306a36Sopenharmony_ci	     memcmp(&base->opad, ostate.state, state_sz)))
118262306a36Sopenharmony_ci		base->needs_inv = true;
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	memcpy(&base->ipad, &istate.state, state_sz);
118562306a36Sopenharmony_ci	memcpy(&base->opad, &ostate.state, state_sz);
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	return 0;
118862306a36Sopenharmony_ci}
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_cistatic int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key,
119162306a36Sopenharmony_ci				    unsigned int keylen, const char *alg,
119262306a36Sopenharmony_ci				    unsigned int state_sz)
119362306a36Sopenharmony_ci{
119462306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	return safexcel_hmac_setkey(&ctx->base, key, keylen, alg, state_sz);
119762306a36Sopenharmony_ci}
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_cistatic int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
120062306a36Sopenharmony_ci				     unsigned int keylen)
120162306a36Sopenharmony_ci{
120262306a36Sopenharmony_ci	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1",
120362306a36Sopenharmony_ci					SHA1_DIGEST_SIZE);
120462306a36Sopenharmony_ci}
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha1 = {
120762306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
120862306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA1,
120962306a36Sopenharmony_ci	.alg.ahash = {
121062306a36Sopenharmony_ci		.init = safexcel_hmac_sha1_init,
121162306a36Sopenharmony_ci		.update = safexcel_ahash_update,
121262306a36Sopenharmony_ci		.final = safexcel_ahash_final,
121362306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
121462306a36Sopenharmony_ci		.digest = safexcel_hmac_sha1_digest,
121562306a36Sopenharmony_ci		.setkey = safexcel_hmac_sha1_setkey,
121662306a36Sopenharmony_ci		.export = safexcel_ahash_export,
121762306a36Sopenharmony_ci		.import = safexcel_ahash_import,
121862306a36Sopenharmony_ci		.halg = {
121962306a36Sopenharmony_ci			.digestsize = SHA1_DIGEST_SIZE,
122062306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
122162306a36Sopenharmony_ci			.base = {
122262306a36Sopenharmony_ci				.cra_name = "hmac(sha1)",
122362306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sha1",
122462306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
122562306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
122662306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
122762306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
122862306a36Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
122962306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
123062306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
123162306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
123262306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
123362306a36Sopenharmony_ci			},
123462306a36Sopenharmony_ci		},
123562306a36Sopenharmony_ci	},
123662306a36Sopenharmony_ci};
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_cistatic int safexcel_sha256_init(struct ahash_request *areq)
123962306a36Sopenharmony_ci{
124062306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
124162306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
124662306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
124762306a36Sopenharmony_ci	req->state_sz = SHA256_DIGEST_SIZE;
124862306a36Sopenharmony_ci	req->digest_sz = SHA256_DIGEST_SIZE;
124962306a36Sopenharmony_ci	req->block_sz = SHA256_BLOCK_SIZE;
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	return 0;
125262306a36Sopenharmony_ci}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_cistatic int safexcel_sha256_digest(struct ahash_request *areq)
125562306a36Sopenharmony_ci{
125662306a36Sopenharmony_ci	int ret = safexcel_sha256_init(areq);
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	if (ret)
125962306a36Sopenharmony_ci		return ret;
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
126262306a36Sopenharmony_ci}
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha256 = {
126562306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
126662306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA2_256,
126762306a36Sopenharmony_ci	.alg.ahash = {
126862306a36Sopenharmony_ci		.init = safexcel_sha256_init,
126962306a36Sopenharmony_ci		.update = safexcel_ahash_update,
127062306a36Sopenharmony_ci		.final = safexcel_ahash_final,
127162306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
127262306a36Sopenharmony_ci		.digest = safexcel_sha256_digest,
127362306a36Sopenharmony_ci		.export = safexcel_ahash_export,
127462306a36Sopenharmony_ci		.import = safexcel_ahash_import,
127562306a36Sopenharmony_ci		.halg = {
127662306a36Sopenharmony_ci			.digestsize = SHA256_DIGEST_SIZE,
127762306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
127862306a36Sopenharmony_ci			.base = {
127962306a36Sopenharmony_ci				.cra_name = "sha256",
128062306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sha256",
128162306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
128262306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
128362306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
128462306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
128562306a36Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
128662306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
128762306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
128862306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
128962306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
129062306a36Sopenharmony_ci			},
129162306a36Sopenharmony_ci		},
129262306a36Sopenharmony_ci	},
129362306a36Sopenharmony_ci};
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_cistatic int safexcel_sha224_init(struct ahash_request *areq)
129662306a36Sopenharmony_ci{
129762306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
129862306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
130362306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
130462306a36Sopenharmony_ci	req->state_sz = SHA256_DIGEST_SIZE;
130562306a36Sopenharmony_ci	req->digest_sz = SHA256_DIGEST_SIZE;
130662306a36Sopenharmony_ci	req->block_sz = SHA256_BLOCK_SIZE;
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	return 0;
130962306a36Sopenharmony_ci}
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_cistatic int safexcel_sha224_digest(struct ahash_request *areq)
131262306a36Sopenharmony_ci{
131362306a36Sopenharmony_ci	int ret = safexcel_sha224_init(areq);
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci	if (ret)
131662306a36Sopenharmony_ci		return ret;
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
131962306a36Sopenharmony_ci}
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha224 = {
132262306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
132362306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA2_256,
132462306a36Sopenharmony_ci	.alg.ahash = {
132562306a36Sopenharmony_ci		.init = safexcel_sha224_init,
132662306a36Sopenharmony_ci		.update = safexcel_ahash_update,
132762306a36Sopenharmony_ci		.final = safexcel_ahash_final,
132862306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
132962306a36Sopenharmony_ci		.digest = safexcel_sha224_digest,
133062306a36Sopenharmony_ci		.export = safexcel_ahash_export,
133162306a36Sopenharmony_ci		.import = safexcel_ahash_import,
133262306a36Sopenharmony_ci		.halg = {
133362306a36Sopenharmony_ci			.digestsize = SHA224_DIGEST_SIZE,
133462306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
133562306a36Sopenharmony_ci			.base = {
133662306a36Sopenharmony_ci				.cra_name = "sha224",
133762306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sha224",
133862306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
133962306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
134062306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
134162306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
134262306a36Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
134362306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
134462306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
134562306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
134662306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
134762306a36Sopenharmony_ci			},
134862306a36Sopenharmony_ci		},
134962306a36Sopenharmony_ci	},
135062306a36Sopenharmony_ci};
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_cistatic int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key,
135362306a36Sopenharmony_ci				       unsigned int keylen)
135462306a36Sopenharmony_ci{
135562306a36Sopenharmony_ci	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224",
135662306a36Sopenharmony_ci					SHA256_DIGEST_SIZE);
135762306a36Sopenharmony_ci}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_cistatic int safexcel_hmac_sha224_init(struct ahash_request *areq)
136062306a36Sopenharmony_ci{
136162306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
136262306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci	/* Start from ipad precompute */
136762306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE);
136862306a36Sopenharmony_ci	/* Already processed the key^ipad part now! */
136962306a36Sopenharmony_ci	req->len	= SHA256_BLOCK_SIZE;
137062306a36Sopenharmony_ci	req->processed	= SHA256_BLOCK_SIZE;
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
137362306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
137462306a36Sopenharmony_ci	req->state_sz = SHA256_DIGEST_SIZE;
137562306a36Sopenharmony_ci	req->digest_sz = SHA256_DIGEST_SIZE;
137662306a36Sopenharmony_ci	req->block_sz = SHA256_BLOCK_SIZE;
137762306a36Sopenharmony_ci	req->hmac = true;
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci	return 0;
138062306a36Sopenharmony_ci}
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_cistatic int safexcel_hmac_sha224_digest(struct ahash_request *areq)
138362306a36Sopenharmony_ci{
138462306a36Sopenharmony_ci	int ret = safexcel_hmac_sha224_init(areq);
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	if (ret)
138762306a36Sopenharmony_ci		return ret;
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
139062306a36Sopenharmony_ci}
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha224 = {
139362306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
139462306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA2_256,
139562306a36Sopenharmony_ci	.alg.ahash = {
139662306a36Sopenharmony_ci		.init = safexcel_hmac_sha224_init,
139762306a36Sopenharmony_ci		.update = safexcel_ahash_update,
139862306a36Sopenharmony_ci		.final = safexcel_ahash_final,
139962306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
140062306a36Sopenharmony_ci		.digest = safexcel_hmac_sha224_digest,
140162306a36Sopenharmony_ci		.setkey = safexcel_hmac_sha224_setkey,
140262306a36Sopenharmony_ci		.export = safexcel_ahash_export,
140362306a36Sopenharmony_ci		.import = safexcel_ahash_import,
140462306a36Sopenharmony_ci		.halg = {
140562306a36Sopenharmony_ci			.digestsize = SHA224_DIGEST_SIZE,
140662306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
140762306a36Sopenharmony_ci			.base = {
140862306a36Sopenharmony_ci				.cra_name = "hmac(sha224)",
140962306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sha224",
141062306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
141162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
141262306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
141362306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
141462306a36Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
141562306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
141662306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
141762306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
141862306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
141962306a36Sopenharmony_ci			},
142062306a36Sopenharmony_ci		},
142162306a36Sopenharmony_ci	},
142262306a36Sopenharmony_ci};
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_cistatic int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
142562306a36Sopenharmony_ci				     unsigned int keylen)
142662306a36Sopenharmony_ci{
142762306a36Sopenharmony_ci	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256",
142862306a36Sopenharmony_ci					SHA256_DIGEST_SIZE);
142962306a36Sopenharmony_ci}
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_cistatic int safexcel_hmac_sha256_init(struct ahash_request *areq)
143262306a36Sopenharmony_ci{
143362306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
143462306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	/* Start from ipad precompute */
143962306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE);
144062306a36Sopenharmony_ci	/* Already processed the key^ipad part now! */
144162306a36Sopenharmony_ci	req->len	= SHA256_BLOCK_SIZE;
144262306a36Sopenharmony_ci	req->processed	= SHA256_BLOCK_SIZE;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
144562306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
144662306a36Sopenharmony_ci	req->state_sz = SHA256_DIGEST_SIZE;
144762306a36Sopenharmony_ci	req->digest_sz = SHA256_DIGEST_SIZE;
144862306a36Sopenharmony_ci	req->block_sz = SHA256_BLOCK_SIZE;
144962306a36Sopenharmony_ci	req->hmac = true;
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci	return 0;
145262306a36Sopenharmony_ci}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_cistatic int safexcel_hmac_sha256_digest(struct ahash_request *areq)
145562306a36Sopenharmony_ci{
145662306a36Sopenharmony_ci	int ret = safexcel_hmac_sha256_init(areq);
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	if (ret)
145962306a36Sopenharmony_ci		return ret;
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
146262306a36Sopenharmony_ci}
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha256 = {
146562306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
146662306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA2_256,
146762306a36Sopenharmony_ci	.alg.ahash = {
146862306a36Sopenharmony_ci		.init = safexcel_hmac_sha256_init,
146962306a36Sopenharmony_ci		.update = safexcel_ahash_update,
147062306a36Sopenharmony_ci		.final = safexcel_ahash_final,
147162306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
147262306a36Sopenharmony_ci		.digest = safexcel_hmac_sha256_digest,
147362306a36Sopenharmony_ci		.setkey = safexcel_hmac_sha256_setkey,
147462306a36Sopenharmony_ci		.export = safexcel_ahash_export,
147562306a36Sopenharmony_ci		.import = safexcel_ahash_import,
147662306a36Sopenharmony_ci		.halg = {
147762306a36Sopenharmony_ci			.digestsize = SHA256_DIGEST_SIZE,
147862306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
147962306a36Sopenharmony_ci			.base = {
148062306a36Sopenharmony_ci				.cra_name = "hmac(sha256)",
148162306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sha256",
148262306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
148362306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
148462306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
148562306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
148662306a36Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
148762306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
148862306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
148962306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
149062306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
149162306a36Sopenharmony_ci			},
149262306a36Sopenharmony_ci		},
149362306a36Sopenharmony_ci	},
149462306a36Sopenharmony_ci};
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_cistatic int safexcel_sha512_init(struct ahash_request *areq)
149762306a36Sopenharmony_ci{
149862306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
149962306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
150462306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
150562306a36Sopenharmony_ci	req->state_sz = SHA512_DIGEST_SIZE;
150662306a36Sopenharmony_ci	req->digest_sz = SHA512_DIGEST_SIZE;
150762306a36Sopenharmony_ci	req->block_sz = SHA512_BLOCK_SIZE;
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	return 0;
151062306a36Sopenharmony_ci}
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_cistatic int safexcel_sha512_digest(struct ahash_request *areq)
151362306a36Sopenharmony_ci{
151462306a36Sopenharmony_ci	int ret = safexcel_sha512_init(areq);
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci	if (ret)
151762306a36Sopenharmony_ci		return ret;
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
152062306a36Sopenharmony_ci}
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha512 = {
152362306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
152462306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA2_512,
152562306a36Sopenharmony_ci	.alg.ahash = {
152662306a36Sopenharmony_ci		.init = safexcel_sha512_init,
152762306a36Sopenharmony_ci		.update = safexcel_ahash_update,
152862306a36Sopenharmony_ci		.final = safexcel_ahash_final,
152962306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
153062306a36Sopenharmony_ci		.digest = safexcel_sha512_digest,
153162306a36Sopenharmony_ci		.export = safexcel_ahash_export,
153262306a36Sopenharmony_ci		.import = safexcel_ahash_import,
153362306a36Sopenharmony_ci		.halg = {
153462306a36Sopenharmony_ci			.digestsize = SHA512_DIGEST_SIZE,
153562306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
153662306a36Sopenharmony_ci			.base = {
153762306a36Sopenharmony_ci				.cra_name = "sha512",
153862306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sha512",
153962306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
154062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
154162306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
154262306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
154362306a36Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
154462306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
154562306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
154662306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
154762306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
154862306a36Sopenharmony_ci			},
154962306a36Sopenharmony_ci		},
155062306a36Sopenharmony_ci	},
155162306a36Sopenharmony_ci};
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_cistatic int safexcel_sha384_init(struct ahash_request *areq)
155462306a36Sopenharmony_ci{
155562306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
155662306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
156162306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
156262306a36Sopenharmony_ci	req->state_sz = SHA512_DIGEST_SIZE;
156362306a36Sopenharmony_ci	req->digest_sz = SHA512_DIGEST_SIZE;
156462306a36Sopenharmony_ci	req->block_sz = SHA512_BLOCK_SIZE;
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	return 0;
156762306a36Sopenharmony_ci}
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_cistatic int safexcel_sha384_digest(struct ahash_request *areq)
157062306a36Sopenharmony_ci{
157162306a36Sopenharmony_ci	int ret = safexcel_sha384_init(areq);
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	if (ret)
157462306a36Sopenharmony_ci		return ret;
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
157762306a36Sopenharmony_ci}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha384 = {
158062306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
158162306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA2_512,
158262306a36Sopenharmony_ci	.alg.ahash = {
158362306a36Sopenharmony_ci		.init = safexcel_sha384_init,
158462306a36Sopenharmony_ci		.update = safexcel_ahash_update,
158562306a36Sopenharmony_ci		.final = safexcel_ahash_final,
158662306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
158762306a36Sopenharmony_ci		.digest = safexcel_sha384_digest,
158862306a36Sopenharmony_ci		.export = safexcel_ahash_export,
158962306a36Sopenharmony_ci		.import = safexcel_ahash_import,
159062306a36Sopenharmony_ci		.halg = {
159162306a36Sopenharmony_ci			.digestsize = SHA384_DIGEST_SIZE,
159262306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
159362306a36Sopenharmony_ci			.base = {
159462306a36Sopenharmony_ci				.cra_name = "sha384",
159562306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sha384",
159662306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
159762306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
159862306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
159962306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
160062306a36Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
160162306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
160262306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
160362306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
160462306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
160562306a36Sopenharmony_ci			},
160662306a36Sopenharmony_ci		},
160762306a36Sopenharmony_ci	},
160862306a36Sopenharmony_ci};
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_cistatic int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key,
161162306a36Sopenharmony_ci				       unsigned int keylen)
161262306a36Sopenharmony_ci{
161362306a36Sopenharmony_ci	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512",
161462306a36Sopenharmony_ci					SHA512_DIGEST_SIZE);
161562306a36Sopenharmony_ci}
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_cistatic int safexcel_hmac_sha512_init(struct ahash_request *areq)
161862306a36Sopenharmony_ci{
161962306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
162062306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	/* Start from ipad precompute */
162562306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE);
162662306a36Sopenharmony_ci	/* Already processed the key^ipad part now! */
162762306a36Sopenharmony_ci	req->len	= SHA512_BLOCK_SIZE;
162862306a36Sopenharmony_ci	req->processed	= SHA512_BLOCK_SIZE;
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
163162306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
163262306a36Sopenharmony_ci	req->state_sz = SHA512_DIGEST_SIZE;
163362306a36Sopenharmony_ci	req->digest_sz = SHA512_DIGEST_SIZE;
163462306a36Sopenharmony_ci	req->block_sz = SHA512_BLOCK_SIZE;
163562306a36Sopenharmony_ci	req->hmac = true;
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	return 0;
163862306a36Sopenharmony_ci}
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_cistatic int safexcel_hmac_sha512_digest(struct ahash_request *areq)
164162306a36Sopenharmony_ci{
164262306a36Sopenharmony_ci	int ret = safexcel_hmac_sha512_init(areq);
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	if (ret)
164562306a36Sopenharmony_ci		return ret;
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
164862306a36Sopenharmony_ci}
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha512 = {
165162306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
165262306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA2_512,
165362306a36Sopenharmony_ci	.alg.ahash = {
165462306a36Sopenharmony_ci		.init = safexcel_hmac_sha512_init,
165562306a36Sopenharmony_ci		.update = safexcel_ahash_update,
165662306a36Sopenharmony_ci		.final = safexcel_ahash_final,
165762306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
165862306a36Sopenharmony_ci		.digest = safexcel_hmac_sha512_digest,
165962306a36Sopenharmony_ci		.setkey = safexcel_hmac_sha512_setkey,
166062306a36Sopenharmony_ci		.export = safexcel_ahash_export,
166162306a36Sopenharmony_ci		.import = safexcel_ahash_import,
166262306a36Sopenharmony_ci		.halg = {
166362306a36Sopenharmony_ci			.digestsize = SHA512_DIGEST_SIZE,
166462306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
166562306a36Sopenharmony_ci			.base = {
166662306a36Sopenharmony_ci				.cra_name = "hmac(sha512)",
166762306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sha512",
166862306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
166962306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
167062306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
167162306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
167262306a36Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
167362306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
167462306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
167562306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
167662306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
167762306a36Sopenharmony_ci			},
167862306a36Sopenharmony_ci		},
167962306a36Sopenharmony_ci	},
168062306a36Sopenharmony_ci};
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_cistatic int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key,
168362306a36Sopenharmony_ci				       unsigned int keylen)
168462306a36Sopenharmony_ci{
168562306a36Sopenharmony_ci	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384",
168662306a36Sopenharmony_ci					SHA512_DIGEST_SIZE);
168762306a36Sopenharmony_ci}
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_cistatic int safexcel_hmac_sha384_init(struct ahash_request *areq)
169062306a36Sopenharmony_ci{
169162306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
169262306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
169562306a36Sopenharmony_ci
169662306a36Sopenharmony_ci	/* Start from ipad precompute */
169762306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE);
169862306a36Sopenharmony_ci	/* Already processed the key^ipad part now! */
169962306a36Sopenharmony_ci	req->len	= SHA512_BLOCK_SIZE;
170062306a36Sopenharmony_ci	req->processed	= SHA512_BLOCK_SIZE;
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
170362306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
170462306a36Sopenharmony_ci	req->state_sz = SHA512_DIGEST_SIZE;
170562306a36Sopenharmony_ci	req->digest_sz = SHA512_DIGEST_SIZE;
170662306a36Sopenharmony_ci	req->block_sz = SHA512_BLOCK_SIZE;
170762306a36Sopenharmony_ci	req->hmac = true;
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	return 0;
171062306a36Sopenharmony_ci}
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_cistatic int safexcel_hmac_sha384_digest(struct ahash_request *areq)
171362306a36Sopenharmony_ci{
171462306a36Sopenharmony_ci	int ret = safexcel_hmac_sha384_init(areq);
171562306a36Sopenharmony_ci
171662306a36Sopenharmony_ci	if (ret)
171762306a36Sopenharmony_ci		return ret;
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
172062306a36Sopenharmony_ci}
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha384 = {
172362306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
172462306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA2_512,
172562306a36Sopenharmony_ci	.alg.ahash = {
172662306a36Sopenharmony_ci		.init = safexcel_hmac_sha384_init,
172762306a36Sopenharmony_ci		.update = safexcel_ahash_update,
172862306a36Sopenharmony_ci		.final = safexcel_ahash_final,
172962306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
173062306a36Sopenharmony_ci		.digest = safexcel_hmac_sha384_digest,
173162306a36Sopenharmony_ci		.setkey = safexcel_hmac_sha384_setkey,
173262306a36Sopenharmony_ci		.export = safexcel_ahash_export,
173362306a36Sopenharmony_ci		.import = safexcel_ahash_import,
173462306a36Sopenharmony_ci		.halg = {
173562306a36Sopenharmony_ci			.digestsize = SHA384_DIGEST_SIZE,
173662306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
173762306a36Sopenharmony_ci			.base = {
173862306a36Sopenharmony_ci				.cra_name = "hmac(sha384)",
173962306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sha384",
174062306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
174162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
174262306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
174362306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
174462306a36Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
174562306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
174662306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
174762306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
174862306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
174962306a36Sopenharmony_ci			},
175062306a36Sopenharmony_ci		},
175162306a36Sopenharmony_ci	},
175262306a36Sopenharmony_ci};
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_cistatic int safexcel_md5_init(struct ahash_request *areq)
175562306a36Sopenharmony_ci{
175662306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
175762306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
176262306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
176362306a36Sopenharmony_ci	req->state_sz = MD5_DIGEST_SIZE;
176462306a36Sopenharmony_ci	req->digest_sz = MD5_DIGEST_SIZE;
176562306a36Sopenharmony_ci	req->block_sz = MD5_HMAC_BLOCK_SIZE;
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	return 0;
176862306a36Sopenharmony_ci}
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_cistatic int safexcel_md5_digest(struct ahash_request *areq)
177162306a36Sopenharmony_ci{
177262306a36Sopenharmony_ci	int ret = safexcel_md5_init(areq);
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci	if (ret)
177562306a36Sopenharmony_ci		return ret;
177662306a36Sopenharmony_ci
177762306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
177862306a36Sopenharmony_ci}
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_md5 = {
178162306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
178262306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_MD5,
178362306a36Sopenharmony_ci	.alg.ahash = {
178462306a36Sopenharmony_ci		.init = safexcel_md5_init,
178562306a36Sopenharmony_ci		.update = safexcel_ahash_update,
178662306a36Sopenharmony_ci		.final = safexcel_ahash_final,
178762306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
178862306a36Sopenharmony_ci		.digest = safexcel_md5_digest,
178962306a36Sopenharmony_ci		.export = safexcel_ahash_export,
179062306a36Sopenharmony_ci		.import = safexcel_ahash_import,
179162306a36Sopenharmony_ci		.halg = {
179262306a36Sopenharmony_ci			.digestsize = MD5_DIGEST_SIZE,
179362306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
179462306a36Sopenharmony_ci			.base = {
179562306a36Sopenharmony_ci				.cra_name = "md5",
179662306a36Sopenharmony_ci				.cra_driver_name = "safexcel-md5",
179762306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
179862306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
179962306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
180062306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
180162306a36Sopenharmony_ci				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
180262306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
180362306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
180462306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
180562306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
180662306a36Sopenharmony_ci			},
180762306a36Sopenharmony_ci		},
180862306a36Sopenharmony_ci	},
180962306a36Sopenharmony_ci};
181062306a36Sopenharmony_ci
181162306a36Sopenharmony_cistatic int safexcel_hmac_md5_init(struct ahash_request *areq)
181262306a36Sopenharmony_ci{
181362306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
181462306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci	/* Start from ipad precompute */
181962306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, MD5_DIGEST_SIZE);
182062306a36Sopenharmony_ci	/* Already processed the key^ipad part now! */
182162306a36Sopenharmony_ci	req->len	= MD5_HMAC_BLOCK_SIZE;
182262306a36Sopenharmony_ci	req->processed	= MD5_HMAC_BLOCK_SIZE;
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5;
182562306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
182662306a36Sopenharmony_ci	req->state_sz = MD5_DIGEST_SIZE;
182762306a36Sopenharmony_ci	req->digest_sz = MD5_DIGEST_SIZE;
182862306a36Sopenharmony_ci	req->block_sz = MD5_HMAC_BLOCK_SIZE;
182962306a36Sopenharmony_ci	req->len_is_le = true; /* MD5 is little endian! ... */
183062306a36Sopenharmony_ci	req->hmac = true;
183162306a36Sopenharmony_ci
183262306a36Sopenharmony_ci	return 0;
183362306a36Sopenharmony_ci}
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_cistatic int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key,
183662306a36Sopenharmony_ci				     unsigned int keylen)
183762306a36Sopenharmony_ci{
183862306a36Sopenharmony_ci	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5",
183962306a36Sopenharmony_ci					MD5_DIGEST_SIZE);
184062306a36Sopenharmony_ci}
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_cistatic int safexcel_hmac_md5_digest(struct ahash_request *areq)
184362306a36Sopenharmony_ci{
184462306a36Sopenharmony_ci	int ret = safexcel_hmac_md5_init(areq);
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci	if (ret)
184762306a36Sopenharmony_ci		return ret;
184862306a36Sopenharmony_ci
184962306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
185062306a36Sopenharmony_ci}
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_md5 = {
185362306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
185462306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_MD5,
185562306a36Sopenharmony_ci	.alg.ahash = {
185662306a36Sopenharmony_ci		.init = safexcel_hmac_md5_init,
185762306a36Sopenharmony_ci		.update = safexcel_ahash_update,
185862306a36Sopenharmony_ci		.final = safexcel_ahash_final,
185962306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
186062306a36Sopenharmony_ci		.digest = safexcel_hmac_md5_digest,
186162306a36Sopenharmony_ci		.setkey = safexcel_hmac_md5_setkey,
186262306a36Sopenharmony_ci		.export = safexcel_ahash_export,
186362306a36Sopenharmony_ci		.import = safexcel_ahash_import,
186462306a36Sopenharmony_ci		.halg = {
186562306a36Sopenharmony_ci			.digestsize = MD5_DIGEST_SIZE,
186662306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
186762306a36Sopenharmony_ci			.base = {
186862306a36Sopenharmony_ci				.cra_name = "hmac(md5)",
186962306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-md5",
187062306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
187162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
187262306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
187362306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
187462306a36Sopenharmony_ci				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
187562306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
187662306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
187762306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
187862306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
187962306a36Sopenharmony_ci			},
188062306a36Sopenharmony_ci		},
188162306a36Sopenharmony_ci	},
188262306a36Sopenharmony_ci};
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_cistatic int safexcel_crc32_cra_init(struct crypto_tfm *tfm)
188562306a36Sopenharmony_ci{
188662306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
188762306a36Sopenharmony_ci	int ret = safexcel_ahash_cra_init(tfm);
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	/* Default 'key' is all zeroes */
189062306a36Sopenharmony_ci	memset(&ctx->base.ipad, 0, sizeof(u32));
189162306a36Sopenharmony_ci	return ret;
189262306a36Sopenharmony_ci}
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_cistatic int safexcel_crc32_init(struct ahash_request *areq)
189562306a36Sopenharmony_ci{
189662306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
189762306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	/* Start from loaded key */
190262306a36Sopenharmony_ci	req->state[0]	= cpu_to_le32(~ctx->base.ipad.word[0]);
190362306a36Sopenharmony_ci	/* Set processed to non-zero to enable invalidation detection */
190462306a36Sopenharmony_ci	req->len	= sizeof(u32);
190562306a36Sopenharmony_ci	req->processed	= sizeof(u32);
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32;
190862306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_XCM;
190962306a36Sopenharmony_ci	req->state_sz = sizeof(u32);
191062306a36Sopenharmony_ci	req->digest_sz = sizeof(u32);
191162306a36Sopenharmony_ci	req->block_sz = sizeof(u32);
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	return 0;
191462306a36Sopenharmony_ci}
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_cistatic int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key,
191762306a36Sopenharmony_ci				 unsigned int keylen)
191862306a36Sopenharmony_ci{
191962306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_ci	if (keylen != sizeof(u32))
192262306a36Sopenharmony_ci		return -EINVAL;
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	memcpy(&ctx->base.ipad, key, sizeof(u32));
192562306a36Sopenharmony_ci	return 0;
192662306a36Sopenharmony_ci}
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_cistatic int safexcel_crc32_digest(struct ahash_request *areq)
192962306a36Sopenharmony_ci{
193062306a36Sopenharmony_ci	return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq);
193162306a36Sopenharmony_ci}
193262306a36Sopenharmony_ci
193362306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_crc32 = {
193462306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
193562306a36Sopenharmony_ci	.algo_mask = 0,
193662306a36Sopenharmony_ci	.alg.ahash = {
193762306a36Sopenharmony_ci		.init = safexcel_crc32_init,
193862306a36Sopenharmony_ci		.update = safexcel_ahash_update,
193962306a36Sopenharmony_ci		.final = safexcel_ahash_final,
194062306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
194162306a36Sopenharmony_ci		.digest = safexcel_crc32_digest,
194262306a36Sopenharmony_ci		.setkey = safexcel_crc32_setkey,
194362306a36Sopenharmony_ci		.export = safexcel_ahash_export,
194462306a36Sopenharmony_ci		.import = safexcel_ahash_import,
194562306a36Sopenharmony_ci		.halg = {
194662306a36Sopenharmony_ci			.digestsize = sizeof(u32),
194762306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
194862306a36Sopenharmony_ci			.base = {
194962306a36Sopenharmony_ci				.cra_name = "crc32",
195062306a36Sopenharmony_ci				.cra_driver_name = "safexcel-crc32",
195162306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
195262306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_OPTIONAL_KEY |
195362306a36Sopenharmony_ci					     CRYPTO_ALG_ASYNC |
195462306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
195562306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
195662306a36Sopenharmony_ci				.cra_blocksize = 1,
195762306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
195862306a36Sopenharmony_ci				.cra_init = safexcel_crc32_cra_init,
195962306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
196062306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
196162306a36Sopenharmony_ci			},
196262306a36Sopenharmony_ci		},
196362306a36Sopenharmony_ci	},
196462306a36Sopenharmony_ci};
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_cistatic int safexcel_cbcmac_init(struct ahash_request *areq)
196762306a36Sopenharmony_ci{
196862306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
196962306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci	/* Start from loaded keys */
197462306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, ctx->key_sz);
197562306a36Sopenharmony_ci	/* Set processed to non-zero to enable invalidation detection */
197662306a36Sopenharmony_ci	req->len	= AES_BLOCK_SIZE;
197762306a36Sopenharmony_ci	req->processed	= AES_BLOCK_SIZE;
197862306a36Sopenharmony_ci
197962306a36Sopenharmony_ci	req->digest   = CONTEXT_CONTROL_DIGEST_XCM;
198062306a36Sopenharmony_ci	req->state_sz = ctx->key_sz;
198162306a36Sopenharmony_ci	req->digest_sz = AES_BLOCK_SIZE;
198262306a36Sopenharmony_ci	req->block_sz = AES_BLOCK_SIZE;
198362306a36Sopenharmony_ci	req->xcbcmac  = true;
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	return 0;
198662306a36Sopenharmony_ci}
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_cistatic int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
198962306a36Sopenharmony_ci				 unsigned int len)
199062306a36Sopenharmony_ci{
199162306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
199262306a36Sopenharmony_ci	struct crypto_aes_ctx aes;
199362306a36Sopenharmony_ci	int ret, i;
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_ci	ret = aes_expandkey(&aes, key, len);
199662306a36Sopenharmony_ci	if (ret)
199762306a36Sopenharmony_ci		return ret;
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci	memset(&ctx->base.ipad, 0, 2 * AES_BLOCK_SIZE);
200062306a36Sopenharmony_ci	for (i = 0; i < len / sizeof(u32); i++)
200162306a36Sopenharmony_ci		ctx->base.ipad.be[i + 8] = cpu_to_be32(aes.key_enc[i]);
200262306a36Sopenharmony_ci
200362306a36Sopenharmony_ci	if (len == AES_KEYSIZE_192) {
200462306a36Sopenharmony_ci		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
200562306a36Sopenharmony_ci		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
200662306a36Sopenharmony_ci	} else if (len == AES_KEYSIZE_256) {
200762306a36Sopenharmony_ci		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
200862306a36Sopenharmony_ci		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
200962306a36Sopenharmony_ci	} else {
201062306a36Sopenharmony_ci		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
201162306a36Sopenharmony_ci		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
201262306a36Sopenharmony_ci	}
201362306a36Sopenharmony_ci	ctx->cbcmac  = true;
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	memzero_explicit(&aes, sizeof(aes));
201662306a36Sopenharmony_ci	return 0;
201762306a36Sopenharmony_ci}
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_cistatic int safexcel_cbcmac_digest(struct ahash_request *areq)
202062306a36Sopenharmony_ci{
202162306a36Sopenharmony_ci	return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq);
202262306a36Sopenharmony_ci}
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_cbcmac = {
202562306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
202662306a36Sopenharmony_ci	.algo_mask = 0,
202762306a36Sopenharmony_ci	.alg.ahash = {
202862306a36Sopenharmony_ci		.init = safexcel_cbcmac_init,
202962306a36Sopenharmony_ci		.update = safexcel_ahash_update,
203062306a36Sopenharmony_ci		.final = safexcel_ahash_final,
203162306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
203262306a36Sopenharmony_ci		.digest = safexcel_cbcmac_digest,
203362306a36Sopenharmony_ci		.setkey = safexcel_cbcmac_setkey,
203462306a36Sopenharmony_ci		.export = safexcel_ahash_export,
203562306a36Sopenharmony_ci		.import = safexcel_ahash_import,
203662306a36Sopenharmony_ci		.halg = {
203762306a36Sopenharmony_ci			.digestsize = AES_BLOCK_SIZE,
203862306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
203962306a36Sopenharmony_ci			.base = {
204062306a36Sopenharmony_ci				.cra_name = "cbcmac(aes)",
204162306a36Sopenharmony_ci				.cra_driver_name = "safexcel-cbcmac-aes",
204262306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
204362306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
204462306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
204562306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
204662306a36Sopenharmony_ci				.cra_blocksize = 1,
204762306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
204862306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
204962306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
205062306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
205162306a36Sopenharmony_ci			},
205262306a36Sopenharmony_ci		},
205362306a36Sopenharmony_ci	},
205462306a36Sopenharmony_ci};
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_cistatic int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key,
205762306a36Sopenharmony_ci				 unsigned int len)
205862306a36Sopenharmony_ci{
205962306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
206062306a36Sopenharmony_ci	u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)];
206162306a36Sopenharmony_ci	int ret, i;
206262306a36Sopenharmony_ci
206362306a36Sopenharmony_ci	ret = aes_expandkey(ctx->aes, key, len);
206462306a36Sopenharmony_ci	if (ret)
206562306a36Sopenharmony_ci		return ret;
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci	/* precompute the XCBC key material */
206862306a36Sopenharmony_ci	aes_encrypt(ctx->aes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
206962306a36Sopenharmony_ci		    "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1");
207062306a36Sopenharmony_ci	aes_encrypt(ctx->aes, (u8 *)key_tmp,
207162306a36Sopenharmony_ci		    "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2");
207262306a36Sopenharmony_ci	aes_encrypt(ctx->aes, (u8 *)key_tmp + AES_BLOCK_SIZE,
207362306a36Sopenharmony_ci		    "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3");
207462306a36Sopenharmony_ci	for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++)
207562306a36Sopenharmony_ci		ctx->base.ipad.word[i] = swab32(key_tmp[i]);
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci	ret = aes_expandkey(ctx->aes,
207862306a36Sopenharmony_ci			    (u8 *)key_tmp + 2 * AES_BLOCK_SIZE,
207962306a36Sopenharmony_ci			    AES_MIN_KEY_SIZE);
208062306a36Sopenharmony_ci	if (ret)
208162306a36Sopenharmony_ci		return ret;
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
208462306a36Sopenharmony_ci	ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
208562306a36Sopenharmony_ci	ctx->cbcmac = false;
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	return 0;
208862306a36Sopenharmony_ci}
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_cistatic int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm)
209162306a36Sopenharmony_ci{
209262306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci	safexcel_ahash_cra_init(tfm);
209562306a36Sopenharmony_ci	ctx->aes = kmalloc(sizeof(*ctx->aes), GFP_KERNEL);
209662306a36Sopenharmony_ci	return PTR_ERR_OR_ZERO(ctx->aes);
209762306a36Sopenharmony_ci}
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_cistatic void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm)
210062306a36Sopenharmony_ci{
210162306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
210262306a36Sopenharmony_ci
210362306a36Sopenharmony_ci	kfree(ctx->aes);
210462306a36Sopenharmony_ci	safexcel_ahash_cra_exit(tfm);
210562306a36Sopenharmony_ci}
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_xcbcmac = {
210862306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
210962306a36Sopenharmony_ci	.algo_mask = 0,
211062306a36Sopenharmony_ci	.alg.ahash = {
211162306a36Sopenharmony_ci		.init = safexcel_cbcmac_init,
211262306a36Sopenharmony_ci		.update = safexcel_ahash_update,
211362306a36Sopenharmony_ci		.final = safexcel_ahash_final,
211462306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
211562306a36Sopenharmony_ci		.digest = safexcel_cbcmac_digest,
211662306a36Sopenharmony_ci		.setkey = safexcel_xcbcmac_setkey,
211762306a36Sopenharmony_ci		.export = safexcel_ahash_export,
211862306a36Sopenharmony_ci		.import = safexcel_ahash_import,
211962306a36Sopenharmony_ci		.halg = {
212062306a36Sopenharmony_ci			.digestsize = AES_BLOCK_SIZE,
212162306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
212262306a36Sopenharmony_ci			.base = {
212362306a36Sopenharmony_ci				.cra_name = "xcbc(aes)",
212462306a36Sopenharmony_ci				.cra_driver_name = "safexcel-xcbc-aes",
212562306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
212662306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
212762306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
212862306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
212962306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
213062306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
213162306a36Sopenharmony_ci				.cra_init = safexcel_xcbcmac_cra_init,
213262306a36Sopenharmony_ci				.cra_exit = safexcel_xcbcmac_cra_exit,
213362306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
213462306a36Sopenharmony_ci			},
213562306a36Sopenharmony_ci		},
213662306a36Sopenharmony_ci	},
213762306a36Sopenharmony_ci};
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_cistatic int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
214062306a36Sopenharmony_ci				unsigned int len)
214162306a36Sopenharmony_ci{
214262306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
214362306a36Sopenharmony_ci	__be64 consts[4];
214462306a36Sopenharmony_ci	u64 _const[2];
214562306a36Sopenharmony_ci	u8 msb_mask, gfmask;
214662306a36Sopenharmony_ci	int ret, i;
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_ci	/* precompute the CMAC key material */
214962306a36Sopenharmony_ci	ret = aes_expandkey(ctx->aes, key, len);
215062306a36Sopenharmony_ci	if (ret)
215162306a36Sopenharmony_ci		return ret;
215262306a36Sopenharmony_ci
215362306a36Sopenharmony_ci	for (i = 0; i < len / sizeof(u32); i++)
215462306a36Sopenharmony_ci		ctx->base.ipad.word[i + 8] = swab32(ctx->aes->key_enc[i]);
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_ci	/* code below borrowed from crypto/cmac.c */
215762306a36Sopenharmony_ci	/* encrypt the zero block */
215862306a36Sopenharmony_ci	memset(consts, 0, AES_BLOCK_SIZE);
215962306a36Sopenharmony_ci	aes_encrypt(ctx->aes, (u8 *)consts, (u8 *)consts);
216062306a36Sopenharmony_ci
216162306a36Sopenharmony_ci	gfmask = 0x87;
216262306a36Sopenharmony_ci	_const[0] = be64_to_cpu(consts[1]);
216362306a36Sopenharmony_ci	_const[1] = be64_to_cpu(consts[0]);
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci	/* gf(2^128) multiply zero-ciphertext with u and u^2 */
216662306a36Sopenharmony_ci	for (i = 0; i < 4; i += 2) {
216762306a36Sopenharmony_ci		msb_mask = ((s64)_const[1] >> 63) & gfmask;
216862306a36Sopenharmony_ci		_const[1] = (_const[1] << 1) | (_const[0] >> 63);
216962306a36Sopenharmony_ci		_const[0] = (_const[0] << 1) ^ msb_mask;
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_ci		consts[i + 0] = cpu_to_be64(_const[1]);
217262306a36Sopenharmony_ci		consts[i + 1] = cpu_to_be64(_const[0]);
217362306a36Sopenharmony_ci	}
217462306a36Sopenharmony_ci	/* end of code borrowed from crypto/cmac.c */
217562306a36Sopenharmony_ci
217662306a36Sopenharmony_ci	for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++)
217762306a36Sopenharmony_ci		ctx->base.ipad.be[i] = cpu_to_be32(((u32 *)consts)[i]);
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci	if (len == AES_KEYSIZE_192) {
218062306a36Sopenharmony_ci		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
218162306a36Sopenharmony_ci		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
218262306a36Sopenharmony_ci	} else if (len == AES_KEYSIZE_256) {
218362306a36Sopenharmony_ci		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
218462306a36Sopenharmony_ci		ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE;
218562306a36Sopenharmony_ci	} else {
218662306a36Sopenharmony_ci		ctx->alg    = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
218762306a36Sopenharmony_ci		ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE;
218862306a36Sopenharmony_ci	}
218962306a36Sopenharmony_ci	ctx->cbcmac = false;
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci	return 0;
219262306a36Sopenharmony_ci}
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_cmac = {
219562306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
219662306a36Sopenharmony_ci	.algo_mask = 0,
219762306a36Sopenharmony_ci	.alg.ahash = {
219862306a36Sopenharmony_ci		.init = safexcel_cbcmac_init,
219962306a36Sopenharmony_ci		.update = safexcel_ahash_update,
220062306a36Sopenharmony_ci		.final = safexcel_ahash_final,
220162306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
220262306a36Sopenharmony_ci		.digest = safexcel_cbcmac_digest,
220362306a36Sopenharmony_ci		.setkey = safexcel_cmac_setkey,
220462306a36Sopenharmony_ci		.export = safexcel_ahash_export,
220562306a36Sopenharmony_ci		.import = safexcel_ahash_import,
220662306a36Sopenharmony_ci		.halg = {
220762306a36Sopenharmony_ci			.digestsize = AES_BLOCK_SIZE,
220862306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
220962306a36Sopenharmony_ci			.base = {
221062306a36Sopenharmony_ci				.cra_name = "cmac(aes)",
221162306a36Sopenharmony_ci				.cra_driver_name = "safexcel-cmac-aes",
221262306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
221362306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
221462306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
221562306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
221662306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
221762306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
221862306a36Sopenharmony_ci				.cra_init = safexcel_xcbcmac_cra_init,
221962306a36Sopenharmony_ci				.cra_exit = safexcel_xcbcmac_cra_exit,
222062306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
222162306a36Sopenharmony_ci			},
222262306a36Sopenharmony_ci		},
222362306a36Sopenharmony_ci	},
222462306a36Sopenharmony_ci};
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_cistatic int safexcel_sm3_init(struct ahash_request *areq)
222762306a36Sopenharmony_ci{
222862306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
222962306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
223462306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
223562306a36Sopenharmony_ci	req->state_sz = SM3_DIGEST_SIZE;
223662306a36Sopenharmony_ci	req->digest_sz = SM3_DIGEST_SIZE;
223762306a36Sopenharmony_ci	req->block_sz = SM3_BLOCK_SIZE;
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci	return 0;
224062306a36Sopenharmony_ci}
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_cistatic int safexcel_sm3_digest(struct ahash_request *areq)
224362306a36Sopenharmony_ci{
224462306a36Sopenharmony_ci	int ret = safexcel_sm3_init(areq);
224562306a36Sopenharmony_ci
224662306a36Sopenharmony_ci	if (ret)
224762306a36Sopenharmony_ci		return ret;
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
225062306a36Sopenharmony_ci}
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sm3 = {
225362306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
225462306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SM3,
225562306a36Sopenharmony_ci	.alg.ahash = {
225662306a36Sopenharmony_ci		.init = safexcel_sm3_init,
225762306a36Sopenharmony_ci		.update = safexcel_ahash_update,
225862306a36Sopenharmony_ci		.final = safexcel_ahash_final,
225962306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
226062306a36Sopenharmony_ci		.digest = safexcel_sm3_digest,
226162306a36Sopenharmony_ci		.export = safexcel_ahash_export,
226262306a36Sopenharmony_ci		.import = safexcel_ahash_import,
226362306a36Sopenharmony_ci		.halg = {
226462306a36Sopenharmony_ci			.digestsize = SM3_DIGEST_SIZE,
226562306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
226662306a36Sopenharmony_ci			.base = {
226762306a36Sopenharmony_ci				.cra_name = "sm3",
226862306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sm3",
226962306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
227062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
227162306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
227262306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
227362306a36Sopenharmony_ci				.cra_blocksize = SM3_BLOCK_SIZE,
227462306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
227562306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
227662306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
227762306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
227862306a36Sopenharmony_ci			},
227962306a36Sopenharmony_ci		},
228062306a36Sopenharmony_ci	},
228162306a36Sopenharmony_ci};
228262306a36Sopenharmony_ci
228362306a36Sopenharmony_cistatic int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key,
228462306a36Sopenharmony_ci				    unsigned int keylen)
228562306a36Sopenharmony_ci{
228662306a36Sopenharmony_ci	return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3",
228762306a36Sopenharmony_ci					SM3_DIGEST_SIZE);
228862306a36Sopenharmony_ci}
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_cistatic int safexcel_hmac_sm3_init(struct ahash_request *areq)
229162306a36Sopenharmony_ci{
229262306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
229362306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
229662306a36Sopenharmony_ci
229762306a36Sopenharmony_ci	/* Start from ipad precompute */
229862306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SM3_DIGEST_SIZE);
229962306a36Sopenharmony_ci	/* Already processed the key^ipad part now! */
230062306a36Sopenharmony_ci	req->len	= SM3_BLOCK_SIZE;
230162306a36Sopenharmony_ci	req->processed	= SM3_BLOCK_SIZE;
230262306a36Sopenharmony_ci
230362306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
230462306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED;
230562306a36Sopenharmony_ci	req->state_sz = SM3_DIGEST_SIZE;
230662306a36Sopenharmony_ci	req->digest_sz = SM3_DIGEST_SIZE;
230762306a36Sopenharmony_ci	req->block_sz = SM3_BLOCK_SIZE;
230862306a36Sopenharmony_ci	req->hmac = true;
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci	return 0;
231162306a36Sopenharmony_ci}
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_cistatic int safexcel_hmac_sm3_digest(struct ahash_request *areq)
231462306a36Sopenharmony_ci{
231562306a36Sopenharmony_ci	int ret = safexcel_hmac_sm3_init(areq);
231662306a36Sopenharmony_ci
231762306a36Sopenharmony_ci	if (ret)
231862306a36Sopenharmony_ci		return ret;
231962306a36Sopenharmony_ci
232062306a36Sopenharmony_ci	return safexcel_ahash_finup(areq);
232162306a36Sopenharmony_ci}
232262306a36Sopenharmony_ci
232362306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sm3 = {
232462306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
232562306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SM3,
232662306a36Sopenharmony_ci	.alg.ahash = {
232762306a36Sopenharmony_ci		.init = safexcel_hmac_sm3_init,
232862306a36Sopenharmony_ci		.update = safexcel_ahash_update,
232962306a36Sopenharmony_ci		.final = safexcel_ahash_final,
233062306a36Sopenharmony_ci		.finup = safexcel_ahash_finup,
233162306a36Sopenharmony_ci		.digest = safexcel_hmac_sm3_digest,
233262306a36Sopenharmony_ci		.setkey = safexcel_hmac_sm3_setkey,
233362306a36Sopenharmony_ci		.export = safexcel_ahash_export,
233462306a36Sopenharmony_ci		.import = safexcel_ahash_import,
233562306a36Sopenharmony_ci		.halg = {
233662306a36Sopenharmony_ci			.digestsize = SM3_DIGEST_SIZE,
233762306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
233862306a36Sopenharmony_ci			.base = {
233962306a36Sopenharmony_ci				.cra_name = "hmac(sm3)",
234062306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sm3",
234162306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
234262306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
234362306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
234462306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
234562306a36Sopenharmony_ci				.cra_blocksize = SM3_BLOCK_SIZE,
234662306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
234762306a36Sopenharmony_ci				.cra_init = safexcel_ahash_cra_init,
234862306a36Sopenharmony_ci				.cra_exit = safexcel_ahash_cra_exit,
234962306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
235062306a36Sopenharmony_ci			},
235162306a36Sopenharmony_ci		},
235262306a36Sopenharmony_ci	},
235362306a36Sopenharmony_ci};
235462306a36Sopenharmony_ci
235562306a36Sopenharmony_cistatic int safexcel_sha3_224_init(struct ahash_request *areq)
235662306a36Sopenharmony_ci{
235762306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
235862306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
235962306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
236062306a36Sopenharmony_ci
236162306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
236262306a36Sopenharmony_ci
236362306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
236462306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
236562306a36Sopenharmony_ci	req->state_sz = SHA3_224_DIGEST_SIZE;
236662306a36Sopenharmony_ci	req->digest_sz = SHA3_224_DIGEST_SIZE;
236762306a36Sopenharmony_ci	req->block_sz = SHA3_224_BLOCK_SIZE;
236862306a36Sopenharmony_ci	ctx->do_fallback = false;
236962306a36Sopenharmony_ci	ctx->fb_init_done = false;
237062306a36Sopenharmony_ci	return 0;
237162306a36Sopenharmony_ci}
237262306a36Sopenharmony_ci
237362306a36Sopenharmony_cistatic int safexcel_sha3_fbcheck(struct ahash_request *req)
237462306a36Sopenharmony_ci{
237562306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
237662306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
237762306a36Sopenharmony_ci	struct ahash_request *subreq = ahash_request_ctx_dma(req);
237862306a36Sopenharmony_ci	int ret = 0;
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci	if (ctx->do_fallback) {
238162306a36Sopenharmony_ci		ahash_request_set_tfm(subreq, ctx->fback);
238262306a36Sopenharmony_ci		ahash_request_set_callback(subreq, req->base.flags,
238362306a36Sopenharmony_ci					   req->base.complete, req->base.data);
238462306a36Sopenharmony_ci		ahash_request_set_crypt(subreq, req->src, req->result,
238562306a36Sopenharmony_ci					req->nbytes);
238662306a36Sopenharmony_ci		if (!ctx->fb_init_done) {
238762306a36Sopenharmony_ci			if (ctx->fb_do_setkey) {
238862306a36Sopenharmony_ci				/* Set fallback cipher HMAC key */
238962306a36Sopenharmony_ci				u8 key[SHA3_224_BLOCK_SIZE];
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci				memcpy(key, &ctx->base.ipad,
239262306a36Sopenharmony_ci				       crypto_ahash_blocksize(ctx->fback) / 2);
239362306a36Sopenharmony_ci				memcpy(key +
239462306a36Sopenharmony_ci				       crypto_ahash_blocksize(ctx->fback) / 2,
239562306a36Sopenharmony_ci				       &ctx->base.opad,
239662306a36Sopenharmony_ci				       crypto_ahash_blocksize(ctx->fback) / 2);
239762306a36Sopenharmony_ci				ret = crypto_ahash_setkey(ctx->fback, key,
239862306a36Sopenharmony_ci					crypto_ahash_blocksize(ctx->fback));
239962306a36Sopenharmony_ci				memzero_explicit(key,
240062306a36Sopenharmony_ci					crypto_ahash_blocksize(ctx->fback));
240162306a36Sopenharmony_ci				ctx->fb_do_setkey = false;
240262306a36Sopenharmony_ci			}
240362306a36Sopenharmony_ci			ret = ret ?: crypto_ahash_init(subreq);
240462306a36Sopenharmony_ci			ctx->fb_init_done = true;
240562306a36Sopenharmony_ci		}
240662306a36Sopenharmony_ci	}
240762306a36Sopenharmony_ci	return ret;
240862306a36Sopenharmony_ci}
240962306a36Sopenharmony_ci
241062306a36Sopenharmony_cistatic int safexcel_sha3_update(struct ahash_request *req)
241162306a36Sopenharmony_ci{
241262306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
241362306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
241462306a36Sopenharmony_ci	struct ahash_request *subreq = ahash_request_ctx_dma(req);
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_ci	ctx->do_fallback = true;
241762306a36Sopenharmony_ci	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq);
241862306a36Sopenharmony_ci}
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_cistatic int safexcel_sha3_final(struct ahash_request *req)
242162306a36Sopenharmony_ci{
242262306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
242362306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
242462306a36Sopenharmony_ci	struct ahash_request *subreq = ahash_request_ctx_dma(req);
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci	ctx->do_fallback = true;
242762306a36Sopenharmony_ci	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq);
242862306a36Sopenharmony_ci}
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_cistatic int safexcel_sha3_finup(struct ahash_request *req)
243162306a36Sopenharmony_ci{
243262306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
243362306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
243462306a36Sopenharmony_ci	struct ahash_request *subreq = ahash_request_ctx_dma(req);
243562306a36Sopenharmony_ci
243662306a36Sopenharmony_ci	ctx->do_fallback |= !req->nbytes;
243762306a36Sopenharmony_ci	if (ctx->do_fallback)
243862306a36Sopenharmony_ci		/* Update or ex/import happened or len 0, cannot use the HW */
243962306a36Sopenharmony_ci		return safexcel_sha3_fbcheck(req) ?:
244062306a36Sopenharmony_ci		       crypto_ahash_finup(subreq);
244162306a36Sopenharmony_ci	else
244262306a36Sopenharmony_ci		return safexcel_ahash_finup(req);
244362306a36Sopenharmony_ci}
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_cistatic int safexcel_sha3_digest_fallback(struct ahash_request *req)
244662306a36Sopenharmony_ci{
244762306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
244862306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
244962306a36Sopenharmony_ci	struct ahash_request *subreq = ahash_request_ctx_dma(req);
245062306a36Sopenharmony_ci
245162306a36Sopenharmony_ci	ctx->do_fallback = true;
245262306a36Sopenharmony_ci	ctx->fb_init_done = false;
245362306a36Sopenharmony_ci	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq);
245462306a36Sopenharmony_ci}
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_cistatic int safexcel_sha3_224_digest(struct ahash_request *req)
245762306a36Sopenharmony_ci{
245862306a36Sopenharmony_ci	if (req->nbytes)
245962306a36Sopenharmony_ci		return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req);
246062306a36Sopenharmony_ci
246162306a36Sopenharmony_ci	/* HW cannot do zero length hash, use fallback instead */
246262306a36Sopenharmony_ci	return safexcel_sha3_digest_fallback(req);
246362306a36Sopenharmony_ci}
246462306a36Sopenharmony_ci
246562306a36Sopenharmony_cistatic int safexcel_sha3_export(struct ahash_request *req, void *out)
246662306a36Sopenharmony_ci{
246762306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
246862306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
246962306a36Sopenharmony_ci	struct ahash_request *subreq = ahash_request_ctx_dma(req);
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ci	ctx->do_fallback = true;
247262306a36Sopenharmony_ci	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out);
247362306a36Sopenharmony_ci}
247462306a36Sopenharmony_ci
247562306a36Sopenharmony_cistatic int safexcel_sha3_import(struct ahash_request *req, const void *in)
247662306a36Sopenharmony_ci{
247762306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
247862306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
247962306a36Sopenharmony_ci	struct ahash_request *subreq = ahash_request_ctx_dma(req);
248062306a36Sopenharmony_ci
248162306a36Sopenharmony_ci	ctx->do_fallback = true;
248262306a36Sopenharmony_ci	return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in);
248362306a36Sopenharmony_ci	// return safexcel_ahash_import(req, in);
248462306a36Sopenharmony_ci}
248562306a36Sopenharmony_ci
248662306a36Sopenharmony_cistatic int safexcel_sha3_cra_init(struct crypto_tfm *tfm)
248762306a36Sopenharmony_ci{
248862306a36Sopenharmony_ci	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
248962306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_ci	safexcel_ahash_cra_init(tfm);
249262306a36Sopenharmony_ci
249362306a36Sopenharmony_ci	/* Allocate fallback implementation */
249462306a36Sopenharmony_ci	ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0,
249562306a36Sopenharmony_ci					CRYPTO_ALG_ASYNC |
249662306a36Sopenharmony_ci					CRYPTO_ALG_NEED_FALLBACK);
249762306a36Sopenharmony_ci	if (IS_ERR(ctx->fback))
249862306a36Sopenharmony_ci		return PTR_ERR(ctx->fback);
249962306a36Sopenharmony_ci
250062306a36Sopenharmony_ci	/* Update statesize from fallback algorithm! */
250162306a36Sopenharmony_ci	crypto_hash_alg_common(ahash)->statesize =
250262306a36Sopenharmony_ci		crypto_ahash_statesize(ctx->fback);
250362306a36Sopenharmony_ci	crypto_ahash_set_reqsize_dma(
250462306a36Sopenharmony_ci		ahash, max(sizeof(struct safexcel_ahash_req),
250562306a36Sopenharmony_ci			   sizeof(struct ahash_request) +
250662306a36Sopenharmony_ci			   crypto_ahash_reqsize(ctx->fback)));
250762306a36Sopenharmony_ci	return 0;
250862306a36Sopenharmony_ci}
250962306a36Sopenharmony_ci
251062306a36Sopenharmony_cistatic void safexcel_sha3_cra_exit(struct crypto_tfm *tfm)
251162306a36Sopenharmony_ci{
251262306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
251362306a36Sopenharmony_ci
251462306a36Sopenharmony_ci	crypto_free_ahash(ctx->fback);
251562306a36Sopenharmony_ci	safexcel_ahash_cra_exit(tfm);
251662306a36Sopenharmony_ci}
251762306a36Sopenharmony_ci
251862306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_224 = {
251962306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
252062306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA3,
252162306a36Sopenharmony_ci	.alg.ahash = {
252262306a36Sopenharmony_ci		.init = safexcel_sha3_224_init,
252362306a36Sopenharmony_ci		.update = safexcel_sha3_update,
252462306a36Sopenharmony_ci		.final = safexcel_sha3_final,
252562306a36Sopenharmony_ci		.finup = safexcel_sha3_finup,
252662306a36Sopenharmony_ci		.digest = safexcel_sha3_224_digest,
252762306a36Sopenharmony_ci		.export = safexcel_sha3_export,
252862306a36Sopenharmony_ci		.import = safexcel_sha3_import,
252962306a36Sopenharmony_ci		.halg = {
253062306a36Sopenharmony_ci			.digestsize = SHA3_224_DIGEST_SIZE,
253162306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
253262306a36Sopenharmony_ci			.base = {
253362306a36Sopenharmony_ci				.cra_name = "sha3-224",
253462306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sha3-224",
253562306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
253662306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
253762306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY |
253862306a36Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK,
253962306a36Sopenharmony_ci				.cra_blocksize = SHA3_224_BLOCK_SIZE,
254062306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
254162306a36Sopenharmony_ci				.cra_init = safexcel_sha3_cra_init,
254262306a36Sopenharmony_ci				.cra_exit = safexcel_sha3_cra_exit,
254362306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
254462306a36Sopenharmony_ci			},
254562306a36Sopenharmony_ci		},
254662306a36Sopenharmony_ci	},
254762306a36Sopenharmony_ci};
254862306a36Sopenharmony_ci
254962306a36Sopenharmony_cistatic int safexcel_sha3_256_init(struct ahash_request *areq)
255062306a36Sopenharmony_ci{
255162306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
255262306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
255362306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
255462306a36Sopenharmony_ci
255562306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
255662306a36Sopenharmony_ci
255762306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
255862306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
255962306a36Sopenharmony_ci	req->state_sz = SHA3_256_DIGEST_SIZE;
256062306a36Sopenharmony_ci	req->digest_sz = SHA3_256_DIGEST_SIZE;
256162306a36Sopenharmony_ci	req->block_sz = SHA3_256_BLOCK_SIZE;
256262306a36Sopenharmony_ci	ctx->do_fallback = false;
256362306a36Sopenharmony_ci	ctx->fb_init_done = false;
256462306a36Sopenharmony_ci	return 0;
256562306a36Sopenharmony_ci}
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_cistatic int safexcel_sha3_256_digest(struct ahash_request *req)
256862306a36Sopenharmony_ci{
256962306a36Sopenharmony_ci	if (req->nbytes)
257062306a36Sopenharmony_ci		return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req);
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci	/* HW cannot do zero length hash, use fallback instead */
257362306a36Sopenharmony_ci	return safexcel_sha3_digest_fallback(req);
257462306a36Sopenharmony_ci}
257562306a36Sopenharmony_ci
257662306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_256 = {
257762306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
257862306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA3,
257962306a36Sopenharmony_ci	.alg.ahash = {
258062306a36Sopenharmony_ci		.init = safexcel_sha3_256_init,
258162306a36Sopenharmony_ci		.update = safexcel_sha3_update,
258262306a36Sopenharmony_ci		.final = safexcel_sha3_final,
258362306a36Sopenharmony_ci		.finup = safexcel_sha3_finup,
258462306a36Sopenharmony_ci		.digest = safexcel_sha3_256_digest,
258562306a36Sopenharmony_ci		.export = safexcel_sha3_export,
258662306a36Sopenharmony_ci		.import = safexcel_sha3_import,
258762306a36Sopenharmony_ci		.halg = {
258862306a36Sopenharmony_ci			.digestsize = SHA3_256_DIGEST_SIZE,
258962306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
259062306a36Sopenharmony_ci			.base = {
259162306a36Sopenharmony_ci				.cra_name = "sha3-256",
259262306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sha3-256",
259362306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
259462306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
259562306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY |
259662306a36Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK,
259762306a36Sopenharmony_ci				.cra_blocksize = SHA3_256_BLOCK_SIZE,
259862306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
259962306a36Sopenharmony_ci				.cra_init = safexcel_sha3_cra_init,
260062306a36Sopenharmony_ci				.cra_exit = safexcel_sha3_cra_exit,
260162306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
260262306a36Sopenharmony_ci			},
260362306a36Sopenharmony_ci		},
260462306a36Sopenharmony_ci	},
260562306a36Sopenharmony_ci};
260662306a36Sopenharmony_ci
260762306a36Sopenharmony_cistatic int safexcel_sha3_384_init(struct ahash_request *areq)
260862306a36Sopenharmony_ci{
260962306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
261062306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
261162306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
261262306a36Sopenharmony_ci
261362306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
261462306a36Sopenharmony_ci
261562306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
261662306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
261762306a36Sopenharmony_ci	req->state_sz = SHA3_384_DIGEST_SIZE;
261862306a36Sopenharmony_ci	req->digest_sz = SHA3_384_DIGEST_SIZE;
261962306a36Sopenharmony_ci	req->block_sz = SHA3_384_BLOCK_SIZE;
262062306a36Sopenharmony_ci	ctx->do_fallback = false;
262162306a36Sopenharmony_ci	ctx->fb_init_done = false;
262262306a36Sopenharmony_ci	return 0;
262362306a36Sopenharmony_ci}
262462306a36Sopenharmony_ci
262562306a36Sopenharmony_cistatic int safexcel_sha3_384_digest(struct ahash_request *req)
262662306a36Sopenharmony_ci{
262762306a36Sopenharmony_ci	if (req->nbytes)
262862306a36Sopenharmony_ci		return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req);
262962306a36Sopenharmony_ci
263062306a36Sopenharmony_ci	/* HW cannot do zero length hash, use fallback instead */
263162306a36Sopenharmony_ci	return safexcel_sha3_digest_fallback(req);
263262306a36Sopenharmony_ci}
263362306a36Sopenharmony_ci
263462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_384 = {
263562306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
263662306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA3,
263762306a36Sopenharmony_ci	.alg.ahash = {
263862306a36Sopenharmony_ci		.init = safexcel_sha3_384_init,
263962306a36Sopenharmony_ci		.update = safexcel_sha3_update,
264062306a36Sopenharmony_ci		.final = safexcel_sha3_final,
264162306a36Sopenharmony_ci		.finup = safexcel_sha3_finup,
264262306a36Sopenharmony_ci		.digest = safexcel_sha3_384_digest,
264362306a36Sopenharmony_ci		.export = safexcel_sha3_export,
264462306a36Sopenharmony_ci		.import = safexcel_sha3_import,
264562306a36Sopenharmony_ci		.halg = {
264662306a36Sopenharmony_ci			.digestsize = SHA3_384_DIGEST_SIZE,
264762306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
264862306a36Sopenharmony_ci			.base = {
264962306a36Sopenharmony_ci				.cra_name = "sha3-384",
265062306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sha3-384",
265162306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
265262306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
265362306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY |
265462306a36Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK,
265562306a36Sopenharmony_ci				.cra_blocksize = SHA3_384_BLOCK_SIZE,
265662306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
265762306a36Sopenharmony_ci				.cra_init = safexcel_sha3_cra_init,
265862306a36Sopenharmony_ci				.cra_exit = safexcel_sha3_cra_exit,
265962306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
266062306a36Sopenharmony_ci			},
266162306a36Sopenharmony_ci		},
266262306a36Sopenharmony_ci	},
266362306a36Sopenharmony_ci};
266462306a36Sopenharmony_ci
266562306a36Sopenharmony_cistatic int safexcel_sha3_512_init(struct ahash_request *areq)
266662306a36Sopenharmony_ci{
266762306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
266862306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
266962306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
267062306a36Sopenharmony_ci
267162306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
267462306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_INITIAL;
267562306a36Sopenharmony_ci	req->state_sz = SHA3_512_DIGEST_SIZE;
267662306a36Sopenharmony_ci	req->digest_sz = SHA3_512_DIGEST_SIZE;
267762306a36Sopenharmony_ci	req->block_sz = SHA3_512_BLOCK_SIZE;
267862306a36Sopenharmony_ci	ctx->do_fallback = false;
267962306a36Sopenharmony_ci	ctx->fb_init_done = false;
268062306a36Sopenharmony_ci	return 0;
268162306a36Sopenharmony_ci}
268262306a36Sopenharmony_ci
268362306a36Sopenharmony_cistatic int safexcel_sha3_512_digest(struct ahash_request *req)
268462306a36Sopenharmony_ci{
268562306a36Sopenharmony_ci	if (req->nbytes)
268662306a36Sopenharmony_ci		return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req);
268762306a36Sopenharmony_ci
268862306a36Sopenharmony_ci	/* HW cannot do zero length hash, use fallback instead */
268962306a36Sopenharmony_ci	return safexcel_sha3_digest_fallback(req);
269062306a36Sopenharmony_ci}
269162306a36Sopenharmony_ci
269262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_512 = {
269362306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
269462306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA3,
269562306a36Sopenharmony_ci	.alg.ahash = {
269662306a36Sopenharmony_ci		.init = safexcel_sha3_512_init,
269762306a36Sopenharmony_ci		.update = safexcel_sha3_update,
269862306a36Sopenharmony_ci		.final = safexcel_sha3_final,
269962306a36Sopenharmony_ci		.finup = safexcel_sha3_finup,
270062306a36Sopenharmony_ci		.digest = safexcel_sha3_512_digest,
270162306a36Sopenharmony_ci		.export = safexcel_sha3_export,
270262306a36Sopenharmony_ci		.import = safexcel_sha3_import,
270362306a36Sopenharmony_ci		.halg = {
270462306a36Sopenharmony_ci			.digestsize = SHA3_512_DIGEST_SIZE,
270562306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
270662306a36Sopenharmony_ci			.base = {
270762306a36Sopenharmony_ci				.cra_name = "sha3-512",
270862306a36Sopenharmony_ci				.cra_driver_name = "safexcel-sha3-512",
270962306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
271062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
271162306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY |
271262306a36Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK,
271362306a36Sopenharmony_ci				.cra_blocksize = SHA3_512_BLOCK_SIZE,
271462306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
271562306a36Sopenharmony_ci				.cra_init = safexcel_sha3_cra_init,
271662306a36Sopenharmony_ci				.cra_exit = safexcel_sha3_cra_exit,
271762306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
271862306a36Sopenharmony_ci			},
271962306a36Sopenharmony_ci		},
272062306a36Sopenharmony_ci	},
272162306a36Sopenharmony_ci};
272262306a36Sopenharmony_ci
272362306a36Sopenharmony_cistatic int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg)
272462306a36Sopenharmony_ci{
272562306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
272662306a36Sopenharmony_ci	int ret;
272762306a36Sopenharmony_ci
272862306a36Sopenharmony_ci	ret = safexcel_sha3_cra_init(tfm);
272962306a36Sopenharmony_ci	if (ret)
273062306a36Sopenharmony_ci		return ret;
273162306a36Sopenharmony_ci
273262306a36Sopenharmony_ci	/* Allocate precalc basic digest implementation */
273362306a36Sopenharmony_ci	ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
273462306a36Sopenharmony_ci	if (IS_ERR(ctx->shpre))
273562306a36Sopenharmony_ci		return PTR_ERR(ctx->shpre);
273662306a36Sopenharmony_ci
273762306a36Sopenharmony_ci	ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) +
273862306a36Sopenharmony_ci			      crypto_shash_descsize(ctx->shpre), GFP_KERNEL);
273962306a36Sopenharmony_ci	if (!ctx->shdesc) {
274062306a36Sopenharmony_ci		crypto_free_shash(ctx->shpre);
274162306a36Sopenharmony_ci		return -ENOMEM;
274262306a36Sopenharmony_ci	}
274362306a36Sopenharmony_ci	ctx->shdesc->tfm = ctx->shpre;
274462306a36Sopenharmony_ci	return 0;
274562306a36Sopenharmony_ci}
274662306a36Sopenharmony_ci
274762306a36Sopenharmony_cistatic void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm)
274862306a36Sopenharmony_ci{
274962306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
275062306a36Sopenharmony_ci
275162306a36Sopenharmony_ci	crypto_free_ahash(ctx->fback);
275262306a36Sopenharmony_ci	crypto_free_shash(ctx->shpre);
275362306a36Sopenharmony_ci	kfree(ctx->shdesc);
275462306a36Sopenharmony_ci	safexcel_ahash_cra_exit(tfm);
275562306a36Sopenharmony_ci}
275662306a36Sopenharmony_ci
275762306a36Sopenharmony_cistatic int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key,
275862306a36Sopenharmony_ci				     unsigned int keylen)
275962306a36Sopenharmony_ci{
276062306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
276162306a36Sopenharmony_ci	int ret = 0;
276262306a36Sopenharmony_ci
276362306a36Sopenharmony_ci	if (keylen > crypto_ahash_blocksize(tfm)) {
276462306a36Sopenharmony_ci		/*
276562306a36Sopenharmony_ci		 * If the key is larger than the blocksize, then hash it
276662306a36Sopenharmony_ci		 * first using our fallback cipher
276762306a36Sopenharmony_ci		 */
276862306a36Sopenharmony_ci		ret = crypto_shash_digest(ctx->shdesc, key, keylen,
276962306a36Sopenharmony_ci					  ctx->base.ipad.byte);
277062306a36Sopenharmony_ci		keylen = crypto_shash_digestsize(ctx->shpre);
277162306a36Sopenharmony_ci
277262306a36Sopenharmony_ci		/*
277362306a36Sopenharmony_ci		 * If the digest is larger than half the blocksize, we need to
277462306a36Sopenharmony_ci		 * move the rest to opad due to the way our HMAC infra works.
277562306a36Sopenharmony_ci		 */
277662306a36Sopenharmony_ci		if (keylen > crypto_ahash_blocksize(tfm) / 2)
277762306a36Sopenharmony_ci			/* Buffers overlap, need to use memmove iso memcpy! */
277862306a36Sopenharmony_ci			memmove(&ctx->base.opad,
277962306a36Sopenharmony_ci				ctx->base.ipad.byte +
278062306a36Sopenharmony_ci					crypto_ahash_blocksize(tfm) / 2,
278162306a36Sopenharmony_ci				keylen - crypto_ahash_blocksize(tfm) / 2);
278262306a36Sopenharmony_ci	} else {
278362306a36Sopenharmony_ci		/*
278462306a36Sopenharmony_ci		 * Copy the key to our ipad & opad buffers
278562306a36Sopenharmony_ci		 * Note that ipad and opad each contain one half of the key,
278662306a36Sopenharmony_ci		 * to match the existing HMAC driver infrastructure.
278762306a36Sopenharmony_ci		 */
278862306a36Sopenharmony_ci		if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
278962306a36Sopenharmony_ci			memcpy(&ctx->base.ipad, key, keylen);
279062306a36Sopenharmony_ci		} else {
279162306a36Sopenharmony_ci			memcpy(&ctx->base.ipad, key,
279262306a36Sopenharmony_ci			       crypto_ahash_blocksize(tfm) / 2);
279362306a36Sopenharmony_ci			memcpy(&ctx->base.opad,
279462306a36Sopenharmony_ci			       key + crypto_ahash_blocksize(tfm) / 2,
279562306a36Sopenharmony_ci			       keylen - crypto_ahash_blocksize(tfm) / 2);
279662306a36Sopenharmony_ci		}
279762306a36Sopenharmony_ci	}
279862306a36Sopenharmony_ci
279962306a36Sopenharmony_ci	/* Pad key with zeroes */
280062306a36Sopenharmony_ci	if (keylen <= crypto_ahash_blocksize(tfm) / 2) {
280162306a36Sopenharmony_ci		memset(ctx->base.ipad.byte + keylen, 0,
280262306a36Sopenharmony_ci		       crypto_ahash_blocksize(tfm) / 2 - keylen);
280362306a36Sopenharmony_ci		memset(&ctx->base.opad, 0, crypto_ahash_blocksize(tfm) / 2);
280462306a36Sopenharmony_ci	} else {
280562306a36Sopenharmony_ci		memset(ctx->base.opad.byte + keylen -
280662306a36Sopenharmony_ci		       crypto_ahash_blocksize(tfm) / 2, 0,
280762306a36Sopenharmony_ci		       crypto_ahash_blocksize(tfm) - keylen);
280862306a36Sopenharmony_ci	}
280962306a36Sopenharmony_ci
281062306a36Sopenharmony_ci	/* If doing fallback, still need to set the new key! */
281162306a36Sopenharmony_ci	ctx->fb_do_setkey = true;
281262306a36Sopenharmony_ci	return ret;
281362306a36Sopenharmony_ci}
281462306a36Sopenharmony_ci
281562306a36Sopenharmony_cistatic int safexcel_hmac_sha3_224_init(struct ahash_request *areq)
281662306a36Sopenharmony_ci{
281762306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
281862306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
281962306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
282062306a36Sopenharmony_ci
282162306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
282262306a36Sopenharmony_ci
282362306a36Sopenharmony_ci	/* Copy (half of) the key */
282462306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SHA3_224_BLOCK_SIZE / 2);
282562306a36Sopenharmony_ci	/* Start of HMAC should have len == processed == blocksize */
282662306a36Sopenharmony_ci	req->len	= SHA3_224_BLOCK_SIZE;
282762306a36Sopenharmony_ci	req->processed	= SHA3_224_BLOCK_SIZE;
282862306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224;
282962306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
283062306a36Sopenharmony_ci	req->state_sz = SHA3_224_BLOCK_SIZE / 2;
283162306a36Sopenharmony_ci	req->digest_sz = SHA3_224_DIGEST_SIZE;
283262306a36Sopenharmony_ci	req->block_sz = SHA3_224_BLOCK_SIZE;
283362306a36Sopenharmony_ci	req->hmac = true;
283462306a36Sopenharmony_ci	ctx->do_fallback = false;
283562306a36Sopenharmony_ci	ctx->fb_init_done = false;
283662306a36Sopenharmony_ci	return 0;
283762306a36Sopenharmony_ci}
283862306a36Sopenharmony_ci
283962306a36Sopenharmony_cistatic int safexcel_hmac_sha3_224_digest(struct ahash_request *req)
284062306a36Sopenharmony_ci{
284162306a36Sopenharmony_ci	if (req->nbytes)
284262306a36Sopenharmony_ci		return safexcel_hmac_sha3_224_init(req) ?:
284362306a36Sopenharmony_ci		       safexcel_ahash_finup(req);
284462306a36Sopenharmony_ci
284562306a36Sopenharmony_ci	/* HW cannot do zero length HMAC, use fallback instead */
284662306a36Sopenharmony_ci	return safexcel_sha3_digest_fallback(req);
284762306a36Sopenharmony_ci}
284862306a36Sopenharmony_ci
284962306a36Sopenharmony_cistatic int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm)
285062306a36Sopenharmony_ci{
285162306a36Sopenharmony_ci	return safexcel_hmac_sha3_cra_init(tfm, "sha3-224");
285262306a36Sopenharmony_ci}
285362306a36Sopenharmony_ci
285462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_224 = {
285562306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
285662306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA3,
285762306a36Sopenharmony_ci	.alg.ahash = {
285862306a36Sopenharmony_ci		.init = safexcel_hmac_sha3_224_init,
285962306a36Sopenharmony_ci		.update = safexcel_sha3_update,
286062306a36Sopenharmony_ci		.final = safexcel_sha3_final,
286162306a36Sopenharmony_ci		.finup = safexcel_sha3_finup,
286262306a36Sopenharmony_ci		.digest = safexcel_hmac_sha3_224_digest,
286362306a36Sopenharmony_ci		.setkey = safexcel_hmac_sha3_setkey,
286462306a36Sopenharmony_ci		.export = safexcel_sha3_export,
286562306a36Sopenharmony_ci		.import = safexcel_sha3_import,
286662306a36Sopenharmony_ci		.halg = {
286762306a36Sopenharmony_ci			.digestsize = SHA3_224_DIGEST_SIZE,
286862306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
286962306a36Sopenharmony_ci			.base = {
287062306a36Sopenharmony_ci				.cra_name = "hmac(sha3-224)",
287162306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sha3-224",
287262306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
287362306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
287462306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY |
287562306a36Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK,
287662306a36Sopenharmony_ci				.cra_blocksize = SHA3_224_BLOCK_SIZE,
287762306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
287862306a36Sopenharmony_ci				.cra_init = safexcel_hmac_sha3_224_cra_init,
287962306a36Sopenharmony_ci				.cra_exit = safexcel_hmac_sha3_cra_exit,
288062306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
288162306a36Sopenharmony_ci			},
288262306a36Sopenharmony_ci		},
288362306a36Sopenharmony_ci	},
288462306a36Sopenharmony_ci};
288562306a36Sopenharmony_ci
288662306a36Sopenharmony_cistatic int safexcel_hmac_sha3_256_init(struct ahash_request *areq)
288762306a36Sopenharmony_ci{
288862306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
288962306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
289062306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
289162306a36Sopenharmony_ci
289262306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
289362306a36Sopenharmony_ci
289462306a36Sopenharmony_ci	/* Copy (half of) the key */
289562306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SHA3_256_BLOCK_SIZE / 2);
289662306a36Sopenharmony_ci	/* Start of HMAC should have len == processed == blocksize */
289762306a36Sopenharmony_ci	req->len	= SHA3_256_BLOCK_SIZE;
289862306a36Sopenharmony_ci	req->processed	= SHA3_256_BLOCK_SIZE;
289962306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256;
290062306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
290162306a36Sopenharmony_ci	req->state_sz = SHA3_256_BLOCK_SIZE / 2;
290262306a36Sopenharmony_ci	req->digest_sz = SHA3_256_DIGEST_SIZE;
290362306a36Sopenharmony_ci	req->block_sz = SHA3_256_BLOCK_SIZE;
290462306a36Sopenharmony_ci	req->hmac = true;
290562306a36Sopenharmony_ci	ctx->do_fallback = false;
290662306a36Sopenharmony_ci	ctx->fb_init_done = false;
290762306a36Sopenharmony_ci	return 0;
290862306a36Sopenharmony_ci}
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_cistatic int safexcel_hmac_sha3_256_digest(struct ahash_request *req)
291162306a36Sopenharmony_ci{
291262306a36Sopenharmony_ci	if (req->nbytes)
291362306a36Sopenharmony_ci		return safexcel_hmac_sha3_256_init(req) ?:
291462306a36Sopenharmony_ci		       safexcel_ahash_finup(req);
291562306a36Sopenharmony_ci
291662306a36Sopenharmony_ci	/* HW cannot do zero length HMAC, use fallback instead */
291762306a36Sopenharmony_ci	return safexcel_sha3_digest_fallback(req);
291862306a36Sopenharmony_ci}
291962306a36Sopenharmony_ci
292062306a36Sopenharmony_cistatic int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm)
292162306a36Sopenharmony_ci{
292262306a36Sopenharmony_ci	return safexcel_hmac_sha3_cra_init(tfm, "sha3-256");
292362306a36Sopenharmony_ci}
292462306a36Sopenharmony_ci
292562306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_256 = {
292662306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
292762306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA3,
292862306a36Sopenharmony_ci	.alg.ahash = {
292962306a36Sopenharmony_ci		.init = safexcel_hmac_sha3_256_init,
293062306a36Sopenharmony_ci		.update = safexcel_sha3_update,
293162306a36Sopenharmony_ci		.final = safexcel_sha3_final,
293262306a36Sopenharmony_ci		.finup = safexcel_sha3_finup,
293362306a36Sopenharmony_ci		.digest = safexcel_hmac_sha3_256_digest,
293462306a36Sopenharmony_ci		.setkey = safexcel_hmac_sha3_setkey,
293562306a36Sopenharmony_ci		.export = safexcel_sha3_export,
293662306a36Sopenharmony_ci		.import = safexcel_sha3_import,
293762306a36Sopenharmony_ci		.halg = {
293862306a36Sopenharmony_ci			.digestsize = SHA3_256_DIGEST_SIZE,
293962306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
294062306a36Sopenharmony_ci			.base = {
294162306a36Sopenharmony_ci				.cra_name = "hmac(sha3-256)",
294262306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sha3-256",
294362306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
294462306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
294562306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY |
294662306a36Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK,
294762306a36Sopenharmony_ci				.cra_blocksize = SHA3_256_BLOCK_SIZE,
294862306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
294962306a36Sopenharmony_ci				.cra_init = safexcel_hmac_sha3_256_cra_init,
295062306a36Sopenharmony_ci				.cra_exit = safexcel_hmac_sha3_cra_exit,
295162306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
295262306a36Sopenharmony_ci			},
295362306a36Sopenharmony_ci		},
295462306a36Sopenharmony_ci	},
295562306a36Sopenharmony_ci};
295662306a36Sopenharmony_ci
295762306a36Sopenharmony_cistatic int safexcel_hmac_sha3_384_init(struct ahash_request *areq)
295862306a36Sopenharmony_ci{
295962306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
296062306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
296162306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
296262306a36Sopenharmony_ci
296362306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
296462306a36Sopenharmony_ci
296562306a36Sopenharmony_ci	/* Copy (half of) the key */
296662306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SHA3_384_BLOCK_SIZE / 2);
296762306a36Sopenharmony_ci	/* Start of HMAC should have len == processed == blocksize */
296862306a36Sopenharmony_ci	req->len	= SHA3_384_BLOCK_SIZE;
296962306a36Sopenharmony_ci	req->processed	= SHA3_384_BLOCK_SIZE;
297062306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384;
297162306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
297262306a36Sopenharmony_ci	req->state_sz = SHA3_384_BLOCK_SIZE / 2;
297362306a36Sopenharmony_ci	req->digest_sz = SHA3_384_DIGEST_SIZE;
297462306a36Sopenharmony_ci	req->block_sz = SHA3_384_BLOCK_SIZE;
297562306a36Sopenharmony_ci	req->hmac = true;
297662306a36Sopenharmony_ci	ctx->do_fallback = false;
297762306a36Sopenharmony_ci	ctx->fb_init_done = false;
297862306a36Sopenharmony_ci	return 0;
297962306a36Sopenharmony_ci}
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_cistatic int safexcel_hmac_sha3_384_digest(struct ahash_request *req)
298262306a36Sopenharmony_ci{
298362306a36Sopenharmony_ci	if (req->nbytes)
298462306a36Sopenharmony_ci		return safexcel_hmac_sha3_384_init(req) ?:
298562306a36Sopenharmony_ci		       safexcel_ahash_finup(req);
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci	/* HW cannot do zero length HMAC, use fallback instead */
298862306a36Sopenharmony_ci	return safexcel_sha3_digest_fallback(req);
298962306a36Sopenharmony_ci}
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_cistatic int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm)
299262306a36Sopenharmony_ci{
299362306a36Sopenharmony_ci	return safexcel_hmac_sha3_cra_init(tfm, "sha3-384");
299462306a36Sopenharmony_ci}
299562306a36Sopenharmony_ci
299662306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_384 = {
299762306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
299862306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA3,
299962306a36Sopenharmony_ci	.alg.ahash = {
300062306a36Sopenharmony_ci		.init = safexcel_hmac_sha3_384_init,
300162306a36Sopenharmony_ci		.update = safexcel_sha3_update,
300262306a36Sopenharmony_ci		.final = safexcel_sha3_final,
300362306a36Sopenharmony_ci		.finup = safexcel_sha3_finup,
300462306a36Sopenharmony_ci		.digest = safexcel_hmac_sha3_384_digest,
300562306a36Sopenharmony_ci		.setkey = safexcel_hmac_sha3_setkey,
300662306a36Sopenharmony_ci		.export = safexcel_sha3_export,
300762306a36Sopenharmony_ci		.import = safexcel_sha3_import,
300862306a36Sopenharmony_ci		.halg = {
300962306a36Sopenharmony_ci			.digestsize = SHA3_384_DIGEST_SIZE,
301062306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
301162306a36Sopenharmony_ci			.base = {
301262306a36Sopenharmony_ci				.cra_name = "hmac(sha3-384)",
301362306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sha3-384",
301462306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
301562306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
301662306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY |
301762306a36Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK,
301862306a36Sopenharmony_ci				.cra_blocksize = SHA3_384_BLOCK_SIZE,
301962306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
302062306a36Sopenharmony_ci				.cra_init = safexcel_hmac_sha3_384_cra_init,
302162306a36Sopenharmony_ci				.cra_exit = safexcel_hmac_sha3_cra_exit,
302262306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
302362306a36Sopenharmony_ci			},
302462306a36Sopenharmony_ci		},
302562306a36Sopenharmony_ci	},
302662306a36Sopenharmony_ci};
302762306a36Sopenharmony_ci
302862306a36Sopenharmony_cistatic int safexcel_hmac_sha3_512_init(struct ahash_request *areq)
302962306a36Sopenharmony_ci{
303062306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
303162306a36Sopenharmony_ci	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
303262306a36Sopenharmony_ci	struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq);
303362306a36Sopenharmony_ci
303462306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_ci	/* Copy (half of) the key */
303762306a36Sopenharmony_ci	memcpy(req->state, &ctx->base.ipad, SHA3_512_BLOCK_SIZE / 2);
303862306a36Sopenharmony_ci	/* Start of HMAC should have len == processed == blocksize */
303962306a36Sopenharmony_ci	req->len	= SHA3_512_BLOCK_SIZE;
304062306a36Sopenharmony_ci	req->processed	= SHA3_512_BLOCK_SIZE;
304162306a36Sopenharmony_ci	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512;
304262306a36Sopenharmony_ci	req->digest = CONTEXT_CONTROL_DIGEST_HMAC;
304362306a36Sopenharmony_ci	req->state_sz = SHA3_512_BLOCK_SIZE / 2;
304462306a36Sopenharmony_ci	req->digest_sz = SHA3_512_DIGEST_SIZE;
304562306a36Sopenharmony_ci	req->block_sz = SHA3_512_BLOCK_SIZE;
304662306a36Sopenharmony_ci	req->hmac = true;
304762306a36Sopenharmony_ci	ctx->do_fallback = false;
304862306a36Sopenharmony_ci	ctx->fb_init_done = false;
304962306a36Sopenharmony_ci	return 0;
305062306a36Sopenharmony_ci}
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_cistatic int safexcel_hmac_sha3_512_digest(struct ahash_request *req)
305362306a36Sopenharmony_ci{
305462306a36Sopenharmony_ci	if (req->nbytes)
305562306a36Sopenharmony_ci		return safexcel_hmac_sha3_512_init(req) ?:
305662306a36Sopenharmony_ci		       safexcel_ahash_finup(req);
305762306a36Sopenharmony_ci
305862306a36Sopenharmony_ci	/* HW cannot do zero length HMAC, use fallback instead */
305962306a36Sopenharmony_ci	return safexcel_sha3_digest_fallback(req);
306062306a36Sopenharmony_ci}
306162306a36Sopenharmony_ci
306262306a36Sopenharmony_cistatic int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm)
306362306a36Sopenharmony_ci{
306462306a36Sopenharmony_ci	return safexcel_hmac_sha3_cra_init(tfm, "sha3-512");
306562306a36Sopenharmony_ci}
306662306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_512 = {
306762306a36Sopenharmony_ci	.type = SAFEXCEL_ALG_TYPE_AHASH,
306862306a36Sopenharmony_ci	.algo_mask = SAFEXCEL_ALG_SHA3,
306962306a36Sopenharmony_ci	.alg.ahash = {
307062306a36Sopenharmony_ci		.init = safexcel_hmac_sha3_512_init,
307162306a36Sopenharmony_ci		.update = safexcel_sha3_update,
307262306a36Sopenharmony_ci		.final = safexcel_sha3_final,
307362306a36Sopenharmony_ci		.finup = safexcel_sha3_finup,
307462306a36Sopenharmony_ci		.digest = safexcel_hmac_sha3_512_digest,
307562306a36Sopenharmony_ci		.setkey = safexcel_hmac_sha3_setkey,
307662306a36Sopenharmony_ci		.export = safexcel_sha3_export,
307762306a36Sopenharmony_ci		.import = safexcel_sha3_import,
307862306a36Sopenharmony_ci		.halg = {
307962306a36Sopenharmony_ci			.digestsize = SHA3_512_DIGEST_SIZE,
308062306a36Sopenharmony_ci			.statesize = sizeof(struct safexcel_ahash_export_state),
308162306a36Sopenharmony_ci			.base = {
308262306a36Sopenharmony_ci				.cra_name = "hmac(sha3-512)",
308362306a36Sopenharmony_ci				.cra_driver_name = "safexcel-hmac-sha3-512",
308462306a36Sopenharmony_ci				.cra_priority = SAFEXCEL_CRA_PRIORITY,
308562306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
308662306a36Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY |
308762306a36Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK,
308862306a36Sopenharmony_ci				.cra_blocksize = SHA3_512_BLOCK_SIZE,
308962306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
309062306a36Sopenharmony_ci				.cra_init = safexcel_hmac_sha3_512_cra_init,
309162306a36Sopenharmony_ci				.cra_exit = safexcel_hmac_sha3_cra_exit,
309262306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
309362306a36Sopenharmony_ci			},
309462306a36Sopenharmony_ci		},
309562306a36Sopenharmony_ci	},
309662306a36Sopenharmony_ci};
3097