162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/kernel.h>
562306a36Sopenharmony_ci#include <linux/module.h>
662306a36Sopenharmony_ci#include <crypto/algapi.h>
762306a36Sopenharmony_ci#include <crypto/internal/aead.h>
862306a36Sopenharmony_ci#include <crypto/authenc.h>
962306a36Sopenharmony_ci#include <crypto/gcm.h>
1062306a36Sopenharmony_ci#include <linux/rtnetlink.h>
1162306a36Sopenharmony_ci#include <crypto/internal/des.h>
1262306a36Sopenharmony_ci#include "cc_driver.h"
1362306a36Sopenharmony_ci#include "cc_buffer_mgr.h"
1462306a36Sopenharmony_ci#include "cc_aead.h"
1562306a36Sopenharmony_ci#include "cc_request_mgr.h"
1662306a36Sopenharmony_ci#include "cc_hash.h"
1762306a36Sopenharmony_ci#include "cc_sram_mgr.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define template_aead	template_u.aead
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define MAX_AEAD_SETKEY_SEQ 12
2262306a36Sopenharmony_ci#define MAX_AEAD_PROCESS_SEQ 23
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define MAX_HMAC_DIGEST_SIZE (SHA256_DIGEST_SIZE)
2562306a36Sopenharmony_ci#define MAX_HMAC_BLOCK_SIZE (SHA256_BLOCK_SIZE)
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define MAX_NONCE_SIZE CTR_RFC3686_NONCE_SIZE
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistruct cc_aead_handle {
3062306a36Sopenharmony_ci	u32 sram_workspace_addr;
3162306a36Sopenharmony_ci	struct list_head aead_list;
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistruct cc_hmac_s {
3562306a36Sopenharmony_ci	u8 *padded_authkey;
3662306a36Sopenharmony_ci	u8 *ipad_opad; /* IPAD, OPAD*/
3762306a36Sopenharmony_ci	dma_addr_t padded_authkey_dma_addr;
3862306a36Sopenharmony_ci	dma_addr_t ipad_opad_dma_addr;
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct cc_xcbc_s {
4262306a36Sopenharmony_ci	u8 *xcbc_keys; /* K1,K2,K3 */
4362306a36Sopenharmony_ci	dma_addr_t xcbc_keys_dma_addr;
4462306a36Sopenharmony_ci};
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistruct cc_aead_ctx {
4762306a36Sopenharmony_ci	struct cc_drvdata *drvdata;
4862306a36Sopenharmony_ci	u8 ctr_nonce[MAX_NONCE_SIZE]; /* used for ctr3686 iv and aes ccm */
4962306a36Sopenharmony_ci	u8 *enckey;
5062306a36Sopenharmony_ci	dma_addr_t enckey_dma_addr;
5162306a36Sopenharmony_ci	union {
5262306a36Sopenharmony_ci		struct cc_hmac_s hmac;
5362306a36Sopenharmony_ci		struct cc_xcbc_s xcbc;
5462306a36Sopenharmony_ci	} auth_state;
5562306a36Sopenharmony_ci	unsigned int enc_keylen;
5662306a36Sopenharmony_ci	unsigned int auth_keylen;
5762306a36Sopenharmony_ci	unsigned int authsize; /* Actual (reduced?) size of the MAC/ICv */
5862306a36Sopenharmony_ci	unsigned int hash_len;
5962306a36Sopenharmony_ci	enum drv_cipher_mode cipher_mode;
6062306a36Sopenharmony_ci	enum cc_flow_mode flow_mode;
6162306a36Sopenharmony_ci	enum drv_hash_mode auth_mode;
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic void cc_aead_exit(struct crypto_aead *tfm)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
6762306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	dev_dbg(dev, "Clearing context @%p for %s\n", crypto_aead_ctx(tfm),
7062306a36Sopenharmony_ci		crypto_tfm_alg_name(&tfm->base));
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	/* Unmap enckey buffer */
7362306a36Sopenharmony_ci	if (ctx->enckey) {
7462306a36Sopenharmony_ci		dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey,
7562306a36Sopenharmony_ci				  ctx->enckey_dma_addr);
7662306a36Sopenharmony_ci		dev_dbg(dev, "Freed enckey DMA buffer enckey_dma_addr=%pad\n",
7762306a36Sopenharmony_ci			&ctx->enckey_dma_addr);
7862306a36Sopenharmony_ci		ctx->enckey_dma_addr = 0;
7962306a36Sopenharmony_ci		ctx->enckey = NULL;
8062306a36Sopenharmony_ci	}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */
8362306a36Sopenharmony_ci		struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci		if (xcbc->xcbc_keys) {
8662306a36Sopenharmony_ci			dma_free_coherent(dev, CC_AES_128_BIT_KEY_SIZE * 3,
8762306a36Sopenharmony_ci					  xcbc->xcbc_keys,
8862306a36Sopenharmony_ci					  xcbc->xcbc_keys_dma_addr);
8962306a36Sopenharmony_ci		}
9062306a36Sopenharmony_ci		dev_dbg(dev, "Freed xcbc_keys DMA buffer xcbc_keys_dma_addr=%pad\n",
9162306a36Sopenharmony_ci			&xcbc->xcbc_keys_dma_addr);
9262306a36Sopenharmony_ci		xcbc->xcbc_keys_dma_addr = 0;
9362306a36Sopenharmony_ci		xcbc->xcbc_keys = NULL;
9462306a36Sopenharmony_ci	} else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC auth. */
9562306a36Sopenharmony_ci		struct cc_hmac_s *hmac = &ctx->auth_state.hmac;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci		if (hmac->ipad_opad) {
9862306a36Sopenharmony_ci			dma_free_coherent(dev, 2 * MAX_HMAC_DIGEST_SIZE,
9962306a36Sopenharmony_ci					  hmac->ipad_opad,
10062306a36Sopenharmony_ci					  hmac->ipad_opad_dma_addr);
10162306a36Sopenharmony_ci			dev_dbg(dev, "Freed ipad_opad DMA buffer ipad_opad_dma_addr=%pad\n",
10262306a36Sopenharmony_ci				&hmac->ipad_opad_dma_addr);
10362306a36Sopenharmony_ci			hmac->ipad_opad_dma_addr = 0;
10462306a36Sopenharmony_ci			hmac->ipad_opad = NULL;
10562306a36Sopenharmony_ci		}
10662306a36Sopenharmony_ci		if (hmac->padded_authkey) {
10762306a36Sopenharmony_ci			dma_free_coherent(dev, MAX_HMAC_BLOCK_SIZE,
10862306a36Sopenharmony_ci					  hmac->padded_authkey,
10962306a36Sopenharmony_ci					  hmac->padded_authkey_dma_addr);
11062306a36Sopenharmony_ci			dev_dbg(dev, "Freed padded_authkey DMA buffer padded_authkey_dma_addr=%pad\n",
11162306a36Sopenharmony_ci				&hmac->padded_authkey_dma_addr);
11262306a36Sopenharmony_ci			hmac->padded_authkey_dma_addr = 0;
11362306a36Sopenharmony_ci			hmac->padded_authkey = NULL;
11462306a36Sopenharmony_ci		}
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic unsigned int cc_get_aead_hash_len(struct crypto_aead *tfm)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	return cc_get_default_hash_len(ctx->drvdata);
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic int cc_aead_init(struct crypto_aead *tfm)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(tfm);
12862306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
12962306a36Sopenharmony_ci	struct cc_crypto_alg *cc_alg =
13062306a36Sopenharmony_ci			container_of(alg, struct cc_crypto_alg, aead_alg);
13162306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(cc_alg->drvdata);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	dev_dbg(dev, "Initializing context @%p for %s\n", ctx,
13462306a36Sopenharmony_ci		crypto_tfm_alg_name(&tfm->base));
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	/* Initialize modes in instance */
13762306a36Sopenharmony_ci	ctx->cipher_mode = cc_alg->cipher_mode;
13862306a36Sopenharmony_ci	ctx->flow_mode = cc_alg->flow_mode;
13962306a36Sopenharmony_ci	ctx->auth_mode = cc_alg->auth_mode;
14062306a36Sopenharmony_ci	ctx->drvdata = cc_alg->drvdata;
14162306a36Sopenharmony_ci	crypto_aead_set_reqsize_dma(tfm, sizeof(struct aead_req_ctx));
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	/* Allocate key buffer, cache line aligned */
14462306a36Sopenharmony_ci	ctx->enckey = dma_alloc_coherent(dev, AES_MAX_KEY_SIZE,
14562306a36Sopenharmony_ci					 &ctx->enckey_dma_addr, GFP_KERNEL);
14662306a36Sopenharmony_ci	if (!ctx->enckey) {
14762306a36Sopenharmony_ci		dev_err(dev, "Failed allocating key buffer\n");
14862306a36Sopenharmony_ci		goto init_failed;
14962306a36Sopenharmony_ci	}
15062306a36Sopenharmony_ci	dev_dbg(dev, "Allocated enckey buffer in context ctx->enckey=@%p\n",
15162306a36Sopenharmony_ci		ctx->enckey);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	/* Set default authlen value */
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */
15662306a36Sopenharmony_ci		struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc;
15762306a36Sopenharmony_ci		const unsigned int key_size = CC_AES_128_BIT_KEY_SIZE * 3;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci		/* Allocate dma-coherent buffer for XCBC's K1+K2+K3 */
16062306a36Sopenharmony_ci		/* (and temporary for user key - up to 256b) */
16162306a36Sopenharmony_ci		xcbc->xcbc_keys = dma_alloc_coherent(dev, key_size,
16262306a36Sopenharmony_ci						     &xcbc->xcbc_keys_dma_addr,
16362306a36Sopenharmony_ci						     GFP_KERNEL);
16462306a36Sopenharmony_ci		if (!xcbc->xcbc_keys) {
16562306a36Sopenharmony_ci			dev_err(dev, "Failed allocating buffer for XCBC keys\n");
16662306a36Sopenharmony_ci			goto init_failed;
16762306a36Sopenharmony_ci		}
16862306a36Sopenharmony_ci	} else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC authentication */
16962306a36Sopenharmony_ci		struct cc_hmac_s *hmac = &ctx->auth_state.hmac;
17062306a36Sopenharmony_ci		const unsigned int digest_size = 2 * MAX_HMAC_DIGEST_SIZE;
17162306a36Sopenharmony_ci		dma_addr_t *pkey_dma = &hmac->padded_authkey_dma_addr;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci		/* Allocate dma-coherent buffer for IPAD + OPAD */
17462306a36Sopenharmony_ci		hmac->ipad_opad = dma_alloc_coherent(dev, digest_size,
17562306a36Sopenharmony_ci						     &hmac->ipad_opad_dma_addr,
17662306a36Sopenharmony_ci						     GFP_KERNEL);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci		if (!hmac->ipad_opad) {
17962306a36Sopenharmony_ci			dev_err(dev, "Failed allocating IPAD/OPAD buffer\n");
18062306a36Sopenharmony_ci			goto init_failed;
18162306a36Sopenharmony_ci		}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci		dev_dbg(dev, "Allocated authkey buffer in context ctx->authkey=@%p\n",
18462306a36Sopenharmony_ci			hmac->ipad_opad);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci		hmac->padded_authkey = dma_alloc_coherent(dev,
18762306a36Sopenharmony_ci							  MAX_HMAC_BLOCK_SIZE,
18862306a36Sopenharmony_ci							  pkey_dma,
18962306a36Sopenharmony_ci							  GFP_KERNEL);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci		if (!hmac->padded_authkey) {
19262306a36Sopenharmony_ci			dev_err(dev, "failed to allocate padded_authkey\n");
19362306a36Sopenharmony_ci			goto init_failed;
19462306a36Sopenharmony_ci		}
19562306a36Sopenharmony_ci	} else {
19662306a36Sopenharmony_ci		ctx->auth_state.hmac.ipad_opad = NULL;
19762306a36Sopenharmony_ci		ctx->auth_state.hmac.padded_authkey = NULL;
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci	ctx->hash_len = cc_get_aead_hash_len(tfm);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	return 0;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ciinit_failed:
20462306a36Sopenharmony_ci	cc_aead_exit(tfm);
20562306a36Sopenharmony_ci	return -ENOMEM;
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_cistatic void cc_aead_complete(struct device *dev, void *cc_req, int err)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	struct aead_request *areq = (struct aead_request *)cc_req;
21162306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(areq);
21262306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(cc_req);
21362306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	/* BACKLOG notification */
21662306a36Sopenharmony_ci	if (err == -EINPROGRESS)
21762306a36Sopenharmony_ci		goto done;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	cc_unmap_aead_request(dev, areq);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	/* Restore ordinary iv pointer */
22262306a36Sopenharmony_ci	areq->iv = areq_ctx->backup_iv;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	if (err)
22562306a36Sopenharmony_ci		goto done;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
22862306a36Sopenharmony_ci		if (memcmp(areq_ctx->mac_buf, areq_ctx->icv_virt_addr,
22962306a36Sopenharmony_ci			   ctx->authsize) != 0) {
23062306a36Sopenharmony_ci			dev_dbg(dev, "Payload authentication failure, (auth-size=%d, cipher=%d)\n",
23162306a36Sopenharmony_ci				ctx->authsize, ctx->cipher_mode);
23262306a36Sopenharmony_ci			/* In case of payload authentication failure, MUST NOT
23362306a36Sopenharmony_ci			 * revealed the decrypted message --> zero its memory.
23462306a36Sopenharmony_ci			 */
23562306a36Sopenharmony_ci			sg_zero_buffer(areq->dst, sg_nents(areq->dst),
23662306a36Sopenharmony_ci				       areq->cryptlen, areq->assoclen);
23762306a36Sopenharmony_ci			err = -EBADMSG;
23862306a36Sopenharmony_ci		}
23962306a36Sopenharmony_ci	/*ENCRYPT*/
24062306a36Sopenharmony_ci	} else if (areq_ctx->is_icv_fragmented) {
24162306a36Sopenharmony_ci		u32 skip = areq->cryptlen + areq_ctx->dst_offset;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci		cc_copy_sg_portion(dev, areq_ctx->mac_buf, areq_ctx->dst_sgl,
24462306a36Sopenharmony_ci				   skip, (skip + ctx->authsize),
24562306a36Sopenharmony_ci				   CC_SG_FROM_BUF);
24662306a36Sopenharmony_ci	}
24762306a36Sopenharmony_cidone:
24862306a36Sopenharmony_ci	aead_request_complete(areq, err);
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic unsigned int xcbc_setkey(struct cc_hw_desc *desc,
25262306a36Sopenharmony_ci				struct cc_aead_ctx *ctx)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	/* Load the AES key */
25562306a36Sopenharmony_ci	hw_desc_init(&desc[0]);
25662306a36Sopenharmony_ci	/* We are using for the source/user key the same buffer
25762306a36Sopenharmony_ci	 * as for the output keys, * because after this key loading it
25862306a36Sopenharmony_ci	 * is not needed anymore
25962306a36Sopenharmony_ci	 */
26062306a36Sopenharmony_ci	set_din_type(&desc[0], DMA_DLLI,
26162306a36Sopenharmony_ci		     ctx->auth_state.xcbc.xcbc_keys_dma_addr, ctx->auth_keylen,
26262306a36Sopenharmony_ci		     NS_BIT);
26362306a36Sopenharmony_ci	set_cipher_mode(&desc[0], DRV_CIPHER_ECB);
26462306a36Sopenharmony_ci	set_cipher_config0(&desc[0], DRV_CRYPTO_DIRECTION_ENCRYPT);
26562306a36Sopenharmony_ci	set_key_size_aes(&desc[0], ctx->auth_keylen);
26662306a36Sopenharmony_ci	set_flow_mode(&desc[0], S_DIN_to_AES);
26762306a36Sopenharmony_ci	set_setup_mode(&desc[0], SETUP_LOAD_KEY0);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	hw_desc_init(&desc[1]);
27062306a36Sopenharmony_ci	set_din_const(&desc[1], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
27162306a36Sopenharmony_ci	set_flow_mode(&desc[1], DIN_AES_DOUT);
27262306a36Sopenharmony_ci	set_dout_dlli(&desc[1], ctx->auth_state.xcbc.xcbc_keys_dma_addr,
27362306a36Sopenharmony_ci		      AES_KEYSIZE_128, NS_BIT, 0);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	hw_desc_init(&desc[2]);
27662306a36Sopenharmony_ci	set_din_const(&desc[2], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
27762306a36Sopenharmony_ci	set_flow_mode(&desc[2], DIN_AES_DOUT);
27862306a36Sopenharmony_ci	set_dout_dlli(&desc[2], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
27962306a36Sopenharmony_ci					 + AES_KEYSIZE_128),
28062306a36Sopenharmony_ci			      AES_KEYSIZE_128, NS_BIT, 0);
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	hw_desc_init(&desc[3]);
28362306a36Sopenharmony_ci	set_din_const(&desc[3], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
28462306a36Sopenharmony_ci	set_flow_mode(&desc[3], DIN_AES_DOUT);
28562306a36Sopenharmony_ci	set_dout_dlli(&desc[3], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
28662306a36Sopenharmony_ci					  + 2 * AES_KEYSIZE_128),
28762306a36Sopenharmony_ci			      AES_KEYSIZE_128, NS_BIT, 0);
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	return 4;
29062306a36Sopenharmony_ci}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cistatic unsigned int hmac_setkey(struct cc_hw_desc *desc,
29362306a36Sopenharmony_ci				struct cc_aead_ctx *ctx)
29462306a36Sopenharmony_ci{
29562306a36Sopenharmony_ci	unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST };
29662306a36Sopenharmony_ci	unsigned int digest_ofs = 0;
29762306a36Sopenharmony_ci	unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
29862306a36Sopenharmony_ci			DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
29962306a36Sopenharmony_ci	unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
30062306a36Sopenharmony_ci			CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
30162306a36Sopenharmony_ci	struct cc_hmac_s *hmac = &ctx->auth_state.hmac;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	unsigned int idx = 0;
30462306a36Sopenharmony_ci	int i;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	/* calc derived HMAC key */
30762306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
30862306a36Sopenharmony_ci		/* Load hash initial state */
30962306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
31062306a36Sopenharmony_ci		set_cipher_mode(&desc[idx], hash_mode);
31162306a36Sopenharmony_ci		set_din_sram(&desc[idx],
31262306a36Sopenharmony_ci			     cc_larval_digest_addr(ctx->drvdata,
31362306a36Sopenharmony_ci						   ctx->auth_mode),
31462306a36Sopenharmony_ci			     digest_size);
31562306a36Sopenharmony_ci		set_flow_mode(&desc[idx], S_DIN_to_HASH);
31662306a36Sopenharmony_ci		set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
31762306a36Sopenharmony_ci		idx++;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		/* Load the hash current length*/
32062306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
32162306a36Sopenharmony_ci		set_cipher_mode(&desc[idx], hash_mode);
32262306a36Sopenharmony_ci		set_din_const(&desc[idx], 0, ctx->hash_len);
32362306a36Sopenharmony_ci		set_flow_mode(&desc[idx], S_DIN_to_HASH);
32462306a36Sopenharmony_ci		set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
32562306a36Sopenharmony_ci		idx++;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci		/* Prepare ipad key */
32862306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
32962306a36Sopenharmony_ci		set_xor_val(&desc[idx], hmac_pad_const[i]);
33062306a36Sopenharmony_ci		set_cipher_mode(&desc[idx], hash_mode);
33162306a36Sopenharmony_ci		set_flow_mode(&desc[idx], S_DIN_to_HASH);
33262306a36Sopenharmony_ci		set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
33362306a36Sopenharmony_ci		idx++;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci		/* Perform HASH update */
33662306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
33762306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_DLLI,
33862306a36Sopenharmony_ci			     hmac->padded_authkey_dma_addr,
33962306a36Sopenharmony_ci			     SHA256_BLOCK_SIZE, NS_BIT);
34062306a36Sopenharmony_ci		set_cipher_mode(&desc[idx], hash_mode);
34162306a36Sopenharmony_ci		set_xor_active(&desc[idx]);
34262306a36Sopenharmony_ci		set_flow_mode(&desc[idx], DIN_HASH);
34362306a36Sopenharmony_ci		idx++;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		/* Get the digset */
34662306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
34762306a36Sopenharmony_ci		set_cipher_mode(&desc[idx], hash_mode);
34862306a36Sopenharmony_ci		set_dout_dlli(&desc[idx],
34962306a36Sopenharmony_ci			      (hmac->ipad_opad_dma_addr + digest_ofs),
35062306a36Sopenharmony_ci			      digest_size, NS_BIT, 0);
35162306a36Sopenharmony_ci		set_flow_mode(&desc[idx], S_HASH_to_DOUT);
35262306a36Sopenharmony_ci		set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
35362306a36Sopenharmony_ci		set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
35462306a36Sopenharmony_ci		idx++;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci		digest_ofs += digest_size;
35762306a36Sopenharmony_ci	}
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	return idx;
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic int validate_keys_sizes(struct cc_aead_ctx *ctx)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	dev_dbg(dev, "enc_keylen=%u  authkeylen=%u\n",
36762306a36Sopenharmony_ci		ctx->enc_keylen, ctx->auth_keylen);
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	switch (ctx->auth_mode) {
37062306a36Sopenharmony_ci	case DRV_HASH_SHA1:
37162306a36Sopenharmony_ci	case DRV_HASH_SHA256:
37262306a36Sopenharmony_ci		break;
37362306a36Sopenharmony_ci	case DRV_HASH_XCBC_MAC:
37462306a36Sopenharmony_ci		if (ctx->auth_keylen != AES_KEYSIZE_128 &&
37562306a36Sopenharmony_ci		    ctx->auth_keylen != AES_KEYSIZE_192 &&
37662306a36Sopenharmony_ci		    ctx->auth_keylen != AES_KEYSIZE_256)
37762306a36Sopenharmony_ci			return -ENOTSUPP;
37862306a36Sopenharmony_ci		break;
37962306a36Sopenharmony_ci	case DRV_HASH_NULL: /* Not authenc (e.g., CCM) - no auth_key) */
38062306a36Sopenharmony_ci		if (ctx->auth_keylen > 0)
38162306a36Sopenharmony_ci			return -EINVAL;
38262306a36Sopenharmony_ci		break;
38362306a36Sopenharmony_ci	default:
38462306a36Sopenharmony_ci		dev_dbg(dev, "Invalid auth_mode=%d\n", ctx->auth_mode);
38562306a36Sopenharmony_ci		return -EINVAL;
38662306a36Sopenharmony_ci	}
38762306a36Sopenharmony_ci	/* Check cipher key size */
38862306a36Sopenharmony_ci	if (ctx->flow_mode == S_DIN_to_DES) {
38962306a36Sopenharmony_ci		if (ctx->enc_keylen != DES3_EDE_KEY_SIZE) {
39062306a36Sopenharmony_ci			dev_dbg(dev, "Invalid cipher(3DES) key size: %u\n",
39162306a36Sopenharmony_ci				ctx->enc_keylen);
39262306a36Sopenharmony_ci			return -EINVAL;
39362306a36Sopenharmony_ci		}
39462306a36Sopenharmony_ci	} else { /* Default assumed to be AES ciphers */
39562306a36Sopenharmony_ci		if (ctx->enc_keylen != AES_KEYSIZE_128 &&
39662306a36Sopenharmony_ci		    ctx->enc_keylen != AES_KEYSIZE_192 &&
39762306a36Sopenharmony_ci		    ctx->enc_keylen != AES_KEYSIZE_256) {
39862306a36Sopenharmony_ci			dev_dbg(dev, "Invalid cipher(AES) key size: %u\n",
39962306a36Sopenharmony_ci				ctx->enc_keylen);
40062306a36Sopenharmony_ci			return -EINVAL;
40162306a36Sopenharmony_ci		}
40262306a36Sopenharmony_ci	}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	return 0; /* All tests of keys sizes passed */
40562306a36Sopenharmony_ci}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci/* This function prepers the user key so it can pass to the hmac processing
40862306a36Sopenharmony_ci * (copy to intenral buffer or hash in case of key longer than block
40962306a36Sopenharmony_ci */
41062306a36Sopenharmony_cistatic int cc_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *authkey,
41162306a36Sopenharmony_ci				 unsigned int keylen)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	dma_addr_t key_dma_addr = 0;
41462306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
41562306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
41662306a36Sopenharmony_ci	u32 larval_addr;
41762306a36Sopenharmony_ci	struct cc_crypto_req cc_req = {};
41862306a36Sopenharmony_ci	unsigned int blocksize;
41962306a36Sopenharmony_ci	unsigned int digestsize;
42062306a36Sopenharmony_ci	unsigned int hashmode;
42162306a36Sopenharmony_ci	unsigned int idx = 0;
42262306a36Sopenharmony_ci	int rc = 0;
42362306a36Sopenharmony_ci	u8 *key = NULL;
42462306a36Sopenharmony_ci	struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
42562306a36Sopenharmony_ci	dma_addr_t padded_authkey_dma_addr =
42662306a36Sopenharmony_ci		ctx->auth_state.hmac.padded_authkey_dma_addr;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	switch (ctx->auth_mode) { /* auth_key required and >0 */
42962306a36Sopenharmony_ci	case DRV_HASH_SHA1:
43062306a36Sopenharmony_ci		blocksize = SHA1_BLOCK_SIZE;
43162306a36Sopenharmony_ci		digestsize = SHA1_DIGEST_SIZE;
43262306a36Sopenharmony_ci		hashmode = DRV_HASH_HW_SHA1;
43362306a36Sopenharmony_ci		break;
43462306a36Sopenharmony_ci	case DRV_HASH_SHA256:
43562306a36Sopenharmony_ci	default:
43662306a36Sopenharmony_ci		blocksize = SHA256_BLOCK_SIZE;
43762306a36Sopenharmony_ci		digestsize = SHA256_DIGEST_SIZE;
43862306a36Sopenharmony_ci		hashmode = DRV_HASH_HW_SHA256;
43962306a36Sopenharmony_ci	}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	if (keylen != 0) {
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci		key = kmemdup(authkey, keylen, GFP_KERNEL);
44462306a36Sopenharmony_ci		if (!key)
44562306a36Sopenharmony_ci			return -ENOMEM;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci		key_dma_addr = dma_map_single(dev, key, keylen, DMA_TO_DEVICE);
44862306a36Sopenharmony_ci		if (dma_mapping_error(dev, key_dma_addr)) {
44962306a36Sopenharmony_ci			dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
45062306a36Sopenharmony_ci				key, keylen);
45162306a36Sopenharmony_ci			kfree_sensitive(key);
45262306a36Sopenharmony_ci			return -ENOMEM;
45362306a36Sopenharmony_ci		}
45462306a36Sopenharmony_ci		if (keylen > blocksize) {
45562306a36Sopenharmony_ci			/* Load hash initial state */
45662306a36Sopenharmony_ci			hw_desc_init(&desc[idx]);
45762306a36Sopenharmony_ci			set_cipher_mode(&desc[idx], hashmode);
45862306a36Sopenharmony_ci			larval_addr = cc_larval_digest_addr(ctx->drvdata,
45962306a36Sopenharmony_ci							    ctx->auth_mode);
46062306a36Sopenharmony_ci			set_din_sram(&desc[idx], larval_addr, digestsize);
46162306a36Sopenharmony_ci			set_flow_mode(&desc[idx], S_DIN_to_HASH);
46262306a36Sopenharmony_ci			set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
46362306a36Sopenharmony_ci			idx++;
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci			/* Load the hash current length*/
46662306a36Sopenharmony_ci			hw_desc_init(&desc[idx]);
46762306a36Sopenharmony_ci			set_cipher_mode(&desc[idx], hashmode);
46862306a36Sopenharmony_ci			set_din_const(&desc[idx], 0, ctx->hash_len);
46962306a36Sopenharmony_ci			set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
47062306a36Sopenharmony_ci			set_flow_mode(&desc[idx], S_DIN_to_HASH);
47162306a36Sopenharmony_ci			set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
47262306a36Sopenharmony_ci			idx++;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci			hw_desc_init(&desc[idx]);
47562306a36Sopenharmony_ci			set_din_type(&desc[idx], DMA_DLLI,
47662306a36Sopenharmony_ci				     key_dma_addr, keylen, NS_BIT);
47762306a36Sopenharmony_ci			set_flow_mode(&desc[idx], DIN_HASH);
47862306a36Sopenharmony_ci			idx++;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci			/* Get hashed key */
48162306a36Sopenharmony_ci			hw_desc_init(&desc[idx]);
48262306a36Sopenharmony_ci			set_cipher_mode(&desc[idx], hashmode);
48362306a36Sopenharmony_ci			set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
48462306a36Sopenharmony_ci				      digestsize, NS_BIT, 0);
48562306a36Sopenharmony_ci			set_flow_mode(&desc[idx], S_HASH_to_DOUT);
48662306a36Sopenharmony_ci			set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
48762306a36Sopenharmony_ci			set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
48862306a36Sopenharmony_ci			set_cipher_config0(&desc[idx],
48962306a36Sopenharmony_ci					   HASH_DIGEST_RESULT_LITTLE_ENDIAN);
49062306a36Sopenharmony_ci			idx++;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci			hw_desc_init(&desc[idx]);
49362306a36Sopenharmony_ci			set_din_const(&desc[idx], 0, (blocksize - digestsize));
49462306a36Sopenharmony_ci			set_flow_mode(&desc[idx], BYPASS);
49562306a36Sopenharmony_ci			set_dout_dlli(&desc[idx], (padded_authkey_dma_addr +
49662306a36Sopenharmony_ci				      digestsize), (blocksize - digestsize),
49762306a36Sopenharmony_ci				      NS_BIT, 0);
49862306a36Sopenharmony_ci			idx++;
49962306a36Sopenharmony_ci		} else {
50062306a36Sopenharmony_ci			hw_desc_init(&desc[idx]);
50162306a36Sopenharmony_ci			set_din_type(&desc[idx], DMA_DLLI, key_dma_addr,
50262306a36Sopenharmony_ci				     keylen, NS_BIT);
50362306a36Sopenharmony_ci			set_flow_mode(&desc[idx], BYPASS);
50462306a36Sopenharmony_ci			set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
50562306a36Sopenharmony_ci				      keylen, NS_BIT, 0);
50662306a36Sopenharmony_ci			idx++;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci			if ((blocksize - keylen) != 0) {
50962306a36Sopenharmony_ci				hw_desc_init(&desc[idx]);
51062306a36Sopenharmony_ci				set_din_const(&desc[idx], 0,
51162306a36Sopenharmony_ci					      (blocksize - keylen));
51262306a36Sopenharmony_ci				set_flow_mode(&desc[idx], BYPASS);
51362306a36Sopenharmony_ci				set_dout_dlli(&desc[idx],
51462306a36Sopenharmony_ci					      (padded_authkey_dma_addr +
51562306a36Sopenharmony_ci					       keylen),
51662306a36Sopenharmony_ci					      (blocksize - keylen), NS_BIT, 0);
51762306a36Sopenharmony_ci				idx++;
51862306a36Sopenharmony_ci			}
51962306a36Sopenharmony_ci		}
52062306a36Sopenharmony_ci	} else {
52162306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
52262306a36Sopenharmony_ci		set_din_const(&desc[idx], 0, (blocksize - keylen));
52362306a36Sopenharmony_ci		set_flow_mode(&desc[idx], BYPASS);
52462306a36Sopenharmony_ci		set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
52562306a36Sopenharmony_ci			      blocksize, NS_BIT, 0);
52662306a36Sopenharmony_ci		idx++;
52762306a36Sopenharmony_ci	}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx);
53062306a36Sopenharmony_ci	if (rc)
53162306a36Sopenharmony_ci		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	if (key_dma_addr)
53462306a36Sopenharmony_ci		dma_unmap_single(dev, key_dma_addr, keylen, DMA_TO_DEVICE);
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	kfree_sensitive(key);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	return rc;
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_cistatic int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
54262306a36Sopenharmony_ci			  unsigned int keylen)
54362306a36Sopenharmony_ci{
54462306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
54562306a36Sopenharmony_ci	struct cc_crypto_req cc_req = {};
54662306a36Sopenharmony_ci	struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
54762306a36Sopenharmony_ci	unsigned int seq_len = 0;
54862306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
54962306a36Sopenharmony_ci	const u8 *enckey, *authkey;
55062306a36Sopenharmony_ci	int rc;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	dev_dbg(dev, "Setting key in context @%p for %s. key=%p keylen=%u\n",
55362306a36Sopenharmony_ci		ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen);
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	/* STAT_PHASE_0: Init and sanity checks */
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */
55862306a36Sopenharmony_ci		struct crypto_authenc_keys keys;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci		rc = crypto_authenc_extractkeys(&keys, key, keylen);
56162306a36Sopenharmony_ci		if (rc)
56262306a36Sopenharmony_ci			return rc;
56362306a36Sopenharmony_ci		enckey = keys.enckey;
56462306a36Sopenharmony_ci		authkey = keys.authkey;
56562306a36Sopenharmony_ci		ctx->enc_keylen = keys.enckeylen;
56662306a36Sopenharmony_ci		ctx->auth_keylen = keys.authkeylen;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci		if (ctx->cipher_mode == DRV_CIPHER_CTR) {
56962306a36Sopenharmony_ci			/* the nonce is stored in bytes at end of key */
57062306a36Sopenharmony_ci			if (ctx->enc_keylen <
57162306a36Sopenharmony_ci			    (AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE))
57262306a36Sopenharmony_ci				return -EINVAL;
57362306a36Sopenharmony_ci			/* Copy nonce from last 4 bytes in CTR key to
57462306a36Sopenharmony_ci			 *  first 4 bytes in CTR IV
57562306a36Sopenharmony_ci			 */
57662306a36Sopenharmony_ci			memcpy(ctx->ctr_nonce, enckey + ctx->enc_keylen -
57762306a36Sopenharmony_ci			       CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
57862306a36Sopenharmony_ci			/* Set CTR key size */
57962306a36Sopenharmony_ci			ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE;
58062306a36Sopenharmony_ci		}
58162306a36Sopenharmony_ci	} else { /* non-authenc - has just one key */
58262306a36Sopenharmony_ci		enckey = key;
58362306a36Sopenharmony_ci		authkey = NULL;
58462306a36Sopenharmony_ci		ctx->enc_keylen = keylen;
58562306a36Sopenharmony_ci		ctx->auth_keylen = 0;
58662306a36Sopenharmony_ci	}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	rc = validate_keys_sizes(ctx);
58962306a36Sopenharmony_ci	if (rc)
59062306a36Sopenharmony_ci		return rc;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	/* STAT_PHASE_1: Copy key to ctx */
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	/* Get key material */
59562306a36Sopenharmony_ci	memcpy(ctx->enckey, enckey, ctx->enc_keylen);
59662306a36Sopenharmony_ci	if (ctx->enc_keylen == 24)
59762306a36Sopenharmony_ci		memset(ctx->enckey + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
59862306a36Sopenharmony_ci	if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
59962306a36Sopenharmony_ci		memcpy(ctx->auth_state.xcbc.xcbc_keys, authkey,
60062306a36Sopenharmony_ci		       ctx->auth_keylen);
60162306a36Sopenharmony_ci	} else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */
60262306a36Sopenharmony_ci		rc = cc_get_plain_hmac_key(tfm, authkey, ctx->auth_keylen);
60362306a36Sopenharmony_ci		if (rc)
60462306a36Sopenharmony_ci			return rc;
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	/* STAT_PHASE_2: Create sequence */
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	switch (ctx->auth_mode) {
61062306a36Sopenharmony_ci	case DRV_HASH_SHA1:
61162306a36Sopenharmony_ci	case DRV_HASH_SHA256:
61262306a36Sopenharmony_ci		seq_len = hmac_setkey(desc, ctx);
61362306a36Sopenharmony_ci		break;
61462306a36Sopenharmony_ci	case DRV_HASH_XCBC_MAC:
61562306a36Sopenharmony_ci		seq_len = xcbc_setkey(desc, ctx);
61662306a36Sopenharmony_ci		break;
61762306a36Sopenharmony_ci	case DRV_HASH_NULL: /* non-authenc modes, e.g., CCM */
61862306a36Sopenharmony_ci		break; /* No auth. key setup */
61962306a36Sopenharmony_ci	default:
62062306a36Sopenharmony_ci		dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode);
62162306a36Sopenharmony_ci		return -ENOTSUPP;
62262306a36Sopenharmony_ci	}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	/* STAT_PHASE_3: Submit sequence to HW */
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	if (seq_len > 0) { /* For CCM there is no sequence to setup the key */
62762306a36Sopenharmony_ci		rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, seq_len);
62862306a36Sopenharmony_ci		if (rc) {
62962306a36Sopenharmony_ci			dev_err(dev, "send_request() failed (rc=%d)\n", rc);
63062306a36Sopenharmony_ci			return rc;
63162306a36Sopenharmony_ci		}
63262306a36Sopenharmony_ci	}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	/* Update STAT_PHASE_3 */
63562306a36Sopenharmony_ci	return rc;
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_cistatic int cc_des3_aead_setkey(struct crypto_aead *aead, const u8 *key,
63962306a36Sopenharmony_ci			       unsigned int keylen)
64062306a36Sopenharmony_ci{
64162306a36Sopenharmony_ci	struct crypto_authenc_keys keys;
64262306a36Sopenharmony_ci	int err;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	err = crypto_authenc_extractkeys(&keys, key, keylen);
64562306a36Sopenharmony_ci	if (unlikely(err))
64662306a36Sopenharmony_ci		return err;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	err = verify_aead_des3_key(aead, keys.enckey, keys.enckeylen) ?:
64962306a36Sopenharmony_ci	      cc_aead_setkey(aead, key, keylen);
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
65262306a36Sopenharmony_ci	return err;
65362306a36Sopenharmony_ci}
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_cistatic int cc_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key,
65662306a36Sopenharmony_ci				 unsigned int keylen)
65762306a36Sopenharmony_ci{
65862306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	if (keylen < 3)
66162306a36Sopenharmony_ci		return -EINVAL;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	keylen -= 3;
66462306a36Sopenharmony_ci	memcpy(ctx->ctr_nonce, key + keylen, 3);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	return cc_aead_setkey(tfm, key, keylen);
66762306a36Sopenharmony_ci}
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_cistatic int cc_aead_setauthsize(struct crypto_aead *authenc,
67062306a36Sopenharmony_ci			       unsigned int authsize)
67162306a36Sopenharmony_ci{
67262306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc);
67362306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	/* Unsupported auth. sizes */
67662306a36Sopenharmony_ci	if (authsize == 0 ||
67762306a36Sopenharmony_ci	    authsize > crypto_aead_maxauthsize(authenc)) {
67862306a36Sopenharmony_ci		return -ENOTSUPP;
67962306a36Sopenharmony_ci	}
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	ctx->authsize = authsize;
68262306a36Sopenharmony_ci	dev_dbg(dev, "authlen=%d\n", ctx->authsize);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	return 0;
68562306a36Sopenharmony_ci}
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_cistatic int cc_rfc4309_ccm_setauthsize(struct crypto_aead *authenc,
68862306a36Sopenharmony_ci				      unsigned int authsize)
68962306a36Sopenharmony_ci{
69062306a36Sopenharmony_ci	switch (authsize) {
69162306a36Sopenharmony_ci	case 8:
69262306a36Sopenharmony_ci	case 12:
69362306a36Sopenharmony_ci	case 16:
69462306a36Sopenharmony_ci		break;
69562306a36Sopenharmony_ci	default:
69662306a36Sopenharmony_ci		return -EINVAL;
69762306a36Sopenharmony_ci	}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	return cc_aead_setauthsize(authenc, authsize);
70062306a36Sopenharmony_ci}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_cistatic int cc_ccm_setauthsize(struct crypto_aead *authenc,
70362306a36Sopenharmony_ci			      unsigned int authsize)
70462306a36Sopenharmony_ci{
70562306a36Sopenharmony_ci	switch (authsize) {
70662306a36Sopenharmony_ci	case 4:
70762306a36Sopenharmony_ci	case 6:
70862306a36Sopenharmony_ci	case 8:
70962306a36Sopenharmony_ci	case 10:
71062306a36Sopenharmony_ci	case 12:
71162306a36Sopenharmony_ci	case 14:
71262306a36Sopenharmony_ci	case 16:
71362306a36Sopenharmony_ci		break;
71462306a36Sopenharmony_ci	default:
71562306a36Sopenharmony_ci		return -EINVAL;
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	return cc_aead_setauthsize(authenc, authsize);
71962306a36Sopenharmony_ci}
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_cistatic void cc_set_assoc_desc(struct aead_request *areq, unsigned int flow_mode,
72262306a36Sopenharmony_ci			      struct cc_hw_desc desc[], unsigned int *seq_size)
72362306a36Sopenharmony_ci{
72462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
72562306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
72662306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(areq);
72762306a36Sopenharmony_ci	enum cc_req_dma_buf_type assoc_dma_type = areq_ctx->assoc_buff_type;
72862306a36Sopenharmony_ci	unsigned int idx = *seq_size;
72962306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	switch (assoc_dma_type) {
73262306a36Sopenharmony_ci	case CC_DMA_BUF_DLLI:
73362306a36Sopenharmony_ci		dev_dbg(dev, "ASSOC buffer type DLLI\n");
73462306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
73562306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_DLLI, sg_dma_address(areq->src),
73662306a36Sopenharmony_ci			     areq_ctx->assoclen, NS_BIT);
73762306a36Sopenharmony_ci		set_flow_mode(&desc[idx], flow_mode);
73862306a36Sopenharmony_ci		if (ctx->auth_mode == DRV_HASH_XCBC_MAC &&
73962306a36Sopenharmony_ci		    areq_ctx->cryptlen > 0)
74062306a36Sopenharmony_ci			set_din_not_last_indication(&desc[idx]);
74162306a36Sopenharmony_ci		break;
74262306a36Sopenharmony_ci	case CC_DMA_BUF_MLLI:
74362306a36Sopenharmony_ci		dev_dbg(dev, "ASSOC buffer type MLLI\n");
74462306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
74562306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_MLLI, areq_ctx->assoc.sram_addr,
74662306a36Sopenharmony_ci			     areq_ctx->assoc.mlli_nents, NS_BIT);
74762306a36Sopenharmony_ci		set_flow_mode(&desc[idx], flow_mode);
74862306a36Sopenharmony_ci		if (ctx->auth_mode == DRV_HASH_XCBC_MAC &&
74962306a36Sopenharmony_ci		    areq_ctx->cryptlen > 0)
75062306a36Sopenharmony_ci			set_din_not_last_indication(&desc[idx]);
75162306a36Sopenharmony_ci		break;
75262306a36Sopenharmony_ci	case CC_DMA_BUF_NULL:
75362306a36Sopenharmony_ci	default:
75462306a36Sopenharmony_ci		dev_err(dev, "Invalid ASSOC buffer type\n");
75562306a36Sopenharmony_ci	}
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	*seq_size = (++idx);
75862306a36Sopenharmony_ci}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_cistatic void cc_proc_authen_desc(struct aead_request *areq,
76162306a36Sopenharmony_ci				unsigned int flow_mode,
76262306a36Sopenharmony_ci				struct cc_hw_desc desc[],
76362306a36Sopenharmony_ci				unsigned int *seq_size, int direct)
76462306a36Sopenharmony_ci{
76562306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(areq);
76662306a36Sopenharmony_ci	enum cc_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type;
76762306a36Sopenharmony_ci	unsigned int idx = *seq_size;
76862306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
76962306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
77062306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	switch (data_dma_type) {
77362306a36Sopenharmony_ci	case CC_DMA_BUF_DLLI:
77462306a36Sopenharmony_ci	{
77562306a36Sopenharmony_ci		struct scatterlist *cipher =
77662306a36Sopenharmony_ci			(direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
77762306a36Sopenharmony_ci			areq_ctx->dst_sgl : areq_ctx->src_sgl;
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci		unsigned int offset =
78062306a36Sopenharmony_ci			(direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
78162306a36Sopenharmony_ci			areq_ctx->dst_offset : areq_ctx->src_offset;
78262306a36Sopenharmony_ci		dev_dbg(dev, "AUTHENC: SRC/DST buffer type DLLI\n");
78362306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
78462306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_DLLI,
78562306a36Sopenharmony_ci			     (sg_dma_address(cipher) + offset),
78662306a36Sopenharmony_ci			     areq_ctx->cryptlen, NS_BIT);
78762306a36Sopenharmony_ci		set_flow_mode(&desc[idx], flow_mode);
78862306a36Sopenharmony_ci		break;
78962306a36Sopenharmony_ci	}
79062306a36Sopenharmony_ci	case CC_DMA_BUF_MLLI:
79162306a36Sopenharmony_ci	{
79262306a36Sopenharmony_ci		/* DOUBLE-PASS flow (as default)
79362306a36Sopenharmony_ci		 * assoc. + iv + data -compact in one table
79462306a36Sopenharmony_ci		 * if assoclen is ZERO only IV perform
79562306a36Sopenharmony_ci		 */
79662306a36Sopenharmony_ci		u32 mlli_addr = areq_ctx->assoc.sram_addr;
79762306a36Sopenharmony_ci		u32 mlli_nents = areq_ctx->assoc.mlli_nents;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci		if (areq_ctx->is_single_pass) {
80062306a36Sopenharmony_ci			if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
80162306a36Sopenharmony_ci				mlli_addr = areq_ctx->dst.sram_addr;
80262306a36Sopenharmony_ci				mlli_nents = areq_ctx->dst.mlli_nents;
80362306a36Sopenharmony_ci			} else {
80462306a36Sopenharmony_ci				mlli_addr = areq_ctx->src.sram_addr;
80562306a36Sopenharmony_ci				mlli_nents = areq_ctx->src.mlli_nents;
80662306a36Sopenharmony_ci			}
80762306a36Sopenharmony_ci		}
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci		dev_dbg(dev, "AUTHENC: SRC/DST buffer type MLLI\n");
81062306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
81162306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_MLLI, mlli_addr, mlli_nents,
81262306a36Sopenharmony_ci			     NS_BIT);
81362306a36Sopenharmony_ci		set_flow_mode(&desc[idx], flow_mode);
81462306a36Sopenharmony_ci		break;
81562306a36Sopenharmony_ci	}
81662306a36Sopenharmony_ci	case CC_DMA_BUF_NULL:
81762306a36Sopenharmony_ci	default:
81862306a36Sopenharmony_ci		dev_err(dev, "AUTHENC: Invalid SRC/DST buffer type\n");
81962306a36Sopenharmony_ci	}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	*seq_size = (++idx);
82262306a36Sopenharmony_ci}
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_cistatic void cc_proc_cipher_desc(struct aead_request *areq,
82562306a36Sopenharmony_ci				unsigned int flow_mode,
82662306a36Sopenharmony_ci				struct cc_hw_desc desc[],
82762306a36Sopenharmony_ci				unsigned int *seq_size)
82862306a36Sopenharmony_ci{
82962306a36Sopenharmony_ci	unsigned int idx = *seq_size;
83062306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(areq);
83162306a36Sopenharmony_ci	enum cc_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type;
83262306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
83362306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
83462306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	if (areq_ctx->cryptlen == 0)
83762306a36Sopenharmony_ci		return; /*null processing*/
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	switch (data_dma_type) {
84062306a36Sopenharmony_ci	case CC_DMA_BUF_DLLI:
84162306a36Sopenharmony_ci		dev_dbg(dev, "CIPHER: SRC/DST buffer type DLLI\n");
84262306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
84362306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_DLLI,
84462306a36Sopenharmony_ci			     (sg_dma_address(areq_ctx->src_sgl) +
84562306a36Sopenharmony_ci			      areq_ctx->src_offset), areq_ctx->cryptlen,
84662306a36Sopenharmony_ci			      NS_BIT);
84762306a36Sopenharmony_ci		set_dout_dlli(&desc[idx],
84862306a36Sopenharmony_ci			      (sg_dma_address(areq_ctx->dst_sgl) +
84962306a36Sopenharmony_ci			       areq_ctx->dst_offset),
85062306a36Sopenharmony_ci			      areq_ctx->cryptlen, NS_BIT, 0);
85162306a36Sopenharmony_ci		set_flow_mode(&desc[idx], flow_mode);
85262306a36Sopenharmony_ci		break;
85362306a36Sopenharmony_ci	case CC_DMA_BUF_MLLI:
85462306a36Sopenharmony_ci		dev_dbg(dev, "CIPHER: SRC/DST buffer type MLLI\n");
85562306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
85662306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_MLLI, areq_ctx->src.sram_addr,
85762306a36Sopenharmony_ci			     areq_ctx->src.mlli_nents, NS_BIT);
85862306a36Sopenharmony_ci		set_dout_mlli(&desc[idx], areq_ctx->dst.sram_addr,
85962306a36Sopenharmony_ci			      areq_ctx->dst.mlli_nents, NS_BIT, 0);
86062306a36Sopenharmony_ci		set_flow_mode(&desc[idx], flow_mode);
86162306a36Sopenharmony_ci		break;
86262306a36Sopenharmony_ci	case CC_DMA_BUF_NULL:
86362306a36Sopenharmony_ci	default:
86462306a36Sopenharmony_ci		dev_err(dev, "CIPHER: Invalid SRC/DST buffer type\n");
86562306a36Sopenharmony_ci	}
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	*seq_size = (++idx);
86862306a36Sopenharmony_ci}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_cistatic void cc_proc_digest_desc(struct aead_request *req,
87162306a36Sopenharmony_ci				struct cc_hw_desc desc[],
87262306a36Sopenharmony_ci				unsigned int *seq_size)
87362306a36Sopenharmony_ci{
87462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
87562306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
87662306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
87762306a36Sopenharmony_ci	unsigned int idx = *seq_size;
87862306a36Sopenharmony_ci	unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
87962306a36Sopenharmony_ci				DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
88062306a36Sopenharmony_ci	int direct = req_ctx->gen_ctx.op_type;
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	/* Get final ICV result */
88362306a36Sopenharmony_ci	if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
88462306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
88562306a36Sopenharmony_ci		set_flow_mode(&desc[idx], S_HASH_to_DOUT);
88662306a36Sopenharmony_ci		set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
88762306a36Sopenharmony_ci		set_dout_dlli(&desc[idx], req_ctx->icv_dma_addr, ctx->authsize,
88862306a36Sopenharmony_ci			      NS_BIT, 1);
88962306a36Sopenharmony_ci		set_queue_last_ind(ctx->drvdata, &desc[idx]);
89062306a36Sopenharmony_ci		if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
89162306a36Sopenharmony_ci			set_aes_not_hash_mode(&desc[idx]);
89262306a36Sopenharmony_ci			set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
89362306a36Sopenharmony_ci		} else {
89462306a36Sopenharmony_ci			set_cipher_config0(&desc[idx],
89562306a36Sopenharmony_ci					   HASH_DIGEST_RESULT_LITTLE_ENDIAN);
89662306a36Sopenharmony_ci			set_cipher_mode(&desc[idx], hash_mode);
89762306a36Sopenharmony_ci		}
89862306a36Sopenharmony_ci	} else { /*Decrypt*/
89962306a36Sopenharmony_ci		/* Get ICV out from hardware */
90062306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
90162306a36Sopenharmony_ci		set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
90262306a36Sopenharmony_ci		set_flow_mode(&desc[idx], S_HASH_to_DOUT);
90362306a36Sopenharmony_ci		set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr,
90462306a36Sopenharmony_ci			      ctx->authsize, NS_BIT, 1);
90562306a36Sopenharmony_ci		set_queue_last_ind(ctx->drvdata, &desc[idx]);
90662306a36Sopenharmony_ci		set_cipher_config0(&desc[idx],
90762306a36Sopenharmony_ci				   HASH_DIGEST_RESULT_LITTLE_ENDIAN);
90862306a36Sopenharmony_ci		set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
90962306a36Sopenharmony_ci		if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
91062306a36Sopenharmony_ci			set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
91162306a36Sopenharmony_ci			set_aes_not_hash_mode(&desc[idx]);
91262306a36Sopenharmony_ci		} else {
91362306a36Sopenharmony_ci			set_cipher_mode(&desc[idx], hash_mode);
91462306a36Sopenharmony_ci		}
91562306a36Sopenharmony_ci	}
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	*seq_size = (++idx);
91862306a36Sopenharmony_ci}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_cistatic void cc_set_cipher_desc(struct aead_request *req,
92162306a36Sopenharmony_ci			       struct cc_hw_desc desc[],
92262306a36Sopenharmony_ci			       unsigned int *seq_size)
92362306a36Sopenharmony_ci{
92462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
92562306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
92662306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
92762306a36Sopenharmony_ci	unsigned int hw_iv_size = req_ctx->hw_iv_size;
92862306a36Sopenharmony_ci	unsigned int idx = *seq_size;
92962306a36Sopenharmony_ci	int direct = req_ctx->gen_ctx.op_type;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	/* Setup cipher state */
93262306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
93362306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], direct);
93462306a36Sopenharmony_ci	set_flow_mode(&desc[idx], ctx->flow_mode);
93562306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, req_ctx->gen_ctx.iv_dma_addr,
93662306a36Sopenharmony_ci		     hw_iv_size, NS_BIT);
93762306a36Sopenharmony_ci	if (ctx->cipher_mode == DRV_CIPHER_CTR)
93862306a36Sopenharmony_ci		set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
93962306a36Sopenharmony_ci	else
94062306a36Sopenharmony_ci		set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
94162306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], ctx->cipher_mode);
94262306a36Sopenharmony_ci	idx++;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	/* Setup enc. key */
94562306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
94662306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], direct);
94762306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
94862306a36Sopenharmony_ci	set_flow_mode(&desc[idx], ctx->flow_mode);
94962306a36Sopenharmony_ci	if (ctx->flow_mode == S_DIN_to_AES) {
95062306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
95162306a36Sopenharmony_ci			     ((ctx->enc_keylen == 24) ? CC_AES_KEY_SIZE_MAX :
95262306a36Sopenharmony_ci			      ctx->enc_keylen), NS_BIT);
95362306a36Sopenharmony_ci		set_key_size_aes(&desc[idx], ctx->enc_keylen);
95462306a36Sopenharmony_ci	} else {
95562306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
95662306a36Sopenharmony_ci			     ctx->enc_keylen, NS_BIT);
95762306a36Sopenharmony_ci		set_key_size_des(&desc[idx], ctx->enc_keylen);
95862306a36Sopenharmony_ci	}
95962306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], ctx->cipher_mode);
96062306a36Sopenharmony_ci	idx++;
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	*seq_size = idx;
96362306a36Sopenharmony_ci}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_cistatic void cc_proc_cipher(struct aead_request *req, struct cc_hw_desc desc[],
96662306a36Sopenharmony_ci			   unsigned int *seq_size, unsigned int data_flow_mode)
96762306a36Sopenharmony_ci{
96862306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
96962306a36Sopenharmony_ci	int direct = req_ctx->gen_ctx.op_type;
97062306a36Sopenharmony_ci	unsigned int idx = *seq_size;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	if (req_ctx->cryptlen == 0)
97362306a36Sopenharmony_ci		return; /*null processing*/
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	cc_set_cipher_desc(req, desc, &idx);
97662306a36Sopenharmony_ci	cc_proc_cipher_desc(req, data_flow_mode, desc, &idx);
97762306a36Sopenharmony_ci	if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
97862306a36Sopenharmony_ci		/* We must wait for DMA to write all cipher */
97962306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
98062306a36Sopenharmony_ci		set_din_no_dma(&desc[idx], 0, 0xfffff0);
98162306a36Sopenharmony_ci		set_dout_no_dma(&desc[idx], 0, 0, 1);
98262306a36Sopenharmony_ci		idx++;
98362306a36Sopenharmony_ci	}
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	*seq_size = idx;
98662306a36Sopenharmony_ci}
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_cistatic void cc_set_hmac_desc(struct aead_request *req, struct cc_hw_desc desc[],
98962306a36Sopenharmony_ci			     unsigned int *seq_size)
99062306a36Sopenharmony_ci{
99162306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
99262306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
99362306a36Sopenharmony_ci	unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
99462306a36Sopenharmony_ci				DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
99562306a36Sopenharmony_ci	unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
99662306a36Sopenharmony_ci				CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
99762306a36Sopenharmony_ci	unsigned int idx = *seq_size;
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	/* Loading hash ipad xor key state */
100062306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
100162306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], hash_mode);
100262306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI,
100362306a36Sopenharmony_ci		     ctx->auth_state.hmac.ipad_opad_dma_addr, digest_size,
100462306a36Sopenharmony_ci		     NS_BIT);
100562306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
100662306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
100762306a36Sopenharmony_ci	idx++;
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	/* Load init. digest len (64 bytes) */
101062306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
101162306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], hash_mode);
101262306a36Sopenharmony_ci	set_din_sram(&desc[idx], cc_digest_len_addr(ctx->drvdata, hash_mode),
101362306a36Sopenharmony_ci		     ctx->hash_len);
101462306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
101562306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
101662306a36Sopenharmony_ci	idx++;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	*seq_size = idx;
101962306a36Sopenharmony_ci}
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_cistatic void cc_set_xcbc_desc(struct aead_request *req, struct cc_hw_desc desc[],
102262306a36Sopenharmony_ci			     unsigned int *seq_size)
102362306a36Sopenharmony_ci{
102462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
102562306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
102662306a36Sopenharmony_ci	unsigned int idx = *seq_size;
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	/* Loading MAC state */
102962306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
103062306a36Sopenharmony_ci	set_din_const(&desc[idx], 0, CC_AES_BLOCK_SIZE);
103162306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
103262306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
103362306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
103462306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
103562306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
103662306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
103762306a36Sopenharmony_ci	idx++;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	/* Setup XCBC MAC K1 */
104062306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
104162306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI,
104262306a36Sopenharmony_ci		     ctx->auth_state.xcbc.xcbc_keys_dma_addr,
104362306a36Sopenharmony_ci		     AES_KEYSIZE_128, NS_BIT);
104462306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
104562306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
104662306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
104762306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
104862306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
104962306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
105062306a36Sopenharmony_ci	idx++;
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	/* Setup XCBC MAC K2 */
105362306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
105462306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI,
105562306a36Sopenharmony_ci		     (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
105662306a36Sopenharmony_ci		      AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT);
105762306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
105862306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
105962306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
106062306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
106162306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
106262306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
106362306a36Sopenharmony_ci	idx++;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	/* Setup XCBC MAC K3 */
106662306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
106762306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI,
106862306a36Sopenharmony_ci		     (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
106962306a36Sopenharmony_ci		      2 * AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT);
107062306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE2);
107162306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
107262306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
107362306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
107462306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
107562306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
107662306a36Sopenharmony_ci	idx++;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	*seq_size = idx;
107962306a36Sopenharmony_ci}
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_cistatic void cc_proc_header_desc(struct aead_request *req,
108262306a36Sopenharmony_ci				struct cc_hw_desc desc[],
108362306a36Sopenharmony_ci				unsigned int *seq_size)
108462306a36Sopenharmony_ci{
108562306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
108662306a36Sopenharmony_ci	unsigned int idx = *seq_size;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	/* Hash associated data */
108962306a36Sopenharmony_ci	if (areq_ctx->assoclen > 0)
109062306a36Sopenharmony_ci		cc_set_assoc_desc(req, DIN_HASH, desc, &idx);
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	/* Hash IV */
109362306a36Sopenharmony_ci	*seq_size = idx;
109462306a36Sopenharmony_ci}
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_cistatic void cc_proc_scheme_desc(struct aead_request *req,
109762306a36Sopenharmony_ci				struct cc_hw_desc desc[],
109862306a36Sopenharmony_ci				unsigned int *seq_size)
109962306a36Sopenharmony_ci{
110062306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
110162306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
110262306a36Sopenharmony_ci	struct cc_aead_handle *aead_handle = ctx->drvdata->aead_handle;
110362306a36Sopenharmony_ci	unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
110462306a36Sopenharmony_ci				DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
110562306a36Sopenharmony_ci	unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
110662306a36Sopenharmony_ci				CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
110762306a36Sopenharmony_ci	unsigned int idx = *seq_size;
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
111062306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], hash_mode);
111162306a36Sopenharmony_ci	set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr,
111262306a36Sopenharmony_ci		      ctx->hash_len);
111362306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_HASH_to_DOUT);
111462306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
111562306a36Sopenharmony_ci	set_cipher_do(&desc[idx], DO_PAD);
111662306a36Sopenharmony_ci	idx++;
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	/* Get final ICV result */
111962306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
112062306a36Sopenharmony_ci	set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr,
112162306a36Sopenharmony_ci		      digest_size);
112262306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_HASH_to_DOUT);
112362306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
112462306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
112562306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], hash_mode);
112662306a36Sopenharmony_ci	idx++;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	/* Loading hash opad xor key state */
112962306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
113062306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], hash_mode);
113162306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI,
113262306a36Sopenharmony_ci		     (ctx->auth_state.hmac.ipad_opad_dma_addr + digest_size),
113362306a36Sopenharmony_ci		     digest_size, NS_BIT);
113462306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
113562306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
113662306a36Sopenharmony_ci	idx++;
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	/* Load init. digest len (64 bytes) */
113962306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
114062306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], hash_mode);
114162306a36Sopenharmony_ci	set_din_sram(&desc[idx], cc_digest_len_addr(ctx->drvdata, hash_mode),
114262306a36Sopenharmony_ci		     ctx->hash_len);
114362306a36Sopenharmony_ci	set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
114462306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
114562306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
114662306a36Sopenharmony_ci	idx++;
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	/* Perform HASH update */
114962306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
115062306a36Sopenharmony_ci	set_din_sram(&desc[idx], aead_handle->sram_workspace_addr,
115162306a36Sopenharmony_ci		     digest_size);
115262306a36Sopenharmony_ci	set_flow_mode(&desc[idx], DIN_HASH);
115362306a36Sopenharmony_ci	idx++;
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	*seq_size = idx;
115662306a36Sopenharmony_ci}
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_cistatic void cc_mlli_to_sram(struct aead_request *req,
115962306a36Sopenharmony_ci			    struct cc_hw_desc desc[], unsigned int *seq_size)
116062306a36Sopenharmony_ci{
116162306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
116262306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
116362306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
116462306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	if ((req_ctx->assoc_buff_type == CC_DMA_BUF_MLLI ||
116762306a36Sopenharmony_ci	    req_ctx->data_buff_type == CC_DMA_BUF_MLLI ||
116862306a36Sopenharmony_ci	    !req_ctx->is_single_pass) && req_ctx->mlli_params.mlli_len) {
116962306a36Sopenharmony_ci		dev_dbg(dev, "Copy-to-sram: mlli_dma=%08x, mlli_size=%u\n",
117062306a36Sopenharmony_ci			ctx->drvdata->mlli_sram_addr,
117162306a36Sopenharmony_ci			req_ctx->mlli_params.mlli_len);
117262306a36Sopenharmony_ci		/* Copy MLLI table host-to-sram */
117362306a36Sopenharmony_ci		hw_desc_init(&desc[*seq_size]);
117462306a36Sopenharmony_ci		set_din_type(&desc[*seq_size], DMA_DLLI,
117562306a36Sopenharmony_ci			     req_ctx->mlli_params.mlli_dma_addr,
117662306a36Sopenharmony_ci			     req_ctx->mlli_params.mlli_len, NS_BIT);
117762306a36Sopenharmony_ci		set_dout_sram(&desc[*seq_size],
117862306a36Sopenharmony_ci			      ctx->drvdata->mlli_sram_addr,
117962306a36Sopenharmony_ci			      req_ctx->mlli_params.mlli_len);
118062306a36Sopenharmony_ci		set_flow_mode(&desc[*seq_size], BYPASS);
118162306a36Sopenharmony_ci		(*seq_size)++;
118262306a36Sopenharmony_ci	}
118362306a36Sopenharmony_ci}
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_cistatic enum cc_flow_mode cc_get_data_flow(enum drv_crypto_direction direct,
118662306a36Sopenharmony_ci					  enum cc_flow_mode setup_flow_mode,
118762306a36Sopenharmony_ci					  bool is_single_pass)
118862306a36Sopenharmony_ci{
118962306a36Sopenharmony_ci	enum cc_flow_mode data_flow_mode;
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
119262306a36Sopenharmony_ci		if (setup_flow_mode == S_DIN_to_AES)
119362306a36Sopenharmony_ci			data_flow_mode = is_single_pass ?
119462306a36Sopenharmony_ci				AES_to_HASH_and_DOUT : DIN_AES_DOUT;
119562306a36Sopenharmony_ci		else
119662306a36Sopenharmony_ci			data_flow_mode = is_single_pass ?
119762306a36Sopenharmony_ci				DES_to_HASH_and_DOUT : DIN_DES_DOUT;
119862306a36Sopenharmony_ci	} else { /* Decrypt */
119962306a36Sopenharmony_ci		if (setup_flow_mode == S_DIN_to_AES)
120062306a36Sopenharmony_ci			data_flow_mode = is_single_pass ?
120162306a36Sopenharmony_ci				AES_and_HASH : DIN_AES_DOUT;
120262306a36Sopenharmony_ci		else
120362306a36Sopenharmony_ci			data_flow_mode = is_single_pass ?
120462306a36Sopenharmony_ci				DES_and_HASH : DIN_DES_DOUT;
120562306a36Sopenharmony_ci	}
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci	return data_flow_mode;
120862306a36Sopenharmony_ci}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_cistatic void cc_hmac_authenc(struct aead_request *req, struct cc_hw_desc desc[],
121162306a36Sopenharmony_ci			    unsigned int *seq_size)
121262306a36Sopenharmony_ci{
121362306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
121462306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
121562306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
121662306a36Sopenharmony_ci	int direct = req_ctx->gen_ctx.op_type;
121762306a36Sopenharmony_ci	unsigned int data_flow_mode =
121862306a36Sopenharmony_ci		cc_get_data_flow(direct, ctx->flow_mode,
121962306a36Sopenharmony_ci				 req_ctx->is_single_pass);
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	if (req_ctx->is_single_pass) {
122262306a36Sopenharmony_ci		/*
122362306a36Sopenharmony_ci		 * Single-pass flow
122462306a36Sopenharmony_ci		 */
122562306a36Sopenharmony_ci		cc_set_hmac_desc(req, desc, seq_size);
122662306a36Sopenharmony_ci		cc_set_cipher_desc(req, desc, seq_size);
122762306a36Sopenharmony_ci		cc_proc_header_desc(req, desc, seq_size);
122862306a36Sopenharmony_ci		cc_proc_cipher_desc(req, data_flow_mode, desc, seq_size);
122962306a36Sopenharmony_ci		cc_proc_scheme_desc(req, desc, seq_size);
123062306a36Sopenharmony_ci		cc_proc_digest_desc(req, desc, seq_size);
123162306a36Sopenharmony_ci		return;
123262306a36Sopenharmony_ci	}
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	/*
123562306a36Sopenharmony_ci	 * Double-pass flow
123662306a36Sopenharmony_ci	 * Fallback for unsupported single-pass modes,
123762306a36Sopenharmony_ci	 * i.e. using assoc. data of non-word-multiple
123862306a36Sopenharmony_ci	 */
123962306a36Sopenharmony_ci	if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
124062306a36Sopenharmony_ci		/* encrypt first.. */
124162306a36Sopenharmony_ci		cc_proc_cipher(req, desc, seq_size, data_flow_mode);
124262306a36Sopenharmony_ci		/* authenc after..*/
124362306a36Sopenharmony_ci		cc_set_hmac_desc(req, desc, seq_size);
124462306a36Sopenharmony_ci		cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct);
124562306a36Sopenharmony_ci		cc_proc_scheme_desc(req, desc, seq_size);
124662306a36Sopenharmony_ci		cc_proc_digest_desc(req, desc, seq_size);
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	} else { /*DECRYPT*/
124962306a36Sopenharmony_ci		/* authenc first..*/
125062306a36Sopenharmony_ci		cc_set_hmac_desc(req, desc, seq_size);
125162306a36Sopenharmony_ci		cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct);
125262306a36Sopenharmony_ci		cc_proc_scheme_desc(req, desc, seq_size);
125362306a36Sopenharmony_ci		/* decrypt after.. */
125462306a36Sopenharmony_ci		cc_proc_cipher(req, desc, seq_size, data_flow_mode);
125562306a36Sopenharmony_ci		/* read the digest result with setting the completion bit
125662306a36Sopenharmony_ci		 * must be after the cipher operation
125762306a36Sopenharmony_ci		 */
125862306a36Sopenharmony_ci		cc_proc_digest_desc(req, desc, seq_size);
125962306a36Sopenharmony_ci	}
126062306a36Sopenharmony_ci}
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_cistatic void
126362306a36Sopenharmony_cicc_xcbc_authenc(struct aead_request *req, struct cc_hw_desc desc[],
126462306a36Sopenharmony_ci		unsigned int *seq_size)
126562306a36Sopenharmony_ci{
126662306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
126762306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
126862306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
126962306a36Sopenharmony_ci	int direct = req_ctx->gen_ctx.op_type;
127062306a36Sopenharmony_ci	unsigned int data_flow_mode =
127162306a36Sopenharmony_ci		cc_get_data_flow(direct, ctx->flow_mode,
127262306a36Sopenharmony_ci				 req_ctx->is_single_pass);
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	if (req_ctx->is_single_pass) {
127562306a36Sopenharmony_ci		/*
127662306a36Sopenharmony_ci		 * Single-pass flow
127762306a36Sopenharmony_ci		 */
127862306a36Sopenharmony_ci		cc_set_xcbc_desc(req, desc, seq_size);
127962306a36Sopenharmony_ci		cc_set_cipher_desc(req, desc, seq_size);
128062306a36Sopenharmony_ci		cc_proc_header_desc(req, desc, seq_size);
128162306a36Sopenharmony_ci		cc_proc_cipher_desc(req, data_flow_mode, desc, seq_size);
128262306a36Sopenharmony_ci		cc_proc_digest_desc(req, desc, seq_size);
128362306a36Sopenharmony_ci		return;
128462306a36Sopenharmony_ci	}
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	/*
128762306a36Sopenharmony_ci	 * Double-pass flow
128862306a36Sopenharmony_ci	 * Fallback for unsupported single-pass modes,
128962306a36Sopenharmony_ci	 * i.e. using assoc. data of non-word-multiple
129062306a36Sopenharmony_ci	 */
129162306a36Sopenharmony_ci	if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
129262306a36Sopenharmony_ci		/* encrypt first.. */
129362306a36Sopenharmony_ci		cc_proc_cipher(req, desc, seq_size, data_flow_mode);
129462306a36Sopenharmony_ci		/* authenc after.. */
129562306a36Sopenharmony_ci		cc_set_xcbc_desc(req, desc, seq_size);
129662306a36Sopenharmony_ci		cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct);
129762306a36Sopenharmony_ci		cc_proc_digest_desc(req, desc, seq_size);
129862306a36Sopenharmony_ci	} else { /*DECRYPT*/
129962306a36Sopenharmony_ci		/* authenc first.. */
130062306a36Sopenharmony_ci		cc_set_xcbc_desc(req, desc, seq_size);
130162306a36Sopenharmony_ci		cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct);
130262306a36Sopenharmony_ci		/* decrypt after..*/
130362306a36Sopenharmony_ci		cc_proc_cipher(req, desc, seq_size, data_flow_mode);
130462306a36Sopenharmony_ci		/* read the digest result with setting the completion bit
130562306a36Sopenharmony_ci		 * must be after the cipher operation
130662306a36Sopenharmony_ci		 */
130762306a36Sopenharmony_ci		cc_proc_digest_desc(req, desc, seq_size);
130862306a36Sopenharmony_ci	}
130962306a36Sopenharmony_ci}
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_cistatic int validate_data_size(struct cc_aead_ctx *ctx,
131262306a36Sopenharmony_ci			      enum drv_crypto_direction direct,
131362306a36Sopenharmony_ci			      struct aead_request *req)
131462306a36Sopenharmony_ci{
131562306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
131662306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
131762306a36Sopenharmony_ci	unsigned int assoclen = areq_ctx->assoclen;
131862306a36Sopenharmony_ci	unsigned int cipherlen = (direct == DRV_CRYPTO_DIRECTION_DECRYPT) ?
131962306a36Sopenharmony_ci			(req->cryptlen - ctx->authsize) : req->cryptlen;
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci	if (direct == DRV_CRYPTO_DIRECTION_DECRYPT &&
132262306a36Sopenharmony_ci	    req->cryptlen < ctx->authsize)
132362306a36Sopenharmony_ci		goto data_size_err;
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	areq_ctx->is_single_pass = true; /*defaulted to fast flow*/
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	switch (ctx->flow_mode) {
132862306a36Sopenharmony_ci	case S_DIN_to_AES:
132962306a36Sopenharmony_ci		if (ctx->cipher_mode == DRV_CIPHER_CBC &&
133062306a36Sopenharmony_ci		    !IS_ALIGNED(cipherlen, AES_BLOCK_SIZE))
133162306a36Sopenharmony_ci			goto data_size_err;
133262306a36Sopenharmony_ci		if (ctx->cipher_mode == DRV_CIPHER_CCM)
133362306a36Sopenharmony_ci			break;
133462306a36Sopenharmony_ci		if (ctx->cipher_mode == DRV_CIPHER_GCTR) {
133562306a36Sopenharmony_ci			if (areq_ctx->plaintext_authenticate_only)
133662306a36Sopenharmony_ci				areq_ctx->is_single_pass = false;
133762306a36Sopenharmony_ci			break;
133862306a36Sopenharmony_ci		}
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci		if (!IS_ALIGNED(assoclen, sizeof(u32)))
134162306a36Sopenharmony_ci			areq_ctx->is_single_pass = false;
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci		if (ctx->cipher_mode == DRV_CIPHER_CTR &&
134462306a36Sopenharmony_ci		    !IS_ALIGNED(cipherlen, sizeof(u32)))
134562306a36Sopenharmony_ci			areq_ctx->is_single_pass = false;
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci		break;
134862306a36Sopenharmony_ci	case S_DIN_to_DES:
134962306a36Sopenharmony_ci		if (!IS_ALIGNED(cipherlen, DES_BLOCK_SIZE))
135062306a36Sopenharmony_ci			goto data_size_err;
135162306a36Sopenharmony_ci		if (!IS_ALIGNED(assoclen, DES_BLOCK_SIZE))
135262306a36Sopenharmony_ci			areq_ctx->is_single_pass = false;
135362306a36Sopenharmony_ci		break;
135462306a36Sopenharmony_ci	default:
135562306a36Sopenharmony_ci		dev_err(dev, "Unexpected flow mode (%d)\n", ctx->flow_mode);
135662306a36Sopenharmony_ci		goto data_size_err;
135762306a36Sopenharmony_ci	}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	return 0;
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_cidata_size_err:
136262306a36Sopenharmony_ci	return -EINVAL;
136362306a36Sopenharmony_ci}
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_cistatic unsigned int format_ccm_a0(u8 *pa0_buff, u32 header_size)
136662306a36Sopenharmony_ci{
136762306a36Sopenharmony_ci	unsigned int len = 0;
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci	if (header_size == 0)
137062306a36Sopenharmony_ci		return 0;
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	if (header_size < ((1UL << 16) - (1UL << 8))) {
137362306a36Sopenharmony_ci		len = 2;
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_ci		pa0_buff[0] = (header_size >> 8) & 0xFF;
137662306a36Sopenharmony_ci		pa0_buff[1] = header_size & 0xFF;
137762306a36Sopenharmony_ci	} else {
137862306a36Sopenharmony_ci		len = 6;
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci		pa0_buff[0] = 0xFF;
138162306a36Sopenharmony_ci		pa0_buff[1] = 0xFE;
138262306a36Sopenharmony_ci		pa0_buff[2] = (header_size >> 24) & 0xFF;
138362306a36Sopenharmony_ci		pa0_buff[3] = (header_size >> 16) & 0xFF;
138462306a36Sopenharmony_ci		pa0_buff[4] = (header_size >> 8) & 0xFF;
138562306a36Sopenharmony_ci		pa0_buff[5] = header_size & 0xFF;
138662306a36Sopenharmony_ci	}
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci	return len;
138962306a36Sopenharmony_ci}
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_cistatic int set_msg_len(u8 *block, unsigned int msglen, unsigned int csize)
139262306a36Sopenharmony_ci{
139362306a36Sopenharmony_ci	__be32 data;
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	memset(block, 0, csize);
139662306a36Sopenharmony_ci	block += csize;
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	if (csize >= 4)
139962306a36Sopenharmony_ci		csize = 4;
140062306a36Sopenharmony_ci	else if (msglen > (1 << (8 * csize)))
140162306a36Sopenharmony_ci		return -EOVERFLOW;
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	data = cpu_to_be32(msglen);
140462306a36Sopenharmony_ci	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	return 0;
140762306a36Sopenharmony_ci}
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_cistatic int cc_ccm(struct aead_request *req, struct cc_hw_desc desc[],
141062306a36Sopenharmony_ci		  unsigned int *seq_size)
141162306a36Sopenharmony_ci{
141262306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
141362306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
141462306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
141562306a36Sopenharmony_ci	unsigned int idx = *seq_size;
141662306a36Sopenharmony_ci	unsigned int cipher_flow_mode;
141762306a36Sopenharmony_ci	dma_addr_t mac_result;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
142062306a36Sopenharmony_ci		cipher_flow_mode = AES_to_HASH_and_DOUT;
142162306a36Sopenharmony_ci		mac_result = req_ctx->mac_buf_dma_addr;
142262306a36Sopenharmony_ci	} else { /* Encrypt */
142362306a36Sopenharmony_ci		cipher_flow_mode = AES_and_HASH;
142462306a36Sopenharmony_ci		mac_result = req_ctx->icv_dma_addr;
142562306a36Sopenharmony_ci	}
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	/* load key */
142862306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
142962306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
143062306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
143162306a36Sopenharmony_ci		     ((ctx->enc_keylen == 24) ?  CC_AES_KEY_SIZE_MAX :
143262306a36Sopenharmony_ci		      ctx->enc_keylen), NS_BIT);
143362306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], ctx->enc_keylen);
143462306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
143562306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
143662306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_AES);
143762306a36Sopenharmony_ci	idx++;
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci	/* load ctr state */
144062306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
144162306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
144262306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], ctx->enc_keylen);
144362306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI,
144462306a36Sopenharmony_ci		     req_ctx->gen_ctx.iv_dma_addr, AES_BLOCK_SIZE, NS_BIT);
144562306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
144662306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
144762306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_AES);
144862306a36Sopenharmony_ci	idx++;
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci	/* load MAC key */
145162306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
145262306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
145362306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
145462306a36Sopenharmony_ci		     ((ctx->enc_keylen == 24) ?  CC_AES_KEY_SIZE_MAX :
145562306a36Sopenharmony_ci		      ctx->enc_keylen), NS_BIT);
145662306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], ctx->enc_keylen);
145762306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
145862306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
145962306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
146062306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
146162306a36Sopenharmony_ci	idx++;
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	/* load MAC state */
146462306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
146562306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
146662306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], ctx->enc_keylen);
146762306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
146862306a36Sopenharmony_ci		     AES_BLOCK_SIZE, NS_BIT);
146962306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
147062306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
147162306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
147262306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
147362306a36Sopenharmony_ci	idx++;
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci	/* process assoc data */
147662306a36Sopenharmony_ci	if (req_ctx->assoclen > 0) {
147762306a36Sopenharmony_ci		cc_set_assoc_desc(req, DIN_HASH, desc, &idx);
147862306a36Sopenharmony_ci	} else {
147962306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
148062306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_DLLI,
148162306a36Sopenharmony_ci			     sg_dma_address(&req_ctx->ccm_adata_sg),
148262306a36Sopenharmony_ci			     AES_BLOCK_SIZE + req_ctx->ccm_hdr_size, NS_BIT);
148362306a36Sopenharmony_ci		set_flow_mode(&desc[idx], DIN_HASH);
148462306a36Sopenharmony_ci		idx++;
148562306a36Sopenharmony_ci	}
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	/* process the cipher */
148862306a36Sopenharmony_ci	if (req_ctx->cryptlen)
148962306a36Sopenharmony_ci		cc_proc_cipher_desc(req, cipher_flow_mode, desc, &idx);
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	/* Read temporal MAC */
149262306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
149362306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
149462306a36Sopenharmony_ci	set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, ctx->authsize,
149562306a36Sopenharmony_ci		      NS_BIT, 0);
149662306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
149762306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
149862306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_HASH_to_DOUT);
149962306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
150062306a36Sopenharmony_ci	idx++;
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	/* load AES-CTR state (for last MAC calculation)*/
150362306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
150462306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
150562306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
150662306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, req_ctx->ccm_iv0_dma_addr,
150762306a36Sopenharmony_ci		     AES_BLOCK_SIZE, NS_BIT);
150862306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], ctx->enc_keylen);
150962306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
151062306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_AES);
151162306a36Sopenharmony_ci	idx++;
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
151462306a36Sopenharmony_ci	set_din_no_dma(&desc[idx], 0, 0xfffff0);
151562306a36Sopenharmony_ci	set_dout_no_dma(&desc[idx], 0, 0, 1);
151662306a36Sopenharmony_ci	idx++;
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci	/* encrypt the "T" value and store MAC in mac_state */
151962306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
152062306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
152162306a36Sopenharmony_ci		     ctx->authsize, NS_BIT);
152262306a36Sopenharmony_ci	set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1);
152362306a36Sopenharmony_ci	set_queue_last_ind(ctx->drvdata, &desc[idx]);
152462306a36Sopenharmony_ci	set_flow_mode(&desc[idx], DIN_AES_DOUT);
152562306a36Sopenharmony_ci	idx++;
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	*seq_size = idx;
152862306a36Sopenharmony_ci	return 0;
152962306a36Sopenharmony_ci}
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_cistatic int config_ccm_adata(struct aead_request *req)
153262306a36Sopenharmony_ci{
153362306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
153462306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
153562306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
153662306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
153762306a36Sopenharmony_ci	//unsigned int size_of_a = 0, rem_a_size = 0;
153862306a36Sopenharmony_ci	unsigned int lp = req->iv[0];
153962306a36Sopenharmony_ci	/* Note: The code assume that req->iv[0] already contains the value
154062306a36Sopenharmony_ci	 * of L' of RFC3610
154162306a36Sopenharmony_ci	 */
154262306a36Sopenharmony_ci	unsigned int l = lp + 1;  /* This is L' of RFC 3610. */
154362306a36Sopenharmony_ci	unsigned int m = ctx->authsize;  /* This is M' of RFC 3610. */
154462306a36Sopenharmony_ci	u8 *b0 = req_ctx->ccm_config + CCM_B0_OFFSET;
154562306a36Sopenharmony_ci	u8 *a0 = req_ctx->ccm_config + CCM_A0_OFFSET;
154662306a36Sopenharmony_ci	u8 *ctr_count_0 = req_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET;
154762306a36Sopenharmony_ci	unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
154862306a36Sopenharmony_ci				 DRV_CRYPTO_DIRECTION_ENCRYPT) ?
154962306a36Sopenharmony_ci				req->cryptlen :
155062306a36Sopenharmony_ci				(req->cryptlen - ctx->authsize);
155162306a36Sopenharmony_ci	int rc;
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci	memset(req_ctx->mac_buf, 0, AES_BLOCK_SIZE);
155462306a36Sopenharmony_ci	memset(req_ctx->ccm_config, 0, AES_BLOCK_SIZE * 3);
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	/* taken from crypto/ccm.c */
155762306a36Sopenharmony_ci	/* 2 <= L <= 8, so 1 <= L' <= 7. */
155862306a36Sopenharmony_ci	if (l < 2 || l > 8) {
155962306a36Sopenharmony_ci		dev_dbg(dev, "illegal iv value %X\n", req->iv[0]);
156062306a36Sopenharmony_ci		return -EINVAL;
156162306a36Sopenharmony_ci	}
156262306a36Sopenharmony_ci	memcpy(b0, req->iv, AES_BLOCK_SIZE);
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	/* format control info per RFC 3610 and
156562306a36Sopenharmony_ci	 * NIST Special Publication 800-38C
156662306a36Sopenharmony_ci	 */
156762306a36Sopenharmony_ci	*b0 |= (8 * ((m - 2) / 2));
156862306a36Sopenharmony_ci	if (req_ctx->assoclen > 0)
156962306a36Sopenharmony_ci		*b0 |= 64;  /* Enable bit 6 if Adata exists. */
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	rc = set_msg_len(b0 + 16 - l, cryptlen, l);  /* Write L'. */
157262306a36Sopenharmony_ci	if (rc) {
157362306a36Sopenharmony_ci		dev_err(dev, "message len overflow detected");
157462306a36Sopenharmony_ci		return rc;
157562306a36Sopenharmony_ci	}
157662306a36Sopenharmony_ci	 /* END of "taken from crypto/ccm.c" */
157762306a36Sopenharmony_ci
157862306a36Sopenharmony_ci	/* l(a) - size of associated data. */
157962306a36Sopenharmony_ci	req_ctx->ccm_hdr_size = format_ccm_a0(a0, req_ctx->assoclen);
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci	memset(req->iv + 15 - req->iv[0], 0, req->iv[0] + 1);
158262306a36Sopenharmony_ci	req->iv[15] = 1;
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	memcpy(ctr_count_0, req->iv, AES_BLOCK_SIZE);
158562306a36Sopenharmony_ci	ctr_count_0[15] = 0;
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	return 0;
158862306a36Sopenharmony_ci}
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_cistatic void cc_proc_rfc4309_ccm(struct aead_request *req)
159162306a36Sopenharmony_ci{
159262306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
159362306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
159462306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	/* L' */
159762306a36Sopenharmony_ci	memset(areq_ctx->ctr_iv, 0, AES_BLOCK_SIZE);
159862306a36Sopenharmony_ci	/* For RFC 4309, always use 4 bytes for message length
159962306a36Sopenharmony_ci	 * (at most 2^32-1 bytes).
160062306a36Sopenharmony_ci	 */
160162306a36Sopenharmony_ci	areq_ctx->ctr_iv[0] = 3;
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci	/* In RFC 4309 there is an 11-bytes nonce+IV part,
160462306a36Sopenharmony_ci	 * that we build here.
160562306a36Sopenharmony_ci	 */
160662306a36Sopenharmony_ci	memcpy(areq_ctx->ctr_iv + CCM_BLOCK_NONCE_OFFSET, ctx->ctr_nonce,
160762306a36Sopenharmony_ci	       CCM_BLOCK_NONCE_SIZE);
160862306a36Sopenharmony_ci	memcpy(areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, req->iv,
160962306a36Sopenharmony_ci	       CCM_BLOCK_IV_SIZE);
161062306a36Sopenharmony_ci	req->iv = areq_ctx->ctr_iv;
161162306a36Sopenharmony_ci}
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_cistatic void cc_set_ghash_desc(struct aead_request *req,
161462306a36Sopenharmony_ci			      struct cc_hw_desc desc[], unsigned int *seq_size)
161562306a36Sopenharmony_ci{
161662306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
161762306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
161862306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
161962306a36Sopenharmony_ci	unsigned int idx = *seq_size;
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	/* load key to AES*/
162262306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
162362306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
162462306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
162562306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
162662306a36Sopenharmony_ci		     ctx->enc_keylen, NS_BIT);
162762306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], ctx->enc_keylen);
162862306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
162962306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_AES);
163062306a36Sopenharmony_ci	idx++;
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	/* process one zero block to generate hkey */
163362306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
163462306a36Sopenharmony_ci	set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
163562306a36Sopenharmony_ci	set_dout_dlli(&desc[idx], req_ctx->hkey_dma_addr, AES_BLOCK_SIZE,
163662306a36Sopenharmony_ci		      NS_BIT, 0);
163762306a36Sopenharmony_ci	set_flow_mode(&desc[idx], DIN_AES_DOUT);
163862306a36Sopenharmony_ci	idx++;
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	/* Memory Barrier */
164162306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
164262306a36Sopenharmony_ci	set_din_no_dma(&desc[idx], 0, 0xfffff0);
164362306a36Sopenharmony_ci	set_dout_no_dma(&desc[idx], 0, 0, 1);
164462306a36Sopenharmony_ci	idx++;
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci	/* Load GHASH subkey */
164762306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
164862306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, req_ctx->hkey_dma_addr,
164962306a36Sopenharmony_ci		     AES_BLOCK_SIZE, NS_BIT);
165062306a36Sopenharmony_ci	set_dout_no_dma(&desc[idx], 0, 0, 1);
165162306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
165262306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
165362306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
165462306a36Sopenharmony_ci	set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
165562306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
165662306a36Sopenharmony_ci	idx++;
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	/* Configure Hash Engine to work with GHASH.
165962306a36Sopenharmony_ci	 * Since it was not possible to extend HASH submodes to add GHASH,
166062306a36Sopenharmony_ci	 * The following command is necessary in order to
166162306a36Sopenharmony_ci	 * select GHASH (according to HW designers)
166262306a36Sopenharmony_ci	 */
166362306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
166462306a36Sopenharmony_ci	set_din_no_dma(&desc[idx], 0, 0xfffff0);
166562306a36Sopenharmony_ci	set_dout_no_dma(&desc[idx], 0, 0, 1);
166662306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
166762306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
166862306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
166962306a36Sopenharmony_ci	set_cipher_do(&desc[idx], 1); //1=AES_SK RKEK
167062306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
167162306a36Sopenharmony_ci	set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
167262306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
167362306a36Sopenharmony_ci	idx++;
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	/* Load GHASH initial STATE (which is 0). (for any hash there is an
167662306a36Sopenharmony_ci	 * initial state)
167762306a36Sopenharmony_ci	 */
167862306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
167962306a36Sopenharmony_ci	set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
168062306a36Sopenharmony_ci	set_dout_no_dma(&desc[idx], 0, 0, 1);
168162306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_HASH);
168262306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
168362306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
168462306a36Sopenharmony_ci	set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
168562306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
168662306a36Sopenharmony_ci	idx++;
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	*seq_size = idx;
168962306a36Sopenharmony_ci}
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_cistatic void cc_set_gctr_desc(struct aead_request *req, struct cc_hw_desc desc[],
169262306a36Sopenharmony_ci			     unsigned int *seq_size)
169362306a36Sopenharmony_ci{
169462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
169562306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
169662306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
169762306a36Sopenharmony_ci	unsigned int idx = *seq_size;
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	/* load key to AES*/
170062306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
170162306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
170262306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
170362306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
170462306a36Sopenharmony_ci		     ctx->enc_keylen, NS_BIT);
170562306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], ctx->enc_keylen);
170662306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
170762306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_AES);
170862306a36Sopenharmony_ci	idx++;
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	if (req_ctx->cryptlen && !req_ctx->plaintext_authenticate_only) {
171162306a36Sopenharmony_ci		/* load AES/CTR initial CTR value inc by 2*/
171262306a36Sopenharmony_ci		hw_desc_init(&desc[idx]);
171362306a36Sopenharmony_ci		set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
171462306a36Sopenharmony_ci		set_key_size_aes(&desc[idx], ctx->enc_keylen);
171562306a36Sopenharmony_ci		set_din_type(&desc[idx], DMA_DLLI,
171662306a36Sopenharmony_ci			     req_ctx->gcm_iv_inc2_dma_addr, AES_BLOCK_SIZE,
171762306a36Sopenharmony_ci			     NS_BIT);
171862306a36Sopenharmony_ci		set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
171962306a36Sopenharmony_ci		set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
172062306a36Sopenharmony_ci		set_flow_mode(&desc[idx], S_DIN_to_AES);
172162306a36Sopenharmony_ci		idx++;
172262306a36Sopenharmony_ci	}
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	*seq_size = idx;
172562306a36Sopenharmony_ci}
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_cistatic void cc_proc_gcm_result(struct aead_request *req,
172862306a36Sopenharmony_ci			       struct cc_hw_desc desc[],
172962306a36Sopenharmony_ci			       unsigned int *seq_size)
173062306a36Sopenharmony_ci{
173162306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
173262306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
173362306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
173462306a36Sopenharmony_ci	dma_addr_t mac_result;
173562306a36Sopenharmony_ci	unsigned int idx = *seq_size;
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci	if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
173862306a36Sopenharmony_ci		mac_result = req_ctx->mac_buf_dma_addr;
173962306a36Sopenharmony_ci	} else { /* Encrypt */
174062306a36Sopenharmony_ci		mac_result = req_ctx->icv_dma_addr;
174162306a36Sopenharmony_ci	}
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci	/* process(ghash) gcm_block_len */
174462306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
174562306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_block_len_dma_addr,
174662306a36Sopenharmony_ci		     AES_BLOCK_SIZE, NS_BIT);
174762306a36Sopenharmony_ci	set_flow_mode(&desc[idx], DIN_HASH);
174862306a36Sopenharmony_ci	idx++;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	/* Store GHASH state after GHASH(Associated Data + Cipher +LenBlock) */
175162306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
175262306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
175362306a36Sopenharmony_ci	set_din_no_dma(&desc[idx], 0, 0xfffff0);
175462306a36Sopenharmony_ci	set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, AES_BLOCK_SIZE,
175562306a36Sopenharmony_ci		      NS_BIT, 0);
175662306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
175762306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_HASH_to_DOUT);
175862306a36Sopenharmony_ci	set_aes_not_hash_mode(&desc[idx]);
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	idx++;
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci	/* load AES/CTR initial CTR value inc by 1*/
176362306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
176462306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
176562306a36Sopenharmony_ci	set_key_size_aes(&desc[idx], ctx->enc_keylen);
176662306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_iv_inc1_dma_addr,
176762306a36Sopenharmony_ci		     AES_BLOCK_SIZE, NS_BIT);
176862306a36Sopenharmony_ci	set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
176962306a36Sopenharmony_ci	set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
177062306a36Sopenharmony_ci	set_flow_mode(&desc[idx], S_DIN_to_AES);
177162306a36Sopenharmony_ci	idx++;
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci	/* Memory Barrier */
177462306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
177562306a36Sopenharmony_ci	set_din_no_dma(&desc[idx], 0, 0xfffff0);
177662306a36Sopenharmony_ci	set_dout_no_dma(&desc[idx], 0, 0, 1);
177762306a36Sopenharmony_ci	idx++;
177862306a36Sopenharmony_ci
177962306a36Sopenharmony_ci	/* process GCTR on stored GHASH and store MAC in mac_state*/
178062306a36Sopenharmony_ci	hw_desc_init(&desc[idx]);
178162306a36Sopenharmony_ci	set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
178262306a36Sopenharmony_ci	set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
178362306a36Sopenharmony_ci		     AES_BLOCK_SIZE, NS_BIT);
178462306a36Sopenharmony_ci	set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1);
178562306a36Sopenharmony_ci	set_queue_last_ind(ctx->drvdata, &desc[idx]);
178662306a36Sopenharmony_ci	set_flow_mode(&desc[idx], DIN_AES_DOUT);
178762306a36Sopenharmony_ci	idx++;
178862306a36Sopenharmony_ci
178962306a36Sopenharmony_ci	*seq_size = idx;
179062306a36Sopenharmony_ci}
179162306a36Sopenharmony_ci
179262306a36Sopenharmony_cistatic int cc_gcm(struct aead_request *req, struct cc_hw_desc desc[],
179362306a36Sopenharmony_ci		  unsigned int *seq_size)
179462306a36Sopenharmony_ci{
179562306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
179662306a36Sopenharmony_ci	unsigned int cipher_flow_mode;
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_ci	//in RFC4543 no data to encrypt. just copy data from src to dest.
179962306a36Sopenharmony_ci	if (req_ctx->plaintext_authenticate_only) {
180062306a36Sopenharmony_ci		cc_proc_cipher_desc(req, BYPASS, desc, seq_size);
180162306a36Sopenharmony_ci		cc_set_ghash_desc(req, desc, seq_size);
180262306a36Sopenharmony_ci		/* process(ghash) assoc data */
180362306a36Sopenharmony_ci		cc_set_assoc_desc(req, DIN_HASH, desc, seq_size);
180462306a36Sopenharmony_ci		cc_set_gctr_desc(req, desc, seq_size);
180562306a36Sopenharmony_ci		cc_proc_gcm_result(req, desc, seq_size);
180662306a36Sopenharmony_ci		return 0;
180762306a36Sopenharmony_ci	}
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci	if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
181062306a36Sopenharmony_ci		cipher_flow_mode = AES_and_HASH;
181162306a36Sopenharmony_ci	} else { /* Encrypt */
181262306a36Sopenharmony_ci		cipher_flow_mode = AES_to_HASH_and_DOUT;
181362306a36Sopenharmony_ci	}
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	// for gcm and rfc4106.
181662306a36Sopenharmony_ci	cc_set_ghash_desc(req, desc, seq_size);
181762306a36Sopenharmony_ci	/* process(ghash) assoc data */
181862306a36Sopenharmony_ci	if (req_ctx->assoclen > 0)
181962306a36Sopenharmony_ci		cc_set_assoc_desc(req, DIN_HASH, desc, seq_size);
182062306a36Sopenharmony_ci	cc_set_gctr_desc(req, desc, seq_size);
182162306a36Sopenharmony_ci	/* process(gctr+ghash) */
182262306a36Sopenharmony_ci	if (req_ctx->cryptlen)
182362306a36Sopenharmony_ci		cc_proc_cipher_desc(req, cipher_flow_mode, desc, seq_size);
182462306a36Sopenharmony_ci	cc_proc_gcm_result(req, desc, seq_size);
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci	return 0;
182762306a36Sopenharmony_ci}
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_cistatic int config_gcm_context(struct aead_request *req)
183062306a36Sopenharmony_ci{
183162306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
183262306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
183362306a36Sopenharmony_ci	struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req);
183462306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci	unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
183762306a36Sopenharmony_ci				 DRV_CRYPTO_DIRECTION_ENCRYPT) ?
183862306a36Sopenharmony_ci				req->cryptlen :
183962306a36Sopenharmony_ci				(req->cryptlen - ctx->authsize);
184062306a36Sopenharmony_ci	__be32 counter = cpu_to_be32(2);
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_ci	dev_dbg(dev, "%s() cryptlen = %d, req_ctx->assoclen = %d ctx->authsize = %d\n",
184362306a36Sopenharmony_ci		__func__, cryptlen, req_ctx->assoclen, ctx->authsize);
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci	memset(req_ctx->hkey, 0, AES_BLOCK_SIZE);
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci	memset(req_ctx->mac_buf, 0, AES_BLOCK_SIZE);
184862306a36Sopenharmony_ci
184962306a36Sopenharmony_ci	memcpy(req->iv + 12, &counter, 4);
185062306a36Sopenharmony_ci	memcpy(req_ctx->gcm_iv_inc2, req->iv, 16);
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci	counter = cpu_to_be32(1);
185362306a36Sopenharmony_ci	memcpy(req->iv + 12, &counter, 4);
185462306a36Sopenharmony_ci	memcpy(req_ctx->gcm_iv_inc1, req->iv, 16);
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_ci	if (!req_ctx->plaintext_authenticate_only) {
185762306a36Sopenharmony_ci		__be64 temp64;
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci		temp64 = cpu_to_be64(req_ctx->assoclen * 8);
186062306a36Sopenharmony_ci		memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64));
186162306a36Sopenharmony_ci		temp64 = cpu_to_be64(cryptlen * 8);
186262306a36Sopenharmony_ci		memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8);
186362306a36Sopenharmony_ci	} else {
186462306a36Sopenharmony_ci		/* rfc4543=>  all data(AAD,IV,Plain) are considered additional
186562306a36Sopenharmony_ci		 * data that is nothing is encrypted.
186662306a36Sopenharmony_ci		 */
186762306a36Sopenharmony_ci		__be64 temp64;
186862306a36Sopenharmony_ci
186962306a36Sopenharmony_ci		temp64 = cpu_to_be64((req_ctx->assoclen + cryptlen) * 8);
187062306a36Sopenharmony_ci		memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64));
187162306a36Sopenharmony_ci		temp64 = 0;
187262306a36Sopenharmony_ci		memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8);
187362306a36Sopenharmony_ci	}
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci	return 0;
187662306a36Sopenharmony_ci}
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_cistatic void cc_proc_rfc4_gcm(struct aead_request *req)
187962306a36Sopenharmony_ci{
188062306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
188162306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
188262306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_ci	memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_NONCE_OFFSET,
188562306a36Sopenharmony_ci	       ctx->ctr_nonce, GCM_BLOCK_RFC4_NONCE_SIZE);
188662306a36Sopenharmony_ci	memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_IV_OFFSET, req->iv,
188762306a36Sopenharmony_ci	       GCM_BLOCK_RFC4_IV_SIZE);
188862306a36Sopenharmony_ci	req->iv = areq_ctx->ctr_iv;
188962306a36Sopenharmony_ci}
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_cistatic int cc_proc_aead(struct aead_request *req,
189262306a36Sopenharmony_ci			enum drv_crypto_direction direct)
189362306a36Sopenharmony_ci{
189462306a36Sopenharmony_ci	int rc = 0;
189562306a36Sopenharmony_ci	int seq_len = 0;
189662306a36Sopenharmony_ci	struct cc_hw_desc desc[MAX_AEAD_PROCESS_SEQ];
189762306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
189862306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
189962306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
190062306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
190162306a36Sopenharmony_ci	struct cc_crypto_req cc_req = {};
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	dev_dbg(dev, "%s context=%p req=%p iv=%p src=%p src_ofs=%d dst=%p dst_ofs=%d cryptolen=%d\n",
190462306a36Sopenharmony_ci		((direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Enc" : "Dec"),
190562306a36Sopenharmony_ci		ctx, req, req->iv, sg_virt(req->src), req->src->offset,
190662306a36Sopenharmony_ci		sg_virt(req->dst), req->dst->offset, req->cryptlen);
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_ci	/* STAT_PHASE_0: Init and sanity checks */
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	/* Check data length according to mode */
191162306a36Sopenharmony_ci	if (validate_data_size(ctx, direct, req)) {
191262306a36Sopenharmony_ci		dev_err(dev, "Unsupported crypt/assoc len %d/%d.\n",
191362306a36Sopenharmony_ci			req->cryptlen, areq_ctx->assoclen);
191462306a36Sopenharmony_ci		return -EINVAL;
191562306a36Sopenharmony_ci	}
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci	/* Setup request structure */
191862306a36Sopenharmony_ci	cc_req.user_cb = cc_aead_complete;
191962306a36Sopenharmony_ci	cc_req.user_arg = req;
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_ci	/* Setup request context */
192262306a36Sopenharmony_ci	areq_ctx->gen_ctx.op_type = direct;
192362306a36Sopenharmony_ci	areq_ctx->req_authsize = ctx->authsize;
192462306a36Sopenharmony_ci	areq_ctx->cipher_mode = ctx->cipher_mode;
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci	/* STAT_PHASE_1: Map buffers */
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci	if (ctx->cipher_mode == DRV_CIPHER_CTR) {
192962306a36Sopenharmony_ci		/* Build CTR IV - Copy nonce from last 4 bytes in
193062306a36Sopenharmony_ci		 * CTR key to first 4 bytes in CTR IV
193162306a36Sopenharmony_ci		 */
193262306a36Sopenharmony_ci		memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce,
193362306a36Sopenharmony_ci		       CTR_RFC3686_NONCE_SIZE);
193462306a36Sopenharmony_ci		memcpy(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, req->iv,
193562306a36Sopenharmony_ci		       CTR_RFC3686_IV_SIZE);
193662306a36Sopenharmony_ci		/* Initialize counter portion of counter block */
193762306a36Sopenharmony_ci		*(__be32 *)(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE +
193862306a36Sopenharmony_ci			    CTR_RFC3686_IV_SIZE) = cpu_to_be32(1);
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci		/* Replace with counter iv */
194162306a36Sopenharmony_ci		req->iv = areq_ctx->ctr_iv;
194262306a36Sopenharmony_ci		areq_ctx->hw_iv_size = CTR_RFC3686_BLOCK_SIZE;
194362306a36Sopenharmony_ci	} else if ((ctx->cipher_mode == DRV_CIPHER_CCM) ||
194462306a36Sopenharmony_ci		   (ctx->cipher_mode == DRV_CIPHER_GCTR)) {
194562306a36Sopenharmony_ci		areq_ctx->hw_iv_size = AES_BLOCK_SIZE;
194662306a36Sopenharmony_ci		if (areq_ctx->ctr_iv != req->iv) {
194762306a36Sopenharmony_ci			memcpy(areq_ctx->ctr_iv, req->iv,
194862306a36Sopenharmony_ci			       crypto_aead_ivsize(tfm));
194962306a36Sopenharmony_ci			req->iv = areq_ctx->ctr_iv;
195062306a36Sopenharmony_ci		}
195162306a36Sopenharmony_ci	}  else {
195262306a36Sopenharmony_ci		areq_ctx->hw_iv_size = crypto_aead_ivsize(tfm);
195362306a36Sopenharmony_ci	}
195462306a36Sopenharmony_ci
195562306a36Sopenharmony_ci	if (ctx->cipher_mode == DRV_CIPHER_CCM) {
195662306a36Sopenharmony_ci		rc = config_ccm_adata(req);
195762306a36Sopenharmony_ci		if (rc) {
195862306a36Sopenharmony_ci			dev_dbg(dev, "config_ccm_adata() returned with a failure %d!",
195962306a36Sopenharmony_ci				rc);
196062306a36Sopenharmony_ci			goto exit;
196162306a36Sopenharmony_ci		}
196262306a36Sopenharmony_ci	} else {
196362306a36Sopenharmony_ci		areq_ctx->ccm_hdr_size = ccm_header_size_null;
196462306a36Sopenharmony_ci	}
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	if (ctx->cipher_mode == DRV_CIPHER_GCTR) {
196762306a36Sopenharmony_ci		rc = config_gcm_context(req);
196862306a36Sopenharmony_ci		if (rc) {
196962306a36Sopenharmony_ci			dev_dbg(dev, "config_gcm_context() returned with a failure %d!",
197062306a36Sopenharmony_ci				rc);
197162306a36Sopenharmony_ci			goto exit;
197262306a36Sopenharmony_ci		}
197362306a36Sopenharmony_ci	}
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci	rc = cc_map_aead_request(ctx->drvdata, req);
197662306a36Sopenharmony_ci	if (rc) {
197762306a36Sopenharmony_ci		dev_err(dev, "map_request() failed\n");
197862306a36Sopenharmony_ci		goto exit;
197962306a36Sopenharmony_ci	}
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_ci	/* STAT_PHASE_2: Create sequence */
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci	/* Load MLLI tables to SRAM if necessary */
198462306a36Sopenharmony_ci	cc_mlli_to_sram(req, desc, &seq_len);
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_ci	switch (ctx->auth_mode) {
198762306a36Sopenharmony_ci	case DRV_HASH_SHA1:
198862306a36Sopenharmony_ci	case DRV_HASH_SHA256:
198962306a36Sopenharmony_ci		cc_hmac_authenc(req, desc, &seq_len);
199062306a36Sopenharmony_ci		break;
199162306a36Sopenharmony_ci	case DRV_HASH_XCBC_MAC:
199262306a36Sopenharmony_ci		cc_xcbc_authenc(req, desc, &seq_len);
199362306a36Sopenharmony_ci		break;
199462306a36Sopenharmony_ci	case DRV_HASH_NULL:
199562306a36Sopenharmony_ci		if (ctx->cipher_mode == DRV_CIPHER_CCM)
199662306a36Sopenharmony_ci			cc_ccm(req, desc, &seq_len);
199762306a36Sopenharmony_ci		if (ctx->cipher_mode == DRV_CIPHER_GCTR)
199862306a36Sopenharmony_ci			cc_gcm(req, desc, &seq_len);
199962306a36Sopenharmony_ci		break;
200062306a36Sopenharmony_ci	default:
200162306a36Sopenharmony_ci		dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode);
200262306a36Sopenharmony_ci		cc_unmap_aead_request(dev, req);
200362306a36Sopenharmony_ci		rc = -ENOTSUPP;
200462306a36Sopenharmony_ci		goto exit;
200562306a36Sopenharmony_ci	}
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_ci	/* STAT_PHASE_3: Lock HW and push sequence */
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci	rc = cc_send_request(ctx->drvdata, &cc_req, desc, seq_len, &req->base);
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci	if (rc != -EINPROGRESS && rc != -EBUSY) {
201262306a36Sopenharmony_ci		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
201362306a36Sopenharmony_ci		cc_unmap_aead_request(dev, req);
201462306a36Sopenharmony_ci	}
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ciexit:
201762306a36Sopenharmony_ci	return rc;
201862306a36Sopenharmony_ci}
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_cistatic int cc_aead_encrypt(struct aead_request *req)
202162306a36Sopenharmony_ci{
202262306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
202362306a36Sopenharmony_ci	int rc;
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci	memset(areq_ctx, 0, sizeof(*areq_ctx));
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	/* No generated IV required */
202862306a36Sopenharmony_ci	areq_ctx->backup_iv = req->iv;
202962306a36Sopenharmony_ci	areq_ctx->assoclen = req->assoclen;
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci	rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
203262306a36Sopenharmony_ci	if (rc != -EINPROGRESS && rc != -EBUSY)
203362306a36Sopenharmony_ci		req->iv = areq_ctx->backup_iv;
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	return rc;
203662306a36Sopenharmony_ci}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_cistatic int cc_rfc4309_ccm_encrypt(struct aead_request *req)
203962306a36Sopenharmony_ci{
204062306a36Sopenharmony_ci	/* Very similar to cc_aead_encrypt() above. */
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
204362306a36Sopenharmony_ci	int rc;
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	rc = crypto_ipsec_check_assoclen(req->assoclen);
204662306a36Sopenharmony_ci	if (rc)
204762306a36Sopenharmony_ci		goto out;
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci	memset(areq_ctx, 0, sizeof(*areq_ctx));
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_ci	/* No generated IV required */
205262306a36Sopenharmony_ci	areq_ctx->backup_iv = req->iv;
205362306a36Sopenharmony_ci	areq_ctx->assoclen = req->assoclen - CCM_BLOCK_IV_SIZE;
205462306a36Sopenharmony_ci
205562306a36Sopenharmony_ci	cc_proc_rfc4309_ccm(req);
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci	rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
205862306a36Sopenharmony_ci	if (rc != -EINPROGRESS && rc != -EBUSY)
205962306a36Sopenharmony_ci		req->iv = areq_ctx->backup_iv;
206062306a36Sopenharmony_ciout:
206162306a36Sopenharmony_ci	return rc;
206262306a36Sopenharmony_ci}
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_cistatic int cc_aead_decrypt(struct aead_request *req)
206562306a36Sopenharmony_ci{
206662306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
206762306a36Sopenharmony_ci	int rc;
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_ci	memset(areq_ctx, 0, sizeof(*areq_ctx));
207062306a36Sopenharmony_ci
207162306a36Sopenharmony_ci	/* No generated IV required */
207262306a36Sopenharmony_ci	areq_ctx->backup_iv = req->iv;
207362306a36Sopenharmony_ci	areq_ctx->assoclen = req->assoclen;
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT);
207662306a36Sopenharmony_ci	if (rc != -EINPROGRESS && rc != -EBUSY)
207762306a36Sopenharmony_ci		req->iv = areq_ctx->backup_iv;
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci	return rc;
208062306a36Sopenharmony_ci}
208162306a36Sopenharmony_ci
208262306a36Sopenharmony_cistatic int cc_rfc4309_ccm_decrypt(struct aead_request *req)
208362306a36Sopenharmony_ci{
208462306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
208562306a36Sopenharmony_ci	int rc;
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	rc = crypto_ipsec_check_assoclen(req->assoclen);
208862306a36Sopenharmony_ci	if (rc)
208962306a36Sopenharmony_ci		goto out;
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	memset(areq_ctx, 0, sizeof(*areq_ctx));
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_ci	/* No generated IV required */
209462306a36Sopenharmony_ci	areq_ctx->backup_iv = req->iv;
209562306a36Sopenharmony_ci	areq_ctx->assoclen = req->assoclen - CCM_BLOCK_IV_SIZE;
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci	cc_proc_rfc4309_ccm(req);
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT);
210062306a36Sopenharmony_ci	if (rc != -EINPROGRESS && rc != -EBUSY)
210162306a36Sopenharmony_ci		req->iv = areq_ctx->backup_iv;
210262306a36Sopenharmony_ci
210362306a36Sopenharmony_ciout:
210462306a36Sopenharmony_ci	return rc;
210562306a36Sopenharmony_ci}
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_cistatic int cc_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
210862306a36Sopenharmony_ci				 unsigned int keylen)
210962306a36Sopenharmony_ci{
211062306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
211162306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
211262306a36Sopenharmony_ci
211362306a36Sopenharmony_ci	dev_dbg(dev, "%s()  keylen %d, key %p\n", __func__, keylen, key);
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_ci	if (keylen < 4)
211662306a36Sopenharmony_ci		return -EINVAL;
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_ci	keylen -= 4;
211962306a36Sopenharmony_ci	memcpy(ctx->ctr_nonce, key + keylen, 4);
212062306a36Sopenharmony_ci
212162306a36Sopenharmony_ci	return cc_aead_setkey(tfm, key, keylen);
212262306a36Sopenharmony_ci}
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_cistatic int cc_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
212562306a36Sopenharmony_ci				 unsigned int keylen)
212662306a36Sopenharmony_ci{
212762306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
212862306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ci	dev_dbg(dev, "%s()  keylen %d, key %p\n", __func__, keylen, key);
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_ci	if (keylen < 4)
213362306a36Sopenharmony_ci		return -EINVAL;
213462306a36Sopenharmony_ci
213562306a36Sopenharmony_ci	keylen -= 4;
213662306a36Sopenharmony_ci	memcpy(ctx->ctr_nonce, key + keylen, 4);
213762306a36Sopenharmony_ci
213862306a36Sopenharmony_ci	return cc_aead_setkey(tfm, key, keylen);
213962306a36Sopenharmony_ci}
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_cistatic int cc_gcm_setauthsize(struct crypto_aead *authenc,
214262306a36Sopenharmony_ci			      unsigned int authsize)
214362306a36Sopenharmony_ci{
214462306a36Sopenharmony_ci	switch (authsize) {
214562306a36Sopenharmony_ci	case 4:
214662306a36Sopenharmony_ci	case 8:
214762306a36Sopenharmony_ci	case 12:
214862306a36Sopenharmony_ci	case 13:
214962306a36Sopenharmony_ci	case 14:
215062306a36Sopenharmony_ci	case 15:
215162306a36Sopenharmony_ci	case 16:
215262306a36Sopenharmony_ci		break;
215362306a36Sopenharmony_ci	default:
215462306a36Sopenharmony_ci		return -EINVAL;
215562306a36Sopenharmony_ci	}
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_ci	return cc_aead_setauthsize(authenc, authsize);
215862306a36Sopenharmony_ci}
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_cistatic int cc_rfc4106_gcm_setauthsize(struct crypto_aead *authenc,
216162306a36Sopenharmony_ci				      unsigned int authsize)
216262306a36Sopenharmony_ci{
216362306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc);
216462306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
216562306a36Sopenharmony_ci
216662306a36Sopenharmony_ci	dev_dbg(dev, "authsize %d\n", authsize);
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci	switch (authsize) {
216962306a36Sopenharmony_ci	case 8:
217062306a36Sopenharmony_ci	case 12:
217162306a36Sopenharmony_ci	case 16:
217262306a36Sopenharmony_ci		break;
217362306a36Sopenharmony_ci	default:
217462306a36Sopenharmony_ci		return -EINVAL;
217562306a36Sopenharmony_ci	}
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci	return cc_aead_setauthsize(authenc, authsize);
217862306a36Sopenharmony_ci}
217962306a36Sopenharmony_ci
218062306a36Sopenharmony_cistatic int cc_rfc4543_gcm_setauthsize(struct crypto_aead *authenc,
218162306a36Sopenharmony_ci				      unsigned int authsize)
218262306a36Sopenharmony_ci{
218362306a36Sopenharmony_ci	struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc);
218462306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(ctx->drvdata);
218562306a36Sopenharmony_ci
218662306a36Sopenharmony_ci	dev_dbg(dev, "authsize %d\n", authsize);
218762306a36Sopenharmony_ci
218862306a36Sopenharmony_ci	if (authsize != 16)
218962306a36Sopenharmony_ci		return -EINVAL;
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci	return cc_aead_setauthsize(authenc, authsize);
219262306a36Sopenharmony_ci}
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_cistatic int cc_rfc4106_gcm_encrypt(struct aead_request *req)
219562306a36Sopenharmony_ci{
219662306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
219762306a36Sopenharmony_ci	int rc;
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_ci	rc = crypto_ipsec_check_assoclen(req->assoclen);
220062306a36Sopenharmony_ci	if (rc)
220162306a36Sopenharmony_ci		goto out;
220262306a36Sopenharmony_ci
220362306a36Sopenharmony_ci	memset(areq_ctx, 0, sizeof(*areq_ctx));
220462306a36Sopenharmony_ci
220562306a36Sopenharmony_ci	/* No generated IV required */
220662306a36Sopenharmony_ci	areq_ctx->backup_iv = req->iv;
220762306a36Sopenharmony_ci	areq_ctx->assoclen = req->assoclen - GCM_BLOCK_RFC4_IV_SIZE;
220862306a36Sopenharmony_ci
220962306a36Sopenharmony_ci	cc_proc_rfc4_gcm(req);
221062306a36Sopenharmony_ci
221162306a36Sopenharmony_ci	rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
221262306a36Sopenharmony_ci	if (rc != -EINPROGRESS && rc != -EBUSY)
221362306a36Sopenharmony_ci		req->iv = areq_ctx->backup_iv;
221462306a36Sopenharmony_ciout:
221562306a36Sopenharmony_ci	return rc;
221662306a36Sopenharmony_ci}
221762306a36Sopenharmony_ci
221862306a36Sopenharmony_cistatic int cc_rfc4543_gcm_encrypt(struct aead_request *req)
221962306a36Sopenharmony_ci{
222062306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
222162306a36Sopenharmony_ci	int rc;
222262306a36Sopenharmony_ci
222362306a36Sopenharmony_ci	rc = crypto_ipsec_check_assoclen(req->assoclen);
222462306a36Sopenharmony_ci	if (rc)
222562306a36Sopenharmony_ci		goto out;
222662306a36Sopenharmony_ci
222762306a36Sopenharmony_ci	memset(areq_ctx, 0, sizeof(*areq_ctx));
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	//plaintext is not encryped with rfc4543
223062306a36Sopenharmony_ci	areq_ctx->plaintext_authenticate_only = true;
223162306a36Sopenharmony_ci
223262306a36Sopenharmony_ci	/* No generated IV required */
223362306a36Sopenharmony_ci	areq_ctx->backup_iv = req->iv;
223462306a36Sopenharmony_ci	areq_ctx->assoclen = req->assoclen;
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci	cc_proc_rfc4_gcm(req);
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_ci	rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
223962306a36Sopenharmony_ci	if (rc != -EINPROGRESS && rc != -EBUSY)
224062306a36Sopenharmony_ci		req->iv = areq_ctx->backup_iv;
224162306a36Sopenharmony_ciout:
224262306a36Sopenharmony_ci	return rc;
224362306a36Sopenharmony_ci}
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_cistatic int cc_rfc4106_gcm_decrypt(struct aead_request *req)
224662306a36Sopenharmony_ci{
224762306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
224862306a36Sopenharmony_ci	int rc;
224962306a36Sopenharmony_ci
225062306a36Sopenharmony_ci	rc = crypto_ipsec_check_assoclen(req->assoclen);
225162306a36Sopenharmony_ci	if (rc)
225262306a36Sopenharmony_ci		goto out;
225362306a36Sopenharmony_ci
225462306a36Sopenharmony_ci	memset(areq_ctx, 0, sizeof(*areq_ctx));
225562306a36Sopenharmony_ci
225662306a36Sopenharmony_ci	/* No generated IV required */
225762306a36Sopenharmony_ci	areq_ctx->backup_iv = req->iv;
225862306a36Sopenharmony_ci	areq_ctx->assoclen = req->assoclen - GCM_BLOCK_RFC4_IV_SIZE;
225962306a36Sopenharmony_ci
226062306a36Sopenharmony_ci	cc_proc_rfc4_gcm(req);
226162306a36Sopenharmony_ci
226262306a36Sopenharmony_ci	rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT);
226362306a36Sopenharmony_ci	if (rc != -EINPROGRESS && rc != -EBUSY)
226462306a36Sopenharmony_ci		req->iv = areq_ctx->backup_iv;
226562306a36Sopenharmony_ciout:
226662306a36Sopenharmony_ci	return rc;
226762306a36Sopenharmony_ci}
226862306a36Sopenharmony_ci
226962306a36Sopenharmony_cistatic int cc_rfc4543_gcm_decrypt(struct aead_request *req)
227062306a36Sopenharmony_ci{
227162306a36Sopenharmony_ci	struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req);
227262306a36Sopenharmony_ci	int rc;
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci	rc = crypto_ipsec_check_assoclen(req->assoclen);
227562306a36Sopenharmony_ci	if (rc)
227662306a36Sopenharmony_ci		goto out;
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci	memset(areq_ctx, 0, sizeof(*areq_ctx));
227962306a36Sopenharmony_ci
228062306a36Sopenharmony_ci	//plaintext is not decryped with rfc4543
228162306a36Sopenharmony_ci	areq_ctx->plaintext_authenticate_only = true;
228262306a36Sopenharmony_ci
228362306a36Sopenharmony_ci	/* No generated IV required */
228462306a36Sopenharmony_ci	areq_ctx->backup_iv = req->iv;
228562306a36Sopenharmony_ci	areq_ctx->assoclen = req->assoclen;
228662306a36Sopenharmony_ci
228762306a36Sopenharmony_ci	cc_proc_rfc4_gcm(req);
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci	rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT);
229062306a36Sopenharmony_ci	if (rc != -EINPROGRESS && rc != -EBUSY)
229162306a36Sopenharmony_ci		req->iv = areq_ctx->backup_iv;
229262306a36Sopenharmony_ciout:
229362306a36Sopenharmony_ci	return rc;
229462306a36Sopenharmony_ci}
229562306a36Sopenharmony_ci
229662306a36Sopenharmony_ci/* aead alg */
229762306a36Sopenharmony_cistatic struct cc_alg_template aead_algs[] = {
229862306a36Sopenharmony_ci	{
229962306a36Sopenharmony_ci		.name = "authenc(hmac(sha1),cbc(aes))",
230062306a36Sopenharmony_ci		.driver_name = "authenc-hmac-sha1-cbc-aes-ccree",
230162306a36Sopenharmony_ci		.blocksize = AES_BLOCK_SIZE,
230262306a36Sopenharmony_ci		.template_aead = {
230362306a36Sopenharmony_ci			.setkey = cc_aead_setkey,
230462306a36Sopenharmony_ci			.setauthsize = cc_aead_setauthsize,
230562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
230662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
230762306a36Sopenharmony_ci			.init = cc_aead_init,
230862306a36Sopenharmony_ci			.exit = cc_aead_exit,
230962306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
231062306a36Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
231162306a36Sopenharmony_ci		},
231262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CBC,
231362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
231462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_SHA1,
231562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
231662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
231762306a36Sopenharmony_ci	},
231862306a36Sopenharmony_ci	{
231962306a36Sopenharmony_ci		.name = "authenc(hmac(sha1),cbc(des3_ede))",
232062306a36Sopenharmony_ci		.driver_name = "authenc-hmac-sha1-cbc-des3-ccree",
232162306a36Sopenharmony_ci		.blocksize = DES3_EDE_BLOCK_SIZE,
232262306a36Sopenharmony_ci		.template_aead = {
232362306a36Sopenharmony_ci			.setkey = cc_des3_aead_setkey,
232462306a36Sopenharmony_ci			.setauthsize = cc_aead_setauthsize,
232562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
232662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
232762306a36Sopenharmony_ci			.init = cc_aead_init,
232862306a36Sopenharmony_ci			.exit = cc_aead_exit,
232962306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
233062306a36Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
233162306a36Sopenharmony_ci		},
233262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CBC,
233362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_DES,
233462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_SHA1,
233562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
233662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
233762306a36Sopenharmony_ci	},
233862306a36Sopenharmony_ci	{
233962306a36Sopenharmony_ci		.name = "authenc(hmac(sha256),cbc(aes))",
234062306a36Sopenharmony_ci		.driver_name = "authenc-hmac-sha256-cbc-aes-ccree",
234162306a36Sopenharmony_ci		.blocksize = AES_BLOCK_SIZE,
234262306a36Sopenharmony_ci		.template_aead = {
234362306a36Sopenharmony_ci			.setkey = cc_aead_setkey,
234462306a36Sopenharmony_ci			.setauthsize = cc_aead_setauthsize,
234562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
234662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
234762306a36Sopenharmony_ci			.init = cc_aead_init,
234862306a36Sopenharmony_ci			.exit = cc_aead_exit,
234962306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
235062306a36Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
235162306a36Sopenharmony_ci		},
235262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CBC,
235362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
235462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_SHA256,
235562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
235662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
235762306a36Sopenharmony_ci	},
235862306a36Sopenharmony_ci	{
235962306a36Sopenharmony_ci		.name = "authenc(hmac(sha256),cbc(des3_ede))",
236062306a36Sopenharmony_ci		.driver_name = "authenc-hmac-sha256-cbc-des3-ccree",
236162306a36Sopenharmony_ci		.blocksize = DES3_EDE_BLOCK_SIZE,
236262306a36Sopenharmony_ci		.template_aead = {
236362306a36Sopenharmony_ci			.setkey = cc_des3_aead_setkey,
236462306a36Sopenharmony_ci			.setauthsize = cc_aead_setauthsize,
236562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
236662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
236762306a36Sopenharmony_ci			.init = cc_aead_init,
236862306a36Sopenharmony_ci			.exit = cc_aead_exit,
236962306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
237062306a36Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
237162306a36Sopenharmony_ci		},
237262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CBC,
237362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_DES,
237462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_SHA256,
237562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
237662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
237762306a36Sopenharmony_ci	},
237862306a36Sopenharmony_ci	{
237962306a36Sopenharmony_ci		.name = "authenc(xcbc(aes),cbc(aes))",
238062306a36Sopenharmony_ci		.driver_name = "authenc-xcbc-aes-cbc-aes-ccree",
238162306a36Sopenharmony_ci		.blocksize = AES_BLOCK_SIZE,
238262306a36Sopenharmony_ci		.template_aead = {
238362306a36Sopenharmony_ci			.setkey = cc_aead_setkey,
238462306a36Sopenharmony_ci			.setauthsize = cc_aead_setauthsize,
238562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
238662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
238762306a36Sopenharmony_ci			.init = cc_aead_init,
238862306a36Sopenharmony_ci			.exit = cc_aead_exit,
238962306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
239062306a36Sopenharmony_ci			.maxauthsize = AES_BLOCK_SIZE,
239162306a36Sopenharmony_ci		},
239262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CBC,
239362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
239462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_XCBC_MAC,
239562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
239662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
239762306a36Sopenharmony_ci	},
239862306a36Sopenharmony_ci	{
239962306a36Sopenharmony_ci		.name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
240062306a36Sopenharmony_ci		.driver_name = "authenc-hmac-sha1-rfc3686-ctr-aes-ccree",
240162306a36Sopenharmony_ci		.blocksize = 1,
240262306a36Sopenharmony_ci		.template_aead = {
240362306a36Sopenharmony_ci			.setkey = cc_aead_setkey,
240462306a36Sopenharmony_ci			.setauthsize = cc_aead_setauthsize,
240562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
240662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
240762306a36Sopenharmony_ci			.init = cc_aead_init,
240862306a36Sopenharmony_ci			.exit = cc_aead_exit,
240962306a36Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
241062306a36Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
241162306a36Sopenharmony_ci		},
241262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CTR,
241362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
241462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_SHA1,
241562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
241662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
241762306a36Sopenharmony_ci	},
241862306a36Sopenharmony_ci	{
241962306a36Sopenharmony_ci		.name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
242062306a36Sopenharmony_ci		.driver_name = "authenc-hmac-sha256-rfc3686-ctr-aes-ccree",
242162306a36Sopenharmony_ci		.blocksize = 1,
242262306a36Sopenharmony_ci		.template_aead = {
242362306a36Sopenharmony_ci			.setkey = cc_aead_setkey,
242462306a36Sopenharmony_ci			.setauthsize = cc_aead_setauthsize,
242562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
242662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
242762306a36Sopenharmony_ci			.init = cc_aead_init,
242862306a36Sopenharmony_ci			.exit = cc_aead_exit,
242962306a36Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
243062306a36Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
243162306a36Sopenharmony_ci		},
243262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CTR,
243362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
243462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_SHA256,
243562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
243662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
243762306a36Sopenharmony_ci	},
243862306a36Sopenharmony_ci	{
243962306a36Sopenharmony_ci		.name = "authenc(xcbc(aes),rfc3686(ctr(aes)))",
244062306a36Sopenharmony_ci		.driver_name = "authenc-xcbc-aes-rfc3686-ctr-aes-ccree",
244162306a36Sopenharmony_ci		.blocksize = 1,
244262306a36Sopenharmony_ci		.template_aead = {
244362306a36Sopenharmony_ci			.setkey = cc_aead_setkey,
244462306a36Sopenharmony_ci			.setauthsize = cc_aead_setauthsize,
244562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
244662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
244762306a36Sopenharmony_ci			.init = cc_aead_init,
244862306a36Sopenharmony_ci			.exit = cc_aead_exit,
244962306a36Sopenharmony_ci			.ivsize = CTR_RFC3686_IV_SIZE,
245062306a36Sopenharmony_ci			.maxauthsize = AES_BLOCK_SIZE,
245162306a36Sopenharmony_ci		},
245262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CTR,
245362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
245462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_XCBC_MAC,
245562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
245662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
245762306a36Sopenharmony_ci	},
245862306a36Sopenharmony_ci	{
245962306a36Sopenharmony_ci		.name = "ccm(aes)",
246062306a36Sopenharmony_ci		.driver_name = "ccm-aes-ccree",
246162306a36Sopenharmony_ci		.blocksize = 1,
246262306a36Sopenharmony_ci		.template_aead = {
246362306a36Sopenharmony_ci			.setkey = cc_aead_setkey,
246462306a36Sopenharmony_ci			.setauthsize = cc_ccm_setauthsize,
246562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
246662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
246762306a36Sopenharmony_ci			.init = cc_aead_init,
246862306a36Sopenharmony_ci			.exit = cc_aead_exit,
246962306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
247062306a36Sopenharmony_ci			.maxauthsize = AES_BLOCK_SIZE,
247162306a36Sopenharmony_ci		},
247262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CCM,
247362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
247462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_NULL,
247562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
247662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
247762306a36Sopenharmony_ci	},
247862306a36Sopenharmony_ci	{
247962306a36Sopenharmony_ci		.name = "rfc4309(ccm(aes))",
248062306a36Sopenharmony_ci		.driver_name = "rfc4309-ccm-aes-ccree",
248162306a36Sopenharmony_ci		.blocksize = 1,
248262306a36Sopenharmony_ci		.template_aead = {
248362306a36Sopenharmony_ci			.setkey = cc_rfc4309_ccm_setkey,
248462306a36Sopenharmony_ci			.setauthsize = cc_rfc4309_ccm_setauthsize,
248562306a36Sopenharmony_ci			.encrypt = cc_rfc4309_ccm_encrypt,
248662306a36Sopenharmony_ci			.decrypt = cc_rfc4309_ccm_decrypt,
248762306a36Sopenharmony_ci			.init = cc_aead_init,
248862306a36Sopenharmony_ci			.exit = cc_aead_exit,
248962306a36Sopenharmony_ci			.ivsize = CCM_BLOCK_IV_SIZE,
249062306a36Sopenharmony_ci			.maxauthsize = AES_BLOCK_SIZE,
249162306a36Sopenharmony_ci		},
249262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_CCM,
249362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
249462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_NULL,
249562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
249662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
249762306a36Sopenharmony_ci	},
249862306a36Sopenharmony_ci	{
249962306a36Sopenharmony_ci		.name = "gcm(aes)",
250062306a36Sopenharmony_ci		.driver_name = "gcm-aes-ccree",
250162306a36Sopenharmony_ci		.blocksize = 1,
250262306a36Sopenharmony_ci		.template_aead = {
250362306a36Sopenharmony_ci			.setkey = cc_aead_setkey,
250462306a36Sopenharmony_ci			.setauthsize = cc_gcm_setauthsize,
250562306a36Sopenharmony_ci			.encrypt = cc_aead_encrypt,
250662306a36Sopenharmony_ci			.decrypt = cc_aead_decrypt,
250762306a36Sopenharmony_ci			.init = cc_aead_init,
250862306a36Sopenharmony_ci			.exit = cc_aead_exit,
250962306a36Sopenharmony_ci			.ivsize = 12,
251062306a36Sopenharmony_ci			.maxauthsize = AES_BLOCK_SIZE,
251162306a36Sopenharmony_ci		},
251262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_GCTR,
251362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
251462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_NULL,
251562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
251662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
251762306a36Sopenharmony_ci	},
251862306a36Sopenharmony_ci	{
251962306a36Sopenharmony_ci		.name = "rfc4106(gcm(aes))",
252062306a36Sopenharmony_ci		.driver_name = "rfc4106-gcm-aes-ccree",
252162306a36Sopenharmony_ci		.blocksize = 1,
252262306a36Sopenharmony_ci		.template_aead = {
252362306a36Sopenharmony_ci			.setkey = cc_rfc4106_gcm_setkey,
252462306a36Sopenharmony_ci			.setauthsize = cc_rfc4106_gcm_setauthsize,
252562306a36Sopenharmony_ci			.encrypt = cc_rfc4106_gcm_encrypt,
252662306a36Sopenharmony_ci			.decrypt = cc_rfc4106_gcm_decrypt,
252762306a36Sopenharmony_ci			.init = cc_aead_init,
252862306a36Sopenharmony_ci			.exit = cc_aead_exit,
252962306a36Sopenharmony_ci			.ivsize = GCM_BLOCK_RFC4_IV_SIZE,
253062306a36Sopenharmony_ci			.maxauthsize = AES_BLOCK_SIZE,
253162306a36Sopenharmony_ci		},
253262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_GCTR,
253362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
253462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_NULL,
253562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
253662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
253762306a36Sopenharmony_ci	},
253862306a36Sopenharmony_ci	{
253962306a36Sopenharmony_ci		.name = "rfc4543(gcm(aes))",
254062306a36Sopenharmony_ci		.driver_name = "rfc4543-gcm-aes-ccree",
254162306a36Sopenharmony_ci		.blocksize = 1,
254262306a36Sopenharmony_ci		.template_aead = {
254362306a36Sopenharmony_ci			.setkey = cc_rfc4543_gcm_setkey,
254462306a36Sopenharmony_ci			.setauthsize = cc_rfc4543_gcm_setauthsize,
254562306a36Sopenharmony_ci			.encrypt = cc_rfc4543_gcm_encrypt,
254662306a36Sopenharmony_ci			.decrypt = cc_rfc4543_gcm_decrypt,
254762306a36Sopenharmony_ci			.init = cc_aead_init,
254862306a36Sopenharmony_ci			.exit = cc_aead_exit,
254962306a36Sopenharmony_ci			.ivsize = GCM_BLOCK_RFC4_IV_SIZE,
255062306a36Sopenharmony_ci			.maxauthsize = AES_BLOCK_SIZE,
255162306a36Sopenharmony_ci		},
255262306a36Sopenharmony_ci		.cipher_mode = DRV_CIPHER_GCTR,
255362306a36Sopenharmony_ci		.flow_mode = S_DIN_to_AES,
255462306a36Sopenharmony_ci		.auth_mode = DRV_HASH_NULL,
255562306a36Sopenharmony_ci		.min_hw_rev = CC_HW_REV_630,
255662306a36Sopenharmony_ci		.std_body = CC_STD_NIST,
255762306a36Sopenharmony_ci	},
255862306a36Sopenharmony_ci};
255962306a36Sopenharmony_ci
256062306a36Sopenharmony_cistatic struct cc_crypto_alg *cc_create_aead_alg(struct cc_alg_template *tmpl,
256162306a36Sopenharmony_ci						struct device *dev)
256262306a36Sopenharmony_ci{
256362306a36Sopenharmony_ci	struct cc_crypto_alg *t_alg;
256462306a36Sopenharmony_ci	struct aead_alg *alg;
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_ci	t_alg = devm_kzalloc(dev, sizeof(*t_alg), GFP_KERNEL);
256762306a36Sopenharmony_ci	if (!t_alg)
256862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
256962306a36Sopenharmony_ci
257062306a36Sopenharmony_ci	alg = &tmpl->template_aead;
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci	snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", tmpl->name);
257362306a36Sopenharmony_ci	snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
257462306a36Sopenharmony_ci		 tmpl->driver_name);
257562306a36Sopenharmony_ci	alg->base.cra_module = THIS_MODULE;
257662306a36Sopenharmony_ci	alg->base.cra_priority = CC_CRA_PRIO;
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci	alg->base.cra_ctxsize = sizeof(struct cc_aead_ctx);
257962306a36Sopenharmony_ci	alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY;
258062306a36Sopenharmony_ci	alg->base.cra_blocksize = tmpl->blocksize;
258162306a36Sopenharmony_ci	alg->init = cc_aead_init;
258262306a36Sopenharmony_ci	alg->exit = cc_aead_exit;
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_ci	t_alg->aead_alg = *alg;
258562306a36Sopenharmony_ci
258662306a36Sopenharmony_ci	t_alg->cipher_mode = tmpl->cipher_mode;
258762306a36Sopenharmony_ci	t_alg->flow_mode = tmpl->flow_mode;
258862306a36Sopenharmony_ci	t_alg->auth_mode = tmpl->auth_mode;
258962306a36Sopenharmony_ci
259062306a36Sopenharmony_ci	return t_alg;
259162306a36Sopenharmony_ci}
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_ciint cc_aead_free(struct cc_drvdata *drvdata)
259462306a36Sopenharmony_ci{
259562306a36Sopenharmony_ci	struct cc_crypto_alg *t_alg, *n;
259662306a36Sopenharmony_ci	struct cc_aead_handle *aead_handle = drvdata->aead_handle;
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci	/* Remove registered algs */
259962306a36Sopenharmony_ci	list_for_each_entry_safe(t_alg, n, &aead_handle->aead_list, entry) {
260062306a36Sopenharmony_ci		crypto_unregister_aead(&t_alg->aead_alg);
260162306a36Sopenharmony_ci		list_del(&t_alg->entry);
260262306a36Sopenharmony_ci	}
260362306a36Sopenharmony_ci
260462306a36Sopenharmony_ci	return 0;
260562306a36Sopenharmony_ci}
260662306a36Sopenharmony_ci
260762306a36Sopenharmony_ciint cc_aead_alloc(struct cc_drvdata *drvdata)
260862306a36Sopenharmony_ci{
260962306a36Sopenharmony_ci	struct cc_aead_handle *aead_handle;
261062306a36Sopenharmony_ci	struct cc_crypto_alg *t_alg;
261162306a36Sopenharmony_ci	int rc = -ENOMEM;
261262306a36Sopenharmony_ci	int alg;
261362306a36Sopenharmony_ci	struct device *dev = drvdata_to_dev(drvdata);
261462306a36Sopenharmony_ci
261562306a36Sopenharmony_ci	aead_handle = devm_kmalloc(dev, sizeof(*aead_handle), GFP_KERNEL);
261662306a36Sopenharmony_ci	if (!aead_handle) {
261762306a36Sopenharmony_ci		rc = -ENOMEM;
261862306a36Sopenharmony_ci		goto fail0;
261962306a36Sopenharmony_ci	}
262062306a36Sopenharmony_ci
262162306a36Sopenharmony_ci	INIT_LIST_HEAD(&aead_handle->aead_list);
262262306a36Sopenharmony_ci	drvdata->aead_handle = aead_handle;
262362306a36Sopenharmony_ci
262462306a36Sopenharmony_ci	aead_handle->sram_workspace_addr = cc_sram_alloc(drvdata,
262562306a36Sopenharmony_ci							 MAX_HMAC_DIGEST_SIZE);
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci	if (aead_handle->sram_workspace_addr == NULL_SRAM_ADDR) {
262862306a36Sopenharmony_ci		rc = -ENOMEM;
262962306a36Sopenharmony_ci		goto fail1;
263062306a36Sopenharmony_ci	}
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	/* Linux crypto */
263362306a36Sopenharmony_ci	for (alg = 0; alg < ARRAY_SIZE(aead_algs); alg++) {
263462306a36Sopenharmony_ci		if ((aead_algs[alg].min_hw_rev > drvdata->hw_rev) ||
263562306a36Sopenharmony_ci		    !(drvdata->std_bodies & aead_algs[alg].std_body))
263662306a36Sopenharmony_ci			continue;
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci		t_alg = cc_create_aead_alg(&aead_algs[alg], dev);
263962306a36Sopenharmony_ci		if (IS_ERR(t_alg)) {
264062306a36Sopenharmony_ci			rc = PTR_ERR(t_alg);
264162306a36Sopenharmony_ci			dev_err(dev, "%s alg allocation failed\n",
264262306a36Sopenharmony_ci				aead_algs[alg].driver_name);
264362306a36Sopenharmony_ci			goto fail1;
264462306a36Sopenharmony_ci		}
264562306a36Sopenharmony_ci		t_alg->drvdata = drvdata;
264662306a36Sopenharmony_ci		rc = crypto_register_aead(&t_alg->aead_alg);
264762306a36Sopenharmony_ci		if (rc) {
264862306a36Sopenharmony_ci			dev_err(dev, "%s alg registration failed\n",
264962306a36Sopenharmony_ci				t_alg->aead_alg.base.cra_driver_name);
265062306a36Sopenharmony_ci			goto fail1;
265162306a36Sopenharmony_ci		}
265262306a36Sopenharmony_ci
265362306a36Sopenharmony_ci		list_add_tail(&t_alg->entry, &aead_handle->aead_list);
265462306a36Sopenharmony_ci		dev_dbg(dev, "Registered %s\n",
265562306a36Sopenharmony_ci			t_alg->aead_alg.base.cra_driver_name);
265662306a36Sopenharmony_ci	}
265762306a36Sopenharmony_ci
265862306a36Sopenharmony_ci	return 0;
265962306a36Sopenharmony_ci
266062306a36Sopenharmony_cifail1:
266162306a36Sopenharmony_ci	cc_aead_free(drvdata);
266262306a36Sopenharmony_cifail0:
266362306a36Sopenharmony_ci	return rc;
266462306a36Sopenharmony_ci}
2665