162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2019 HiSilicon Limited. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <crypto/aes.h>
562306a36Sopenharmony_ci#include <crypto/aead.h>
662306a36Sopenharmony_ci#include <crypto/algapi.h>
762306a36Sopenharmony_ci#include <crypto/authenc.h>
862306a36Sopenharmony_ci#include <crypto/des.h>
962306a36Sopenharmony_ci#include <crypto/hash.h>
1062306a36Sopenharmony_ci#include <crypto/internal/aead.h>
1162306a36Sopenharmony_ci#include <crypto/internal/des.h>
1262306a36Sopenharmony_ci#include <crypto/sha1.h>
1362306a36Sopenharmony_ci#include <crypto/sha2.h>
1462306a36Sopenharmony_ci#include <crypto/skcipher.h>
1562306a36Sopenharmony_ci#include <crypto/xts.h>
1662306a36Sopenharmony_ci#include <linux/crypto.h>
1762306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1862306a36Sopenharmony_ci#include <linux/idr.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include "sec.h"
2162306a36Sopenharmony_ci#include "sec_crypto.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define SEC_PRIORITY		4001
2462306a36Sopenharmony_ci#define SEC_XTS_MIN_KEY_SIZE	(2 * AES_MIN_KEY_SIZE)
2562306a36Sopenharmony_ci#define SEC_XTS_MID_KEY_SIZE	(3 * AES_MIN_KEY_SIZE)
2662306a36Sopenharmony_ci#define SEC_XTS_MAX_KEY_SIZE	(2 * AES_MAX_KEY_SIZE)
2762306a36Sopenharmony_ci#define SEC_DES3_2KEY_SIZE	(2 * DES_KEY_SIZE)
2862306a36Sopenharmony_ci#define SEC_DES3_3KEY_SIZE	(3 * DES_KEY_SIZE)
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* SEC sqe(bd) bit operational relative MACRO */
3162306a36Sopenharmony_ci#define SEC_DE_OFFSET		1
3262306a36Sopenharmony_ci#define SEC_CIPHER_OFFSET	4
3362306a36Sopenharmony_ci#define SEC_SCENE_OFFSET	3
3462306a36Sopenharmony_ci#define SEC_DST_SGL_OFFSET	2
3562306a36Sopenharmony_ci#define SEC_SRC_SGL_OFFSET	7
3662306a36Sopenharmony_ci#define SEC_CKEY_OFFSET		9
3762306a36Sopenharmony_ci#define SEC_CMODE_OFFSET	12
3862306a36Sopenharmony_ci#define SEC_AKEY_OFFSET         5
3962306a36Sopenharmony_ci#define SEC_AEAD_ALG_OFFSET     11
4062306a36Sopenharmony_ci#define SEC_AUTH_OFFSET		6
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define SEC_DE_OFFSET_V3		9
4362306a36Sopenharmony_ci#define SEC_SCENE_OFFSET_V3	5
4462306a36Sopenharmony_ci#define SEC_CKEY_OFFSET_V3	13
4562306a36Sopenharmony_ci#define SEC_CTR_CNT_OFFSET	25
4662306a36Sopenharmony_ci#define SEC_CTR_CNT_ROLLOVER	2
4762306a36Sopenharmony_ci#define SEC_SRC_SGL_OFFSET_V3	11
4862306a36Sopenharmony_ci#define SEC_DST_SGL_OFFSET_V3	14
4962306a36Sopenharmony_ci#define SEC_CALG_OFFSET_V3	4
5062306a36Sopenharmony_ci#define SEC_AKEY_OFFSET_V3	9
5162306a36Sopenharmony_ci#define SEC_MAC_OFFSET_V3	4
5262306a36Sopenharmony_ci#define SEC_AUTH_ALG_OFFSET_V3	15
5362306a36Sopenharmony_ci#define SEC_CIPHER_AUTH_V3	0xbf
5462306a36Sopenharmony_ci#define SEC_AUTH_CIPHER_V3	0x40
5562306a36Sopenharmony_ci#define SEC_FLAG_OFFSET		7
5662306a36Sopenharmony_ci#define SEC_FLAG_MASK		0x0780
5762306a36Sopenharmony_ci#define SEC_TYPE_MASK		0x0F
5862306a36Sopenharmony_ci#define SEC_DONE_MASK		0x0001
5962306a36Sopenharmony_ci#define SEC_ICV_MASK		0x000E
6062306a36Sopenharmony_ci#define SEC_SQE_LEN_RATE_MASK	0x3
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#define SEC_TOTAL_IV_SZ(depth)	(SEC_IV_SIZE * (depth))
6362306a36Sopenharmony_ci#define SEC_SGL_SGE_NR		128
6462306a36Sopenharmony_ci#define SEC_CIPHER_AUTH		0xfe
6562306a36Sopenharmony_ci#define SEC_AUTH_CIPHER		0x1
6662306a36Sopenharmony_ci#define SEC_MAX_MAC_LEN		64
6762306a36Sopenharmony_ci#define SEC_MAX_AAD_LEN		65535
6862306a36Sopenharmony_ci#define SEC_MAX_CCM_AAD_LEN	65279
6962306a36Sopenharmony_ci#define SEC_TOTAL_MAC_SZ(depth) (SEC_MAX_MAC_LEN * (depth))
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci#define SEC_PBUF_SZ			512
7262306a36Sopenharmony_ci#define SEC_PBUF_IV_OFFSET		SEC_PBUF_SZ
7362306a36Sopenharmony_ci#define SEC_PBUF_MAC_OFFSET		(SEC_PBUF_SZ + SEC_IV_SIZE)
7462306a36Sopenharmony_ci#define SEC_PBUF_PKG		(SEC_PBUF_SZ + SEC_IV_SIZE +	\
7562306a36Sopenharmony_ci			SEC_MAX_MAC_LEN * 2)
7662306a36Sopenharmony_ci#define SEC_PBUF_NUM		(PAGE_SIZE / SEC_PBUF_PKG)
7762306a36Sopenharmony_ci#define SEC_PBUF_PAGE_NUM(depth)	((depth) / SEC_PBUF_NUM)
7862306a36Sopenharmony_ci#define SEC_PBUF_LEFT_SZ(depth)		(SEC_PBUF_PKG * ((depth) -	\
7962306a36Sopenharmony_ci				SEC_PBUF_PAGE_NUM(depth) * SEC_PBUF_NUM))
8062306a36Sopenharmony_ci#define SEC_TOTAL_PBUF_SZ(depth)	(PAGE_SIZE * SEC_PBUF_PAGE_NUM(depth) +	\
8162306a36Sopenharmony_ci				SEC_PBUF_LEFT_SZ(depth))
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#define SEC_SQE_LEN_RATE	4
8462306a36Sopenharmony_ci#define SEC_SQE_CFLAG		2
8562306a36Sopenharmony_ci#define SEC_SQE_AEAD_FLAG	3
8662306a36Sopenharmony_ci#define SEC_SQE_DONE		0x1
8762306a36Sopenharmony_ci#define SEC_ICV_ERR		0x2
8862306a36Sopenharmony_ci#define MIN_MAC_LEN		4
8962306a36Sopenharmony_ci#define MAC_LEN_MASK		0x1U
9062306a36Sopenharmony_ci#define MAX_INPUT_DATA_LEN	0xFFFE00
9162306a36Sopenharmony_ci#define BITS_MASK		0xFF
9262306a36Sopenharmony_ci#define BYTE_BITS		0x8
9362306a36Sopenharmony_ci#define SEC_XTS_NAME_SZ		0x3
9462306a36Sopenharmony_ci#define IV_CM_CAL_NUM		2
9562306a36Sopenharmony_ci#define IV_CL_MASK		0x7
9662306a36Sopenharmony_ci#define IV_CL_MIN		2
9762306a36Sopenharmony_ci#define IV_CL_MID		4
9862306a36Sopenharmony_ci#define IV_CL_MAX		8
9962306a36Sopenharmony_ci#define IV_FLAGS_OFFSET	0x6
10062306a36Sopenharmony_ci#define IV_CM_OFFSET		0x3
10162306a36Sopenharmony_ci#define IV_LAST_BYTE1		1
10262306a36Sopenharmony_ci#define IV_LAST_BYTE2		2
10362306a36Sopenharmony_ci#define IV_LAST_BYTE_MASK	0xFF
10462306a36Sopenharmony_ci#define IV_CTR_INIT		0x1
10562306a36Sopenharmony_ci#define IV_BYTE_OFFSET		0x8
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistruct sec_skcipher {
10862306a36Sopenharmony_ci	u64 alg_msk;
10962306a36Sopenharmony_ci	struct skcipher_alg alg;
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistruct sec_aead {
11362306a36Sopenharmony_ci	u64 alg_msk;
11462306a36Sopenharmony_ci	struct aead_alg alg;
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/* Get an en/de-cipher queue cyclically to balance load over queues of TFM */
11862306a36Sopenharmony_cistatic inline int sec_alloc_queue_id(struct sec_ctx *ctx, struct sec_req *req)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	if (req->c_req.encrypt)
12162306a36Sopenharmony_ci		return (u32)atomic_inc_return(&ctx->enc_qcyclic) %
12262306a36Sopenharmony_ci				 ctx->hlf_q_num;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num +
12562306a36Sopenharmony_ci				 ctx->hlf_q_num;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic inline void sec_free_queue_id(struct sec_ctx *ctx, struct sec_req *req)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	if (req->c_req.encrypt)
13162306a36Sopenharmony_ci		atomic_dec(&ctx->enc_qcyclic);
13262306a36Sopenharmony_ci	else
13362306a36Sopenharmony_ci		atomic_dec(&ctx->dec_qcyclic);
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	int req_id;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	spin_lock_bh(&qp_ctx->req_lock);
14162306a36Sopenharmony_ci	req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL, 0, qp_ctx->qp->sq_depth, GFP_ATOMIC);
14262306a36Sopenharmony_ci	spin_unlock_bh(&qp_ctx->req_lock);
14362306a36Sopenharmony_ci	if (unlikely(req_id < 0)) {
14462306a36Sopenharmony_ci		dev_err(req->ctx->dev, "alloc req id fail!\n");
14562306a36Sopenharmony_ci		return req_id;
14662306a36Sopenharmony_ci	}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	req->qp_ctx = qp_ctx;
14962306a36Sopenharmony_ci	qp_ctx->req_list[req_id] = req;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	return req_id;
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic void sec_free_req_id(struct sec_req *req)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
15762306a36Sopenharmony_ci	int req_id = req->req_id;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	if (unlikely(req_id < 0 || req_id >= qp_ctx->qp->sq_depth)) {
16062306a36Sopenharmony_ci		dev_err(req->ctx->dev, "free request id invalid!\n");
16162306a36Sopenharmony_ci		return;
16262306a36Sopenharmony_ci	}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	qp_ctx->req_list[req_id] = NULL;
16562306a36Sopenharmony_ci	req->qp_ctx = NULL;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	spin_lock_bh(&qp_ctx->req_lock);
16862306a36Sopenharmony_ci	idr_remove(&qp_ctx->req_idr, req_id);
16962306a36Sopenharmony_ci	spin_unlock_bh(&qp_ctx->req_lock);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic u8 pre_parse_finished_bd(struct bd_status *status, void *resp)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	struct sec_sqe *bd = resp;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	status->done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK;
17762306a36Sopenharmony_ci	status->icv = (le16_to_cpu(bd->type2.done_flag) & SEC_ICV_MASK) >> 1;
17862306a36Sopenharmony_ci	status->flag = (le16_to_cpu(bd->type2.done_flag) &
17962306a36Sopenharmony_ci					SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
18062306a36Sopenharmony_ci	status->tag = le16_to_cpu(bd->type2.tag);
18162306a36Sopenharmony_ci	status->err_type = bd->type2.error_type;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	return bd->type_cipher_auth & SEC_TYPE_MASK;
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic u8 pre_parse_finished_bd3(struct bd_status *status, void *resp)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	struct sec_sqe3 *bd3 = resp;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	status->done = le16_to_cpu(bd3->done_flag) & SEC_DONE_MASK;
19162306a36Sopenharmony_ci	status->icv = (le16_to_cpu(bd3->done_flag) & SEC_ICV_MASK) >> 1;
19262306a36Sopenharmony_ci	status->flag = (le16_to_cpu(bd3->done_flag) &
19362306a36Sopenharmony_ci					SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
19462306a36Sopenharmony_ci	status->tag = le64_to_cpu(bd3->tag);
19562306a36Sopenharmony_ci	status->err_type = bd3->error_type;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	return le32_to_cpu(bd3->bd_param) & SEC_TYPE_MASK;
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistatic int sec_cb_status_check(struct sec_req *req,
20162306a36Sopenharmony_ci			       struct bd_status *status)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	struct sec_ctx *ctx = req->ctx;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	if (unlikely(req->err_type || status->done != SEC_SQE_DONE)) {
20662306a36Sopenharmony_ci		dev_err_ratelimited(ctx->dev, "err_type[%d], done[%u]\n",
20762306a36Sopenharmony_ci				    req->err_type, status->done);
20862306a36Sopenharmony_ci		return -EIO;
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	if (unlikely(ctx->alg_type == SEC_SKCIPHER)) {
21262306a36Sopenharmony_ci		if (unlikely(status->flag != SEC_SQE_CFLAG)) {
21362306a36Sopenharmony_ci			dev_err_ratelimited(ctx->dev, "flag[%u]\n",
21462306a36Sopenharmony_ci					    status->flag);
21562306a36Sopenharmony_ci			return -EIO;
21662306a36Sopenharmony_ci		}
21762306a36Sopenharmony_ci	} else if (unlikely(ctx->alg_type == SEC_AEAD)) {
21862306a36Sopenharmony_ci		if (unlikely(status->flag != SEC_SQE_AEAD_FLAG ||
21962306a36Sopenharmony_ci			     status->icv == SEC_ICV_ERR)) {
22062306a36Sopenharmony_ci			dev_err_ratelimited(ctx->dev,
22162306a36Sopenharmony_ci					    "flag[%u], icv[%u]\n",
22262306a36Sopenharmony_ci					    status->flag, status->icv);
22362306a36Sopenharmony_ci			return -EBADMSG;
22462306a36Sopenharmony_ci		}
22562306a36Sopenharmony_ci	}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	return 0;
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic void sec_req_cb(struct hisi_qp *qp, void *resp)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = qp->qp_ctx;
23362306a36Sopenharmony_ci	struct sec_dfx *dfx = &qp_ctx->ctx->sec->debug.dfx;
23462306a36Sopenharmony_ci	u8 type_supported = qp_ctx->ctx->type_supported;
23562306a36Sopenharmony_ci	struct bd_status status;
23662306a36Sopenharmony_ci	struct sec_ctx *ctx;
23762306a36Sopenharmony_ci	struct sec_req *req;
23862306a36Sopenharmony_ci	int err;
23962306a36Sopenharmony_ci	u8 type;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	if (type_supported == SEC_BD_TYPE2) {
24262306a36Sopenharmony_ci		type = pre_parse_finished_bd(&status, resp);
24362306a36Sopenharmony_ci		req = qp_ctx->req_list[status.tag];
24462306a36Sopenharmony_ci	} else {
24562306a36Sopenharmony_ci		type = pre_parse_finished_bd3(&status, resp);
24662306a36Sopenharmony_ci		req = (void *)(uintptr_t)status.tag;
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	if (unlikely(type != type_supported)) {
25062306a36Sopenharmony_ci		atomic64_inc(&dfx->err_bd_cnt);
25162306a36Sopenharmony_ci		pr_err("err bd type [%u]\n", type);
25262306a36Sopenharmony_ci		return;
25362306a36Sopenharmony_ci	}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	if (unlikely(!req)) {
25662306a36Sopenharmony_ci		atomic64_inc(&dfx->invalid_req_cnt);
25762306a36Sopenharmony_ci		atomic_inc(&qp->qp_status.used);
25862306a36Sopenharmony_ci		return;
25962306a36Sopenharmony_ci	}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	req->err_type = status.err_type;
26262306a36Sopenharmony_ci	ctx = req->ctx;
26362306a36Sopenharmony_ci	err = sec_cb_status_check(req, &status);
26462306a36Sopenharmony_ci	if (err)
26562306a36Sopenharmony_ci		atomic64_inc(&dfx->done_flag_cnt);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	atomic64_inc(&dfx->recv_cnt);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	ctx->req_op->buf_unmap(ctx, req);
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	ctx->req_op->callback(ctx, req, err);
27262306a36Sopenharmony_ci}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
27762306a36Sopenharmony_ci	int ret;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	if (ctx->fake_req_limit <=
28062306a36Sopenharmony_ci	    atomic_read(&qp_ctx->qp->qp_status.used) &&
28162306a36Sopenharmony_ci	    !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG))
28262306a36Sopenharmony_ci		return -EBUSY;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	spin_lock_bh(&qp_ctx->req_lock);
28562306a36Sopenharmony_ci	ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
28662306a36Sopenharmony_ci	if (ctx->fake_req_limit <=
28762306a36Sopenharmony_ci	    atomic_read(&qp_ctx->qp->qp_status.used) && !ret) {
28862306a36Sopenharmony_ci		list_add_tail(&req->backlog_head, &qp_ctx->backlog);
28962306a36Sopenharmony_ci		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
29062306a36Sopenharmony_ci		atomic64_inc(&ctx->sec->debug.dfx.send_busy_cnt);
29162306a36Sopenharmony_ci		spin_unlock_bh(&qp_ctx->req_lock);
29262306a36Sopenharmony_ci		return -EBUSY;
29362306a36Sopenharmony_ci	}
29462306a36Sopenharmony_ci	spin_unlock_bh(&qp_ctx->req_lock);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	if (unlikely(ret == -EBUSY))
29762306a36Sopenharmony_ci		return -ENOBUFS;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	if (likely(!ret)) {
30062306a36Sopenharmony_ci		ret = -EINPROGRESS;
30162306a36Sopenharmony_ci		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
30262306a36Sopenharmony_ci	}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	return ret;
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci/* Get DMA memory resources */
30862306a36Sopenharmony_cistatic int sec_alloc_civ_resource(struct device *dev, struct sec_alg_res *res)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	u16 q_depth = res->depth;
31162306a36Sopenharmony_ci	int i;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ(q_depth),
31462306a36Sopenharmony_ci					 &res->c_ivin_dma, GFP_KERNEL);
31562306a36Sopenharmony_ci	if (!res->c_ivin)
31662306a36Sopenharmony_ci		return -ENOMEM;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	for (i = 1; i < q_depth; i++) {
31962306a36Sopenharmony_ci		res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE;
32062306a36Sopenharmony_ci		res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE;
32162306a36Sopenharmony_ci	}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	return 0;
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistatic void sec_free_civ_resource(struct device *dev, struct sec_alg_res *res)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	if (res->c_ivin)
32962306a36Sopenharmony_ci		dma_free_coherent(dev, SEC_TOTAL_IV_SZ(res->depth),
33062306a36Sopenharmony_ci				  res->c_ivin, res->c_ivin_dma);
33162306a36Sopenharmony_ci}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cistatic int sec_alloc_aiv_resource(struct device *dev, struct sec_alg_res *res)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	u16 q_depth = res->depth;
33662306a36Sopenharmony_ci	int i;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	res->a_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ(q_depth),
33962306a36Sopenharmony_ci					 &res->a_ivin_dma, GFP_KERNEL);
34062306a36Sopenharmony_ci	if (!res->a_ivin)
34162306a36Sopenharmony_ci		return -ENOMEM;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	for (i = 1; i < q_depth; i++) {
34462306a36Sopenharmony_ci		res[i].a_ivin_dma = res->a_ivin_dma + i * SEC_IV_SIZE;
34562306a36Sopenharmony_ci		res[i].a_ivin = res->a_ivin + i * SEC_IV_SIZE;
34662306a36Sopenharmony_ci	}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	return 0;
34962306a36Sopenharmony_ci}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_cistatic void sec_free_aiv_resource(struct device *dev, struct sec_alg_res *res)
35262306a36Sopenharmony_ci{
35362306a36Sopenharmony_ci	if (res->a_ivin)
35462306a36Sopenharmony_ci		dma_free_coherent(dev, SEC_TOTAL_IV_SZ(res->depth),
35562306a36Sopenharmony_ci				  res->a_ivin, res->a_ivin_dma);
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cistatic int sec_alloc_mac_resource(struct device *dev, struct sec_alg_res *res)
35962306a36Sopenharmony_ci{
36062306a36Sopenharmony_ci	u16 q_depth = res->depth;
36162306a36Sopenharmony_ci	int i;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	res->out_mac = dma_alloc_coherent(dev, SEC_TOTAL_MAC_SZ(q_depth) << 1,
36462306a36Sopenharmony_ci					  &res->out_mac_dma, GFP_KERNEL);
36562306a36Sopenharmony_ci	if (!res->out_mac)
36662306a36Sopenharmony_ci		return -ENOMEM;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	for (i = 1; i < q_depth; i++) {
36962306a36Sopenharmony_ci		res[i].out_mac_dma = res->out_mac_dma +
37062306a36Sopenharmony_ci				     i * (SEC_MAX_MAC_LEN << 1);
37162306a36Sopenharmony_ci		res[i].out_mac = res->out_mac + i * (SEC_MAX_MAC_LEN << 1);
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	return 0;
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_cistatic void sec_free_mac_resource(struct device *dev, struct sec_alg_res *res)
37862306a36Sopenharmony_ci{
37962306a36Sopenharmony_ci	if (res->out_mac)
38062306a36Sopenharmony_ci		dma_free_coherent(dev, SEC_TOTAL_MAC_SZ(res->depth) << 1,
38162306a36Sopenharmony_ci				  res->out_mac, res->out_mac_dma);
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic void sec_free_pbuf_resource(struct device *dev, struct sec_alg_res *res)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	if (res->pbuf)
38762306a36Sopenharmony_ci		dma_free_coherent(dev, SEC_TOTAL_PBUF_SZ(res->depth),
38862306a36Sopenharmony_ci				  res->pbuf, res->pbuf_dma);
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci/*
39262306a36Sopenharmony_ci * To improve performance, pbuffer is used for
39362306a36Sopenharmony_ci * small packets (< 512Bytes) as IOMMU translation using.
39462306a36Sopenharmony_ci */
39562306a36Sopenharmony_cistatic int sec_alloc_pbuf_resource(struct device *dev, struct sec_alg_res *res)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	u16 q_depth = res->depth;
39862306a36Sopenharmony_ci	int size = SEC_PBUF_PAGE_NUM(q_depth);
39962306a36Sopenharmony_ci	int pbuf_page_offset;
40062306a36Sopenharmony_ci	int i, j, k;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	res->pbuf = dma_alloc_coherent(dev, SEC_TOTAL_PBUF_SZ(q_depth),
40362306a36Sopenharmony_ci				&res->pbuf_dma, GFP_KERNEL);
40462306a36Sopenharmony_ci	if (!res->pbuf)
40562306a36Sopenharmony_ci		return -ENOMEM;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	/*
40862306a36Sopenharmony_ci	 * SEC_PBUF_PKG contains data pbuf, iv and
40962306a36Sopenharmony_ci	 * out_mac : <SEC_PBUF|SEC_IV|SEC_MAC>
41062306a36Sopenharmony_ci	 * Every PAGE contains six SEC_PBUF_PKG
41162306a36Sopenharmony_ci	 * The sec_qp_ctx contains QM_Q_DEPTH numbers of SEC_PBUF_PKG
41262306a36Sopenharmony_ci	 * So we need SEC_PBUF_PAGE_NUM numbers of PAGE
41362306a36Sopenharmony_ci	 * for the SEC_TOTAL_PBUF_SZ
41462306a36Sopenharmony_ci	 */
41562306a36Sopenharmony_ci	for (i = 0; i <= size; i++) {
41662306a36Sopenharmony_ci		pbuf_page_offset = PAGE_SIZE * i;
41762306a36Sopenharmony_ci		for (j = 0; j < SEC_PBUF_NUM; j++) {
41862306a36Sopenharmony_ci			k = i * SEC_PBUF_NUM + j;
41962306a36Sopenharmony_ci			if (k == q_depth)
42062306a36Sopenharmony_ci				break;
42162306a36Sopenharmony_ci			res[k].pbuf = res->pbuf +
42262306a36Sopenharmony_ci				j * SEC_PBUF_PKG + pbuf_page_offset;
42362306a36Sopenharmony_ci			res[k].pbuf_dma = res->pbuf_dma +
42462306a36Sopenharmony_ci				j * SEC_PBUF_PKG + pbuf_page_offset;
42562306a36Sopenharmony_ci		}
42662306a36Sopenharmony_ci	}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	return 0;
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cistatic int sec_alg_resource_alloc(struct sec_ctx *ctx,
43262306a36Sopenharmony_ci				  struct sec_qp_ctx *qp_ctx)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	struct sec_alg_res *res = qp_ctx->res;
43562306a36Sopenharmony_ci	struct device *dev = ctx->dev;
43662306a36Sopenharmony_ci	int ret;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	ret = sec_alloc_civ_resource(dev, res);
43962306a36Sopenharmony_ci	if (ret)
44062306a36Sopenharmony_ci		return ret;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD) {
44362306a36Sopenharmony_ci		ret = sec_alloc_aiv_resource(dev, res);
44462306a36Sopenharmony_ci		if (ret)
44562306a36Sopenharmony_ci			goto alloc_aiv_fail;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci		ret = sec_alloc_mac_resource(dev, res);
44862306a36Sopenharmony_ci		if (ret)
44962306a36Sopenharmony_ci			goto alloc_mac_fail;
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci	if (ctx->pbuf_supported) {
45262306a36Sopenharmony_ci		ret = sec_alloc_pbuf_resource(dev, res);
45362306a36Sopenharmony_ci		if (ret) {
45462306a36Sopenharmony_ci			dev_err(dev, "fail to alloc pbuf dma resource!\n");
45562306a36Sopenharmony_ci			goto alloc_pbuf_fail;
45662306a36Sopenharmony_ci		}
45762306a36Sopenharmony_ci	}
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	return 0;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cialloc_pbuf_fail:
46262306a36Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD)
46362306a36Sopenharmony_ci		sec_free_mac_resource(dev, qp_ctx->res);
46462306a36Sopenharmony_cialloc_mac_fail:
46562306a36Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD)
46662306a36Sopenharmony_ci		sec_free_aiv_resource(dev, res);
46762306a36Sopenharmony_cialloc_aiv_fail:
46862306a36Sopenharmony_ci	sec_free_civ_resource(dev, res);
46962306a36Sopenharmony_ci	return ret;
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_cistatic void sec_alg_resource_free(struct sec_ctx *ctx,
47362306a36Sopenharmony_ci				  struct sec_qp_ctx *qp_ctx)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	struct device *dev = ctx->dev;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	sec_free_civ_resource(dev, qp_ctx->res);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (ctx->pbuf_supported)
48062306a36Sopenharmony_ci		sec_free_pbuf_resource(dev, qp_ctx->res);
48162306a36Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD)
48262306a36Sopenharmony_ci		sec_free_mac_resource(dev, qp_ctx->res);
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic int sec_alloc_qp_ctx_resource(struct hisi_qm *qm, struct sec_ctx *ctx,
48662306a36Sopenharmony_ci				     struct sec_qp_ctx *qp_ctx)
48762306a36Sopenharmony_ci{
48862306a36Sopenharmony_ci	u16 q_depth = qp_ctx->qp->sq_depth;
48962306a36Sopenharmony_ci	struct device *dev = ctx->dev;
49062306a36Sopenharmony_ci	int ret = -ENOMEM;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	qp_ctx->req_list = kcalloc(q_depth, sizeof(struct sec_req *), GFP_KERNEL);
49362306a36Sopenharmony_ci	if (!qp_ctx->req_list)
49462306a36Sopenharmony_ci		return ret;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	qp_ctx->res = kcalloc(q_depth, sizeof(struct sec_alg_res), GFP_KERNEL);
49762306a36Sopenharmony_ci	if (!qp_ctx->res)
49862306a36Sopenharmony_ci		goto err_free_req_list;
49962306a36Sopenharmony_ci	qp_ctx->res->depth = q_depth;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, q_depth, SEC_SGL_SGE_NR);
50262306a36Sopenharmony_ci	if (IS_ERR(qp_ctx->c_in_pool)) {
50362306a36Sopenharmony_ci		dev_err(dev, "fail to create sgl pool for input!\n");
50462306a36Sopenharmony_ci		goto err_free_res;
50562306a36Sopenharmony_ci	}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, q_depth, SEC_SGL_SGE_NR);
50862306a36Sopenharmony_ci	if (IS_ERR(qp_ctx->c_out_pool)) {
50962306a36Sopenharmony_ci		dev_err(dev, "fail to create sgl pool for output!\n");
51062306a36Sopenharmony_ci		goto err_free_c_in_pool;
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	ret = sec_alg_resource_alloc(ctx, qp_ctx);
51462306a36Sopenharmony_ci	if (ret)
51562306a36Sopenharmony_ci		goto err_free_c_out_pool;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	return 0;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_cierr_free_c_out_pool:
52062306a36Sopenharmony_ci	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
52162306a36Sopenharmony_cierr_free_c_in_pool:
52262306a36Sopenharmony_ci	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
52362306a36Sopenharmony_cierr_free_res:
52462306a36Sopenharmony_ci	kfree(qp_ctx->res);
52562306a36Sopenharmony_cierr_free_req_list:
52662306a36Sopenharmony_ci	kfree(qp_ctx->req_list);
52762306a36Sopenharmony_ci	return ret;
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_cistatic void sec_free_qp_ctx_resource(struct sec_ctx *ctx, struct sec_qp_ctx *qp_ctx)
53162306a36Sopenharmony_ci{
53262306a36Sopenharmony_ci	struct device *dev = ctx->dev;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	sec_alg_resource_free(ctx, qp_ctx);
53562306a36Sopenharmony_ci	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
53662306a36Sopenharmony_ci	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
53762306a36Sopenharmony_ci	kfree(qp_ctx->res);
53862306a36Sopenharmony_ci	kfree(qp_ctx->req_list);
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_cistatic int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx,
54262306a36Sopenharmony_ci			     int qp_ctx_id, int alg_type)
54362306a36Sopenharmony_ci{
54462306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx;
54562306a36Sopenharmony_ci	struct hisi_qp *qp;
54662306a36Sopenharmony_ci	int ret;
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	qp_ctx = &ctx->qp_ctx[qp_ctx_id];
54962306a36Sopenharmony_ci	qp = ctx->qps[qp_ctx_id];
55062306a36Sopenharmony_ci	qp->req_type = 0;
55162306a36Sopenharmony_ci	qp->qp_ctx = qp_ctx;
55262306a36Sopenharmony_ci	qp_ctx->qp = qp;
55362306a36Sopenharmony_ci	qp_ctx->ctx = ctx;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	qp->req_cb = sec_req_cb;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	spin_lock_init(&qp_ctx->req_lock);
55862306a36Sopenharmony_ci	idr_init(&qp_ctx->req_idr);
55962306a36Sopenharmony_ci	INIT_LIST_HEAD(&qp_ctx->backlog);
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	ret = sec_alloc_qp_ctx_resource(qm, ctx, qp_ctx);
56262306a36Sopenharmony_ci	if (ret)
56362306a36Sopenharmony_ci		goto err_destroy_idr;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	ret = hisi_qm_start_qp(qp, 0);
56662306a36Sopenharmony_ci	if (ret < 0)
56762306a36Sopenharmony_ci		goto err_resource_free;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	return 0;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_cierr_resource_free:
57262306a36Sopenharmony_ci	sec_free_qp_ctx_resource(ctx, qp_ctx);
57362306a36Sopenharmony_cierr_destroy_idr:
57462306a36Sopenharmony_ci	idr_destroy(&qp_ctx->req_idr);
57562306a36Sopenharmony_ci	return ret;
57662306a36Sopenharmony_ci}
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_cistatic void sec_release_qp_ctx(struct sec_ctx *ctx,
57962306a36Sopenharmony_ci			       struct sec_qp_ctx *qp_ctx)
58062306a36Sopenharmony_ci{
58162306a36Sopenharmony_ci	hisi_qm_stop_qp(qp_ctx->qp);
58262306a36Sopenharmony_ci	sec_free_qp_ctx_resource(ctx, qp_ctx);
58362306a36Sopenharmony_ci	idr_destroy(&qp_ctx->req_idr);
58462306a36Sopenharmony_ci}
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_cistatic int sec_ctx_base_init(struct sec_ctx *ctx)
58762306a36Sopenharmony_ci{
58862306a36Sopenharmony_ci	struct sec_dev *sec;
58962306a36Sopenharmony_ci	int i, ret;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	ctx->qps = sec_create_qps();
59262306a36Sopenharmony_ci	if (!ctx->qps) {
59362306a36Sopenharmony_ci		pr_err("Can not create sec qps!\n");
59462306a36Sopenharmony_ci		return -ENODEV;
59562306a36Sopenharmony_ci	}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	sec = container_of(ctx->qps[0]->qm, struct sec_dev, qm);
59862306a36Sopenharmony_ci	ctx->sec = sec;
59962306a36Sopenharmony_ci	ctx->dev = &sec->qm.pdev->dev;
60062306a36Sopenharmony_ci	ctx->hlf_q_num = sec->ctx_q_num >> 1;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	ctx->pbuf_supported = ctx->sec->iommu_used;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	/* Half of queue depth is taken as fake requests limit in the queue. */
60562306a36Sopenharmony_ci	ctx->fake_req_limit = ctx->qps[0]->sq_depth >> 1;
60662306a36Sopenharmony_ci	ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx),
60762306a36Sopenharmony_ci			      GFP_KERNEL);
60862306a36Sopenharmony_ci	if (!ctx->qp_ctx) {
60962306a36Sopenharmony_ci		ret = -ENOMEM;
61062306a36Sopenharmony_ci		goto err_destroy_qps;
61162306a36Sopenharmony_ci	}
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	for (i = 0; i < sec->ctx_q_num; i++) {
61462306a36Sopenharmony_ci		ret = sec_create_qp_ctx(&sec->qm, ctx, i, 0);
61562306a36Sopenharmony_ci		if (ret)
61662306a36Sopenharmony_ci			goto err_sec_release_qp_ctx;
61762306a36Sopenharmony_ci	}
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	return 0;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_cierr_sec_release_qp_ctx:
62262306a36Sopenharmony_ci	for (i = i - 1; i >= 0; i--)
62362306a36Sopenharmony_ci		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
62462306a36Sopenharmony_ci	kfree(ctx->qp_ctx);
62562306a36Sopenharmony_cierr_destroy_qps:
62662306a36Sopenharmony_ci	sec_destroy_qps(ctx->qps, sec->ctx_q_num);
62762306a36Sopenharmony_ci	return ret;
62862306a36Sopenharmony_ci}
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_cistatic void sec_ctx_base_uninit(struct sec_ctx *ctx)
63162306a36Sopenharmony_ci{
63262306a36Sopenharmony_ci	int i;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	for (i = 0; i < ctx->sec->ctx_q_num; i++)
63562306a36Sopenharmony_ci		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	sec_destroy_qps(ctx->qps, ctx->sec->ctx_q_num);
63862306a36Sopenharmony_ci	kfree(ctx->qp_ctx);
63962306a36Sopenharmony_ci}
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_cistatic int sec_cipher_init(struct sec_ctx *ctx)
64262306a36Sopenharmony_ci{
64362306a36Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	c_ctx->c_key = dma_alloc_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
64662306a36Sopenharmony_ci					  &c_ctx->c_key_dma, GFP_KERNEL);
64762306a36Sopenharmony_ci	if (!c_ctx->c_key)
64862306a36Sopenharmony_ci		return -ENOMEM;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	return 0;
65162306a36Sopenharmony_ci}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_cistatic void sec_cipher_uninit(struct sec_ctx *ctx)
65462306a36Sopenharmony_ci{
65562306a36Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	memzero_explicit(c_ctx->c_key, SEC_MAX_KEY_SIZE);
65862306a36Sopenharmony_ci	dma_free_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
65962306a36Sopenharmony_ci			  c_ctx->c_key, c_ctx->c_key_dma);
66062306a36Sopenharmony_ci}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_cistatic int sec_auth_init(struct sec_ctx *ctx)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	a_ctx->a_key = dma_alloc_coherent(ctx->dev, SEC_MAX_AKEY_SIZE,
66762306a36Sopenharmony_ci					  &a_ctx->a_key_dma, GFP_KERNEL);
66862306a36Sopenharmony_ci	if (!a_ctx->a_key)
66962306a36Sopenharmony_ci		return -ENOMEM;
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	return 0;
67262306a36Sopenharmony_ci}
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_cistatic void sec_auth_uninit(struct sec_ctx *ctx)
67562306a36Sopenharmony_ci{
67662306a36Sopenharmony_ci	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	memzero_explicit(a_ctx->a_key, SEC_MAX_AKEY_SIZE);
67962306a36Sopenharmony_ci	dma_free_coherent(ctx->dev, SEC_MAX_AKEY_SIZE,
68062306a36Sopenharmony_ci			  a_ctx->a_key, a_ctx->a_key_dma);
68162306a36Sopenharmony_ci}
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_cistatic int sec_skcipher_fbtfm_init(struct crypto_skcipher *tfm)
68462306a36Sopenharmony_ci{
68562306a36Sopenharmony_ci	const char *alg = crypto_tfm_alg_name(&tfm->base);
68662306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
68762306a36Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	c_ctx->fallback = false;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	/* Currently, only XTS mode need fallback tfm when using 192bit key */
69262306a36Sopenharmony_ci	if (likely(strncmp(alg, "xts", SEC_XTS_NAME_SZ)))
69362306a36Sopenharmony_ci		return 0;
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	c_ctx->fbtfm = crypto_alloc_sync_skcipher(alg, 0,
69662306a36Sopenharmony_ci						  CRYPTO_ALG_NEED_FALLBACK);
69762306a36Sopenharmony_ci	if (IS_ERR(c_ctx->fbtfm)) {
69862306a36Sopenharmony_ci		pr_err("failed to alloc xts mode fallback tfm!\n");
69962306a36Sopenharmony_ci		return PTR_ERR(c_ctx->fbtfm);
70062306a36Sopenharmony_ci	}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	return 0;
70362306a36Sopenharmony_ci}
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_cistatic int sec_skcipher_init(struct crypto_skcipher *tfm)
70662306a36Sopenharmony_ci{
70762306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
70862306a36Sopenharmony_ci	int ret;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	ctx->alg_type = SEC_SKCIPHER;
71162306a36Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req));
71262306a36Sopenharmony_ci	ctx->c_ctx.ivsize = crypto_skcipher_ivsize(tfm);
71362306a36Sopenharmony_ci	if (ctx->c_ctx.ivsize > SEC_IV_SIZE) {
71462306a36Sopenharmony_ci		pr_err("get error skcipher iv size!\n");
71562306a36Sopenharmony_ci		return -EINVAL;
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	ret = sec_ctx_base_init(ctx);
71962306a36Sopenharmony_ci	if (ret)
72062306a36Sopenharmony_ci		return ret;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	ret = sec_cipher_init(ctx);
72362306a36Sopenharmony_ci	if (ret)
72462306a36Sopenharmony_ci		goto err_cipher_init;
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	ret = sec_skcipher_fbtfm_init(tfm);
72762306a36Sopenharmony_ci	if (ret)
72862306a36Sopenharmony_ci		goto err_fbtfm_init;
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	return 0;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_cierr_fbtfm_init:
73362306a36Sopenharmony_ci	sec_cipher_uninit(ctx);
73462306a36Sopenharmony_cierr_cipher_init:
73562306a36Sopenharmony_ci	sec_ctx_base_uninit(ctx);
73662306a36Sopenharmony_ci	return ret;
73762306a36Sopenharmony_ci}
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_cistatic void sec_skcipher_uninit(struct crypto_skcipher *tfm)
74062306a36Sopenharmony_ci{
74162306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	if (ctx->c_ctx.fbtfm)
74462306a36Sopenharmony_ci		crypto_free_sync_skcipher(ctx->c_ctx.fbtfm);
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	sec_cipher_uninit(ctx);
74762306a36Sopenharmony_ci	sec_ctx_base_uninit(ctx);
74862306a36Sopenharmony_ci}
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_cistatic int sec_skcipher_3des_setkey(struct crypto_skcipher *tfm, const u8 *key,
75162306a36Sopenharmony_ci				    const u32 keylen,
75262306a36Sopenharmony_ci				    const enum sec_cmode c_mode)
75362306a36Sopenharmony_ci{
75462306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
75562306a36Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
75662306a36Sopenharmony_ci	int ret;
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	ret = verify_skcipher_des3_key(tfm, key);
75962306a36Sopenharmony_ci	if (ret)
76062306a36Sopenharmony_ci		return ret;
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	switch (keylen) {
76362306a36Sopenharmony_ci	case SEC_DES3_2KEY_SIZE:
76462306a36Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_3DES_2KEY;
76562306a36Sopenharmony_ci		break;
76662306a36Sopenharmony_ci	case SEC_DES3_3KEY_SIZE:
76762306a36Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_3DES_3KEY;
76862306a36Sopenharmony_ci		break;
76962306a36Sopenharmony_ci	default:
77062306a36Sopenharmony_ci		return -EINVAL;
77162306a36Sopenharmony_ci	}
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	return 0;
77462306a36Sopenharmony_ci}
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_cistatic int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx,
77762306a36Sopenharmony_ci				       const u32 keylen,
77862306a36Sopenharmony_ci				       const enum sec_cmode c_mode)
77962306a36Sopenharmony_ci{
78062306a36Sopenharmony_ci	if (c_mode == SEC_CMODE_XTS) {
78162306a36Sopenharmony_ci		switch (keylen) {
78262306a36Sopenharmony_ci		case SEC_XTS_MIN_KEY_SIZE:
78362306a36Sopenharmony_ci			c_ctx->c_key_len = SEC_CKEY_128BIT;
78462306a36Sopenharmony_ci			break;
78562306a36Sopenharmony_ci		case SEC_XTS_MID_KEY_SIZE:
78662306a36Sopenharmony_ci			c_ctx->fallback = true;
78762306a36Sopenharmony_ci			break;
78862306a36Sopenharmony_ci		case SEC_XTS_MAX_KEY_SIZE:
78962306a36Sopenharmony_ci			c_ctx->c_key_len = SEC_CKEY_256BIT;
79062306a36Sopenharmony_ci			break;
79162306a36Sopenharmony_ci		default:
79262306a36Sopenharmony_ci			pr_err("hisi_sec2: xts mode key error!\n");
79362306a36Sopenharmony_ci			return -EINVAL;
79462306a36Sopenharmony_ci		}
79562306a36Sopenharmony_ci	} else {
79662306a36Sopenharmony_ci		if (c_ctx->c_alg == SEC_CALG_SM4 &&
79762306a36Sopenharmony_ci		    keylen != AES_KEYSIZE_128) {
79862306a36Sopenharmony_ci			pr_err("hisi_sec2: sm4 key error!\n");
79962306a36Sopenharmony_ci			return -EINVAL;
80062306a36Sopenharmony_ci		} else {
80162306a36Sopenharmony_ci			switch (keylen) {
80262306a36Sopenharmony_ci			case AES_KEYSIZE_128:
80362306a36Sopenharmony_ci				c_ctx->c_key_len = SEC_CKEY_128BIT;
80462306a36Sopenharmony_ci				break;
80562306a36Sopenharmony_ci			case AES_KEYSIZE_192:
80662306a36Sopenharmony_ci				c_ctx->c_key_len = SEC_CKEY_192BIT;
80762306a36Sopenharmony_ci				break;
80862306a36Sopenharmony_ci			case AES_KEYSIZE_256:
80962306a36Sopenharmony_ci				c_ctx->c_key_len = SEC_CKEY_256BIT;
81062306a36Sopenharmony_ci				break;
81162306a36Sopenharmony_ci			default:
81262306a36Sopenharmony_ci				pr_err("hisi_sec2: aes key error!\n");
81362306a36Sopenharmony_ci				return -EINVAL;
81462306a36Sopenharmony_ci			}
81562306a36Sopenharmony_ci		}
81662306a36Sopenharmony_ci	}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	return 0;
81962306a36Sopenharmony_ci}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_cistatic int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
82262306a36Sopenharmony_ci			       const u32 keylen, const enum sec_calg c_alg,
82362306a36Sopenharmony_ci			       const enum sec_cmode c_mode)
82462306a36Sopenharmony_ci{
82562306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
82662306a36Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
82762306a36Sopenharmony_ci	struct device *dev = ctx->dev;
82862306a36Sopenharmony_ci	int ret;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	if (c_mode == SEC_CMODE_XTS) {
83162306a36Sopenharmony_ci		ret = xts_verify_key(tfm, key, keylen);
83262306a36Sopenharmony_ci		if (ret) {
83362306a36Sopenharmony_ci			dev_err(dev, "xts mode key err!\n");
83462306a36Sopenharmony_ci			return ret;
83562306a36Sopenharmony_ci		}
83662306a36Sopenharmony_ci	}
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	c_ctx->c_alg  = c_alg;
83962306a36Sopenharmony_ci	c_ctx->c_mode = c_mode;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	switch (c_alg) {
84262306a36Sopenharmony_ci	case SEC_CALG_3DES:
84362306a36Sopenharmony_ci		ret = sec_skcipher_3des_setkey(tfm, key, keylen, c_mode);
84462306a36Sopenharmony_ci		break;
84562306a36Sopenharmony_ci	case SEC_CALG_AES:
84662306a36Sopenharmony_ci	case SEC_CALG_SM4:
84762306a36Sopenharmony_ci		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
84862306a36Sopenharmony_ci		break;
84962306a36Sopenharmony_ci	default:
85062306a36Sopenharmony_ci		return -EINVAL;
85162306a36Sopenharmony_ci	}
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	if (ret) {
85462306a36Sopenharmony_ci		dev_err(dev, "set sec key err!\n");
85562306a36Sopenharmony_ci		return ret;
85662306a36Sopenharmony_ci	}
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	memcpy(c_ctx->c_key, key, keylen);
85962306a36Sopenharmony_ci	if (c_ctx->fallback && c_ctx->fbtfm) {
86062306a36Sopenharmony_ci		ret = crypto_sync_skcipher_setkey(c_ctx->fbtfm, key, keylen);
86162306a36Sopenharmony_ci		if (ret) {
86262306a36Sopenharmony_ci			dev_err(dev, "failed to set fallback skcipher key!\n");
86362306a36Sopenharmony_ci			return ret;
86462306a36Sopenharmony_ci		}
86562306a36Sopenharmony_ci	}
86662306a36Sopenharmony_ci	return 0;
86762306a36Sopenharmony_ci}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci#define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode)			\
87062306a36Sopenharmony_cistatic int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\
87162306a36Sopenharmony_ci	u32 keylen)							\
87262306a36Sopenharmony_ci{									\
87362306a36Sopenharmony_ci	return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode);	\
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB)
87762306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC)
87862306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS)
87962306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_ofb, SEC_CALG_AES, SEC_CMODE_OFB)
88062306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_cfb, SEC_CALG_AES, SEC_CMODE_CFB)
88162306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_ctr, SEC_CALG_AES, SEC_CMODE_CTR)
88262306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB)
88362306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC)
88462306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS)
88562306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC)
88662306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(sm4_ofb, SEC_CALG_SM4, SEC_CMODE_OFB)
88762306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(sm4_cfb, SEC_CALG_SM4, SEC_CMODE_CFB)
88862306a36Sopenharmony_ciGEN_SEC_SETKEY_FUNC(sm4_ctr, SEC_CALG_SM4, SEC_CMODE_CTR)
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_cistatic int sec_cipher_pbuf_map(struct sec_ctx *ctx, struct sec_req *req,
89162306a36Sopenharmony_ci			struct scatterlist *src)
89262306a36Sopenharmony_ci{
89362306a36Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
89462306a36Sopenharmony_ci	struct aead_request *aead_req = a_req->aead_req;
89562306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
89662306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
89762306a36Sopenharmony_ci	struct device *dev = ctx->dev;
89862306a36Sopenharmony_ci	int copy_size, pbuf_length;
89962306a36Sopenharmony_ci	int req_id = req->req_id;
90062306a36Sopenharmony_ci	struct crypto_aead *tfm;
90162306a36Sopenharmony_ci	size_t authsize;
90262306a36Sopenharmony_ci	u8 *mac_offset;
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD)
90562306a36Sopenharmony_ci		copy_size = aead_req->cryptlen + aead_req->assoclen;
90662306a36Sopenharmony_ci	else
90762306a36Sopenharmony_ci		copy_size = c_req->c_len;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	pbuf_length = sg_copy_to_buffer(src, sg_nents(src),
91062306a36Sopenharmony_ci			qp_ctx->res[req_id].pbuf, copy_size);
91162306a36Sopenharmony_ci	if (unlikely(pbuf_length != copy_size)) {
91262306a36Sopenharmony_ci		dev_err(dev, "copy src data to pbuf error!\n");
91362306a36Sopenharmony_ci		return -EINVAL;
91462306a36Sopenharmony_ci	}
91562306a36Sopenharmony_ci	if (!c_req->encrypt && ctx->alg_type == SEC_AEAD) {
91662306a36Sopenharmony_ci		tfm = crypto_aead_reqtfm(aead_req);
91762306a36Sopenharmony_ci		authsize = crypto_aead_authsize(tfm);
91862306a36Sopenharmony_ci		mac_offset = qp_ctx->res[req_id].pbuf + copy_size - authsize;
91962306a36Sopenharmony_ci		memcpy(a_req->out_mac, mac_offset, authsize);
92062306a36Sopenharmony_ci	}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	req->in_dma = qp_ctx->res[req_id].pbuf_dma;
92362306a36Sopenharmony_ci	c_req->c_out_dma = req->in_dma;
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	return 0;
92662306a36Sopenharmony_ci}
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_cistatic void sec_cipher_pbuf_unmap(struct sec_ctx *ctx, struct sec_req *req,
92962306a36Sopenharmony_ci			struct scatterlist *dst)
93062306a36Sopenharmony_ci{
93162306a36Sopenharmony_ci	struct aead_request *aead_req = req->aead_req.aead_req;
93262306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
93362306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
93462306a36Sopenharmony_ci	int copy_size, pbuf_length;
93562306a36Sopenharmony_ci	int req_id = req->req_id;
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD)
93862306a36Sopenharmony_ci		copy_size = c_req->c_len + aead_req->assoclen;
93962306a36Sopenharmony_ci	else
94062306a36Sopenharmony_ci		copy_size = c_req->c_len;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	pbuf_length = sg_copy_from_buffer(dst, sg_nents(dst),
94362306a36Sopenharmony_ci			qp_ctx->res[req_id].pbuf, copy_size);
94462306a36Sopenharmony_ci	if (unlikely(pbuf_length != copy_size))
94562306a36Sopenharmony_ci		dev_err(ctx->dev, "copy pbuf data to dst error!\n");
94662306a36Sopenharmony_ci}
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_cistatic int sec_aead_mac_init(struct sec_aead_req *req)
94962306a36Sopenharmony_ci{
95062306a36Sopenharmony_ci	struct aead_request *aead_req = req->aead_req;
95162306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
95262306a36Sopenharmony_ci	size_t authsize = crypto_aead_authsize(tfm);
95362306a36Sopenharmony_ci	u8 *mac_out = req->out_mac;
95462306a36Sopenharmony_ci	struct scatterlist *sgl = aead_req->src;
95562306a36Sopenharmony_ci	size_t copy_size;
95662306a36Sopenharmony_ci	off_t skip_size;
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	/* Copy input mac */
95962306a36Sopenharmony_ci	skip_size = aead_req->assoclen + aead_req->cryptlen - authsize;
96062306a36Sopenharmony_ci	copy_size = sg_pcopy_to_buffer(sgl, sg_nents(sgl), mac_out,
96162306a36Sopenharmony_ci				       authsize, skip_size);
96262306a36Sopenharmony_ci	if (unlikely(copy_size != authsize))
96362306a36Sopenharmony_ci		return -EINVAL;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	return 0;
96662306a36Sopenharmony_ci}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_cistatic int sec_cipher_map(struct sec_ctx *ctx, struct sec_req *req,
96962306a36Sopenharmony_ci			  struct scatterlist *src, struct scatterlist *dst)
97062306a36Sopenharmony_ci{
97162306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
97262306a36Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
97362306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
97462306a36Sopenharmony_ci	struct sec_alg_res *res = &qp_ctx->res[req->req_id];
97562306a36Sopenharmony_ci	struct device *dev = ctx->dev;
97662306a36Sopenharmony_ci	int ret;
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	if (req->use_pbuf) {
97962306a36Sopenharmony_ci		c_req->c_ivin = res->pbuf + SEC_PBUF_IV_OFFSET;
98062306a36Sopenharmony_ci		c_req->c_ivin_dma = res->pbuf_dma + SEC_PBUF_IV_OFFSET;
98162306a36Sopenharmony_ci		if (ctx->alg_type == SEC_AEAD) {
98262306a36Sopenharmony_ci			a_req->a_ivin = res->a_ivin;
98362306a36Sopenharmony_ci			a_req->a_ivin_dma = res->a_ivin_dma;
98462306a36Sopenharmony_ci			a_req->out_mac = res->pbuf + SEC_PBUF_MAC_OFFSET;
98562306a36Sopenharmony_ci			a_req->out_mac_dma = res->pbuf_dma +
98662306a36Sopenharmony_ci					SEC_PBUF_MAC_OFFSET;
98762306a36Sopenharmony_ci		}
98862306a36Sopenharmony_ci		ret = sec_cipher_pbuf_map(ctx, req, src);
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci		return ret;
99162306a36Sopenharmony_ci	}
99262306a36Sopenharmony_ci	c_req->c_ivin = res->c_ivin;
99362306a36Sopenharmony_ci	c_req->c_ivin_dma = res->c_ivin_dma;
99462306a36Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD) {
99562306a36Sopenharmony_ci		a_req->a_ivin = res->a_ivin;
99662306a36Sopenharmony_ci		a_req->a_ivin_dma = res->a_ivin_dma;
99762306a36Sopenharmony_ci		a_req->out_mac = res->out_mac;
99862306a36Sopenharmony_ci		a_req->out_mac_dma = res->out_mac_dma;
99962306a36Sopenharmony_ci	}
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	req->in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src,
100262306a36Sopenharmony_ci						qp_ctx->c_in_pool,
100362306a36Sopenharmony_ci						req->req_id,
100462306a36Sopenharmony_ci						&req->in_dma);
100562306a36Sopenharmony_ci	if (IS_ERR(req->in)) {
100662306a36Sopenharmony_ci		dev_err(dev, "fail to dma map input sgl buffers!\n");
100762306a36Sopenharmony_ci		return PTR_ERR(req->in);
100862306a36Sopenharmony_ci	}
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	if (!c_req->encrypt && ctx->alg_type == SEC_AEAD) {
101162306a36Sopenharmony_ci		ret = sec_aead_mac_init(a_req);
101262306a36Sopenharmony_ci		if (unlikely(ret)) {
101362306a36Sopenharmony_ci			dev_err(dev, "fail to init mac data for ICV!\n");
101462306a36Sopenharmony_ci			return ret;
101562306a36Sopenharmony_ci		}
101662306a36Sopenharmony_ci	}
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	if (dst == src) {
101962306a36Sopenharmony_ci		c_req->c_out = req->in;
102062306a36Sopenharmony_ci		c_req->c_out_dma = req->in_dma;
102162306a36Sopenharmony_ci	} else {
102262306a36Sopenharmony_ci		c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst,
102362306a36Sopenharmony_ci							     qp_ctx->c_out_pool,
102462306a36Sopenharmony_ci							     req->req_id,
102562306a36Sopenharmony_ci							     &c_req->c_out_dma);
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci		if (IS_ERR(c_req->c_out)) {
102862306a36Sopenharmony_ci			dev_err(dev, "fail to dma map output sgl buffers!\n");
102962306a36Sopenharmony_ci			hisi_acc_sg_buf_unmap(dev, src, req->in);
103062306a36Sopenharmony_ci			return PTR_ERR(c_req->c_out);
103162306a36Sopenharmony_ci		}
103262306a36Sopenharmony_ci	}
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	return 0;
103562306a36Sopenharmony_ci}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_cistatic void sec_cipher_unmap(struct sec_ctx *ctx, struct sec_req *req,
103862306a36Sopenharmony_ci			     struct scatterlist *src, struct scatterlist *dst)
103962306a36Sopenharmony_ci{
104062306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
104162306a36Sopenharmony_ci	struct device *dev = ctx->dev;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	if (req->use_pbuf) {
104462306a36Sopenharmony_ci		sec_cipher_pbuf_unmap(ctx, req, dst);
104562306a36Sopenharmony_ci	} else {
104662306a36Sopenharmony_ci		if (dst != src)
104762306a36Sopenharmony_ci			hisi_acc_sg_buf_unmap(dev, src, req->in);
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci		hisi_acc_sg_buf_unmap(dev, dst, c_req->c_out);
105062306a36Sopenharmony_ci	}
105162306a36Sopenharmony_ci}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_cistatic int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
105462306a36Sopenharmony_ci{
105562306a36Sopenharmony_ci	struct skcipher_request *sq = req->c_req.sk_req;
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci	return sec_cipher_map(ctx, req, sq->src, sq->dst);
105862306a36Sopenharmony_ci}
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_cistatic void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
106162306a36Sopenharmony_ci{
106262306a36Sopenharmony_ci	struct skcipher_request *sq = req->c_req.sk_req;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	sec_cipher_unmap(ctx, req, sq->src, sq->dst);
106562306a36Sopenharmony_ci}
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_cistatic int sec_aead_aes_set_key(struct sec_cipher_ctx *c_ctx,
106862306a36Sopenharmony_ci				struct crypto_authenc_keys *keys)
106962306a36Sopenharmony_ci{
107062306a36Sopenharmony_ci	switch (keys->enckeylen) {
107162306a36Sopenharmony_ci	case AES_KEYSIZE_128:
107262306a36Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_128BIT;
107362306a36Sopenharmony_ci		break;
107462306a36Sopenharmony_ci	case AES_KEYSIZE_192:
107562306a36Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_192BIT;
107662306a36Sopenharmony_ci		break;
107762306a36Sopenharmony_ci	case AES_KEYSIZE_256:
107862306a36Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_256BIT;
107962306a36Sopenharmony_ci		break;
108062306a36Sopenharmony_ci	default:
108162306a36Sopenharmony_ci		pr_err("hisi_sec2: aead aes key error!\n");
108262306a36Sopenharmony_ci		return -EINVAL;
108362306a36Sopenharmony_ci	}
108462306a36Sopenharmony_ci	memcpy(c_ctx->c_key, keys->enckey, keys->enckeylen);
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	return 0;
108762306a36Sopenharmony_ci}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_cistatic int sec_aead_auth_set_key(struct sec_auth_ctx *ctx,
109062306a36Sopenharmony_ci				 struct crypto_authenc_keys *keys)
109162306a36Sopenharmony_ci{
109262306a36Sopenharmony_ci	struct crypto_shash *hash_tfm = ctx->hash_tfm;
109362306a36Sopenharmony_ci	int blocksize, digestsize, ret;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	if (!keys->authkeylen) {
109662306a36Sopenharmony_ci		pr_err("hisi_sec2: aead auth key error!\n");
109762306a36Sopenharmony_ci		return -EINVAL;
109862306a36Sopenharmony_ci	}
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	blocksize = crypto_shash_blocksize(hash_tfm);
110162306a36Sopenharmony_ci	digestsize = crypto_shash_digestsize(hash_tfm);
110262306a36Sopenharmony_ci	if (keys->authkeylen > blocksize) {
110362306a36Sopenharmony_ci		ret = crypto_shash_tfm_digest(hash_tfm, keys->authkey,
110462306a36Sopenharmony_ci					      keys->authkeylen, ctx->a_key);
110562306a36Sopenharmony_ci		if (ret) {
110662306a36Sopenharmony_ci			pr_err("hisi_sec2: aead auth digest error!\n");
110762306a36Sopenharmony_ci			return -EINVAL;
110862306a36Sopenharmony_ci		}
110962306a36Sopenharmony_ci		ctx->a_key_len = digestsize;
111062306a36Sopenharmony_ci	} else {
111162306a36Sopenharmony_ci		memcpy(ctx->a_key, keys->authkey, keys->authkeylen);
111262306a36Sopenharmony_ci		ctx->a_key_len = keys->authkeylen;
111362306a36Sopenharmony_ci	}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	return 0;
111662306a36Sopenharmony_ci}
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_cistatic int sec_aead_setauthsize(struct crypto_aead *aead, unsigned int authsize)
111962306a36Sopenharmony_ci{
112062306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
112162306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_tfm_ctx(tfm);
112262306a36Sopenharmony_ci	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	if (unlikely(a_ctx->fallback_aead_tfm))
112562306a36Sopenharmony_ci		return crypto_aead_setauthsize(a_ctx->fallback_aead_tfm, authsize);
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	return 0;
112862306a36Sopenharmony_ci}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_cistatic int sec_aead_fallback_setkey(struct sec_auth_ctx *a_ctx,
113162306a36Sopenharmony_ci				    struct crypto_aead *tfm, const u8 *key,
113262306a36Sopenharmony_ci				    unsigned int keylen)
113362306a36Sopenharmony_ci{
113462306a36Sopenharmony_ci	crypto_aead_clear_flags(a_ctx->fallback_aead_tfm, CRYPTO_TFM_REQ_MASK);
113562306a36Sopenharmony_ci	crypto_aead_set_flags(a_ctx->fallback_aead_tfm,
113662306a36Sopenharmony_ci			      crypto_aead_get_flags(tfm) & CRYPTO_TFM_REQ_MASK);
113762306a36Sopenharmony_ci	return crypto_aead_setkey(a_ctx->fallback_aead_tfm, key, keylen);
113862306a36Sopenharmony_ci}
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_cistatic int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
114162306a36Sopenharmony_ci			   const u32 keylen, const enum sec_hash_alg a_alg,
114262306a36Sopenharmony_ci			   const enum sec_calg c_alg,
114362306a36Sopenharmony_ci			   const enum sec_mac_len mac_len,
114462306a36Sopenharmony_ci			   const enum sec_cmode c_mode)
114562306a36Sopenharmony_ci{
114662306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
114762306a36Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
114862306a36Sopenharmony_ci	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
114962306a36Sopenharmony_ci	struct device *dev = ctx->dev;
115062306a36Sopenharmony_ci	struct crypto_authenc_keys keys;
115162306a36Sopenharmony_ci	int ret;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	ctx->a_ctx.a_alg = a_alg;
115462306a36Sopenharmony_ci	ctx->c_ctx.c_alg = c_alg;
115562306a36Sopenharmony_ci	ctx->a_ctx.mac_len = mac_len;
115662306a36Sopenharmony_ci	c_ctx->c_mode = c_mode;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	if (c_mode == SEC_CMODE_CCM || c_mode == SEC_CMODE_GCM) {
115962306a36Sopenharmony_ci		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
116062306a36Sopenharmony_ci		if (ret) {
116162306a36Sopenharmony_ci			dev_err(dev, "set sec aes ccm cipher key err!\n");
116262306a36Sopenharmony_ci			return ret;
116362306a36Sopenharmony_ci		}
116462306a36Sopenharmony_ci		memcpy(c_ctx->c_key, key, keylen);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci		if (unlikely(a_ctx->fallback_aead_tfm)) {
116762306a36Sopenharmony_ci			ret = sec_aead_fallback_setkey(a_ctx, tfm, key, keylen);
116862306a36Sopenharmony_ci			if (ret)
116962306a36Sopenharmony_ci				return ret;
117062306a36Sopenharmony_ci		}
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci		return 0;
117362306a36Sopenharmony_ci	}
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen))
117662306a36Sopenharmony_ci		goto bad_key;
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	ret = sec_aead_aes_set_key(c_ctx, &keys);
117962306a36Sopenharmony_ci	if (ret) {
118062306a36Sopenharmony_ci		dev_err(dev, "set sec cipher key err!\n");
118162306a36Sopenharmony_ci		goto bad_key;
118262306a36Sopenharmony_ci	}
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	ret = sec_aead_auth_set_key(&ctx->a_ctx, &keys);
118562306a36Sopenharmony_ci	if (ret) {
118662306a36Sopenharmony_ci		dev_err(dev, "set sec auth key err!\n");
118762306a36Sopenharmony_ci		goto bad_key;
118862306a36Sopenharmony_ci	}
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	if ((ctx->a_ctx.mac_len & SEC_SQE_LEN_RATE_MASK)  ||
119162306a36Sopenharmony_ci	    (ctx->a_ctx.a_key_len & SEC_SQE_LEN_RATE_MASK)) {
119262306a36Sopenharmony_ci		dev_err(dev, "MAC or AUTH key length error!\n");
119362306a36Sopenharmony_ci		goto bad_key;
119462306a36Sopenharmony_ci	}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	return 0;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_cibad_key:
119962306a36Sopenharmony_ci	memzero_explicit(&keys, sizeof(struct crypto_authenc_keys));
120062306a36Sopenharmony_ci	return -EINVAL;
120162306a36Sopenharmony_ci}
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci#define GEN_SEC_AEAD_SETKEY_FUNC(name, aalg, calg, maclen, cmode)	\
120562306a36Sopenharmony_cistatic int sec_setkey_##name(struct crypto_aead *tfm, const u8 *key,	\
120662306a36Sopenharmony_ci	u32 keylen)							\
120762306a36Sopenharmony_ci{									\
120862306a36Sopenharmony_ci	return sec_aead_setkey(tfm, key, keylen, aalg, calg, maclen, cmode);\
120962306a36Sopenharmony_ci}
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha1, SEC_A_HMAC_SHA1,
121262306a36Sopenharmony_ci			 SEC_CALG_AES, SEC_HMAC_SHA1_MAC, SEC_CMODE_CBC)
121362306a36Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha256, SEC_A_HMAC_SHA256,
121462306a36Sopenharmony_ci			 SEC_CALG_AES, SEC_HMAC_SHA256_MAC, SEC_CMODE_CBC)
121562306a36Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha512, SEC_A_HMAC_SHA512,
121662306a36Sopenharmony_ci			 SEC_CALG_AES, SEC_HMAC_SHA512_MAC, SEC_CMODE_CBC)
121762306a36Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_ccm, 0, SEC_CALG_AES,
121862306a36Sopenharmony_ci			 SEC_HMAC_CCM_MAC, SEC_CMODE_CCM)
121962306a36Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_gcm, 0, SEC_CALG_AES,
122062306a36Sopenharmony_ci			 SEC_HMAC_GCM_MAC, SEC_CMODE_GCM)
122162306a36Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(sm4_ccm, 0, SEC_CALG_SM4,
122262306a36Sopenharmony_ci			 SEC_HMAC_CCM_MAC, SEC_CMODE_CCM)
122362306a36Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(sm4_gcm, 0, SEC_CALG_SM4,
122462306a36Sopenharmony_ci			 SEC_HMAC_GCM_MAC, SEC_CMODE_GCM)
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_cistatic int sec_aead_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
122762306a36Sopenharmony_ci{
122862306a36Sopenharmony_ci	struct aead_request *aq = req->aead_req.aead_req;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	return sec_cipher_map(ctx, req, aq->src, aq->dst);
123162306a36Sopenharmony_ci}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_cistatic void sec_aead_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
123462306a36Sopenharmony_ci{
123562306a36Sopenharmony_ci	struct aead_request *aq = req->aead_req.aead_req;
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	sec_cipher_unmap(ctx, req, aq->src, aq->dst);
123862306a36Sopenharmony_ci}
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_cistatic int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req)
124162306a36Sopenharmony_ci{
124262306a36Sopenharmony_ci	int ret;
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	ret = ctx->req_op->buf_map(ctx, req);
124562306a36Sopenharmony_ci	if (unlikely(ret))
124662306a36Sopenharmony_ci		return ret;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	ctx->req_op->do_transfer(ctx, req);
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	ret = ctx->req_op->bd_fill(ctx, req);
125162306a36Sopenharmony_ci	if (unlikely(ret))
125262306a36Sopenharmony_ci		goto unmap_req_buf;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	return ret;
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ciunmap_req_buf:
125762306a36Sopenharmony_ci	ctx->req_op->buf_unmap(ctx, req);
125862306a36Sopenharmony_ci	return ret;
125962306a36Sopenharmony_ci}
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_cistatic void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req)
126262306a36Sopenharmony_ci{
126362306a36Sopenharmony_ci	ctx->req_op->buf_unmap(ctx, req);
126462306a36Sopenharmony_ci}
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_cistatic void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
126762306a36Sopenharmony_ci{
126862306a36Sopenharmony_ci	struct skcipher_request *sk_req = req->c_req.sk_req;
126962306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	memcpy(c_req->c_ivin, sk_req->iv, ctx->c_ctx.ivsize);
127262306a36Sopenharmony_ci}
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_cistatic int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
127562306a36Sopenharmony_ci{
127662306a36Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
127762306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
127862306a36Sopenharmony_ci	struct sec_sqe *sec_sqe = &req->sec_sqe;
127962306a36Sopenharmony_ci	u8 scene, sa_type, da_type;
128062306a36Sopenharmony_ci	u8 bd_type, cipher;
128162306a36Sopenharmony_ci	u8 de = 0;
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	memset(sec_sqe, 0, sizeof(struct sec_sqe));
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
128662306a36Sopenharmony_ci	sec_sqe->type2.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
128762306a36Sopenharmony_ci	sec_sqe->type2.data_src_addr = cpu_to_le64(req->in_dma);
128862306a36Sopenharmony_ci	sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma);
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) <<
129162306a36Sopenharmony_ci						SEC_CMODE_OFFSET);
129262306a36Sopenharmony_ci	sec_sqe->type2.c_alg = c_ctx->c_alg;
129362306a36Sopenharmony_ci	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
129462306a36Sopenharmony_ci						SEC_CKEY_OFFSET);
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	bd_type = SEC_BD_TYPE2;
129762306a36Sopenharmony_ci	if (c_req->encrypt)
129862306a36Sopenharmony_ci		cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET;
129962306a36Sopenharmony_ci	else
130062306a36Sopenharmony_ci		cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET;
130162306a36Sopenharmony_ci	sec_sqe->type_cipher_auth = bd_type | cipher;
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	/* Set destination and source address type */
130462306a36Sopenharmony_ci	if (req->use_pbuf) {
130562306a36Sopenharmony_ci		sa_type = SEC_PBUF << SEC_SRC_SGL_OFFSET;
130662306a36Sopenharmony_ci		da_type = SEC_PBUF << SEC_DST_SGL_OFFSET;
130762306a36Sopenharmony_ci	} else {
130862306a36Sopenharmony_ci		sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET;
130962306a36Sopenharmony_ci		da_type = SEC_SGL << SEC_DST_SGL_OFFSET;
131062306a36Sopenharmony_ci	}
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_ci	sec_sqe->sdm_addr_type |= da_type;
131362306a36Sopenharmony_ci	scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET;
131462306a36Sopenharmony_ci	if (req->in_dma != c_req->c_out_dma)
131562306a36Sopenharmony_ci		de = 0x1 << SEC_DE_OFFSET;
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	sec_sqe->sds_sa_type = (de | scene | sa_type);
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len);
132062306a36Sopenharmony_ci	sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id);
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	return 0;
132362306a36Sopenharmony_ci}
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_cistatic int sec_skcipher_bd_fill_v3(struct sec_ctx *ctx, struct sec_req *req)
132662306a36Sopenharmony_ci{
132762306a36Sopenharmony_ci	struct sec_sqe3 *sec_sqe3 = &req->sec_sqe3;
132862306a36Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
132962306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
133062306a36Sopenharmony_ci	u32 bd_param = 0;
133162306a36Sopenharmony_ci	u16 cipher;
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	memset(sec_sqe3, 0, sizeof(struct sec_sqe3));
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	sec_sqe3->c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
133662306a36Sopenharmony_ci	sec_sqe3->no_scene.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
133762306a36Sopenharmony_ci	sec_sqe3->data_src_addr = cpu_to_le64(req->in_dma);
133862306a36Sopenharmony_ci	sec_sqe3->data_dst_addr = cpu_to_le64(c_req->c_out_dma);
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	sec_sqe3->c_mode_alg = ((u8)c_ctx->c_alg << SEC_CALG_OFFSET_V3) |
134162306a36Sopenharmony_ci						c_ctx->c_mode;
134262306a36Sopenharmony_ci	sec_sqe3->c_icv_key |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
134362306a36Sopenharmony_ci						SEC_CKEY_OFFSET_V3);
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	if (c_req->encrypt)
134662306a36Sopenharmony_ci		cipher = SEC_CIPHER_ENC;
134762306a36Sopenharmony_ci	else
134862306a36Sopenharmony_ci		cipher = SEC_CIPHER_DEC;
134962306a36Sopenharmony_ci	sec_sqe3->c_icv_key |= cpu_to_le16(cipher);
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	/* Set the CTR counter mode is 128bit rollover */
135262306a36Sopenharmony_ci	sec_sqe3->auth_mac_key = cpu_to_le32((u32)SEC_CTR_CNT_ROLLOVER <<
135362306a36Sopenharmony_ci					SEC_CTR_CNT_OFFSET);
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	if (req->use_pbuf) {
135662306a36Sopenharmony_ci		bd_param |= SEC_PBUF << SEC_SRC_SGL_OFFSET_V3;
135762306a36Sopenharmony_ci		bd_param |= SEC_PBUF << SEC_DST_SGL_OFFSET_V3;
135862306a36Sopenharmony_ci	} else {
135962306a36Sopenharmony_ci		bd_param |= SEC_SGL << SEC_SRC_SGL_OFFSET_V3;
136062306a36Sopenharmony_ci		bd_param |= SEC_SGL << SEC_DST_SGL_OFFSET_V3;
136162306a36Sopenharmony_ci	}
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	bd_param |= SEC_COMM_SCENE << SEC_SCENE_OFFSET_V3;
136462306a36Sopenharmony_ci	if (req->in_dma != c_req->c_out_dma)
136562306a36Sopenharmony_ci		bd_param |= 0x1 << SEC_DE_OFFSET_V3;
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci	bd_param |= SEC_BD_TYPE3;
136862306a36Sopenharmony_ci	sec_sqe3->bd_param = cpu_to_le32(bd_param);
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci	sec_sqe3->c_len_ivin |= cpu_to_le32(c_req->c_len);
137162306a36Sopenharmony_ci	sec_sqe3->tag = cpu_to_le64(req);
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	return 0;
137462306a36Sopenharmony_ci}
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci/* increment counter (128-bit int) */
137762306a36Sopenharmony_cistatic void ctr_iv_inc(__u8 *counter, __u8 bits, __u32 nums)
137862306a36Sopenharmony_ci{
137962306a36Sopenharmony_ci	do {
138062306a36Sopenharmony_ci		--bits;
138162306a36Sopenharmony_ci		nums += counter[bits];
138262306a36Sopenharmony_ci		counter[bits] = nums & BITS_MASK;
138362306a36Sopenharmony_ci		nums >>= BYTE_BITS;
138462306a36Sopenharmony_ci	} while (bits && nums);
138562306a36Sopenharmony_ci}
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_cistatic void sec_update_iv(struct sec_req *req, enum sec_alg_type alg_type)
138862306a36Sopenharmony_ci{
138962306a36Sopenharmony_ci	struct aead_request *aead_req = req->aead_req.aead_req;
139062306a36Sopenharmony_ci	struct skcipher_request *sk_req = req->c_req.sk_req;
139162306a36Sopenharmony_ci	u32 iv_size = req->ctx->c_ctx.ivsize;
139262306a36Sopenharmony_ci	struct scatterlist *sgl;
139362306a36Sopenharmony_ci	unsigned int cryptlen;
139462306a36Sopenharmony_ci	size_t sz;
139562306a36Sopenharmony_ci	u8 *iv;
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	if (req->c_req.encrypt)
139862306a36Sopenharmony_ci		sgl = alg_type == SEC_SKCIPHER ? sk_req->dst : aead_req->dst;
139962306a36Sopenharmony_ci	else
140062306a36Sopenharmony_ci		sgl = alg_type == SEC_SKCIPHER ? sk_req->src : aead_req->src;
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_ci	if (alg_type == SEC_SKCIPHER) {
140362306a36Sopenharmony_ci		iv = sk_req->iv;
140462306a36Sopenharmony_ci		cryptlen = sk_req->cryptlen;
140562306a36Sopenharmony_ci	} else {
140662306a36Sopenharmony_ci		iv = aead_req->iv;
140762306a36Sopenharmony_ci		cryptlen = aead_req->cryptlen;
140862306a36Sopenharmony_ci	}
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci	if (req->ctx->c_ctx.c_mode == SEC_CMODE_CBC) {
141162306a36Sopenharmony_ci		sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), iv, iv_size,
141262306a36Sopenharmony_ci					cryptlen - iv_size);
141362306a36Sopenharmony_ci		if (unlikely(sz != iv_size))
141462306a36Sopenharmony_ci			dev_err(req->ctx->dev, "copy output iv error!\n");
141562306a36Sopenharmony_ci	} else {
141662306a36Sopenharmony_ci		sz = cryptlen / iv_size;
141762306a36Sopenharmony_ci		if (cryptlen % iv_size)
141862306a36Sopenharmony_ci			sz += 1;
141962306a36Sopenharmony_ci		ctr_iv_inc(iv, iv_size, sz);
142062306a36Sopenharmony_ci	}
142162306a36Sopenharmony_ci}
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_cistatic struct sec_req *sec_back_req_clear(struct sec_ctx *ctx,
142462306a36Sopenharmony_ci				struct sec_qp_ctx *qp_ctx)
142562306a36Sopenharmony_ci{
142662306a36Sopenharmony_ci	struct sec_req *backlog_req = NULL;
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	spin_lock_bh(&qp_ctx->req_lock);
142962306a36Sopenharmony_ci	if (ctx->fake_req_limit >=
143062306a36Sopenharmony_ci	    atomic_read(&qp_ctx->qp->qp_status.used) &&
143162306a36Sopenharmony_ci	    !list_empty(&qp_ctx->backlog)) {
143262306a36Sopenharmony_ci		backlog_req = list_first_entry(&qp_ctx->backlog,
143362306a36Sopenharmony_ci				typeof(*backlog_req), backlog_head);
143462306a36Sopenharmony_ci		list_del(&backlog_req->backlog_head);
143562306a36Sopenharmony_ci	}
143662306a36Sopenharmony_ci	spin_unlock_bh(&qp_ctx->req_lock);
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	return backlog_req;
143962306a36Sopenharmony_ci}
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_cistatic void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req,
144262306a36Sopenharmony_ci				  int err)
144362306a36Sopenharmony_ci{
144462306a36Sopenharmony_ci	struct skcipher_request *sk_req = req->c_req.sk_req;
144562306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
144662306a36Sopenharmony_ci	struct skcipher_request *backlog_sk_req;
144762306a36Sopenharmony_ci	struct sec_req *backlog_req;
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	sec_free_req_id(req);
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci	/* IV output at encrypto of CBC/CTR mode */
145262306a36Sopenharmony_ci	if (!err && (ctx->c_ctx.c_mode == SEC_CMODE_CBC ||
145362306a36Sopenharmony_ci	    ctx->c_ctx.c_mode == SEC_CMODE_CTR) && req->c_req.encrypt)
145462306a36Sopenharmony_ci		sec_update_iv(req, SEC_SKCIPHER);
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci	while (1) {
145762306a36Sopenharmony_ci		backlog_req = sec_back_req_clear(ctx, qp_ctx);
145862306a36Sopenharmony_ci		if (!backlog_req)
145962306a36Sopenharmony_ci			break;
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci		backlog_sk_req = backlog_req->c_req.sk_req;
146262306a36Sopenharmony_ci		skcipher_request_complete(backlog_sk_req, -EINPROGRESS);
146362306a36Sopenharmony_ci		atomic64_inc(&ctx->sec->debug.dfx.recv_busy_cnt);
146462306a36Sopenharmony_ci	}
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	skcipher_request_complete(sk_req, err);
146762306a36Sopenharmony_ci}
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_cistatic void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req)
147062306a36Sopenharmony_ci{
147162306a36Sopenharmony_ci	struct aead_request *aead_req = req->aead_req.aead_req;
147262306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
147362306a36Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
147462306a36Sopenharmony_ci	size_t authsize = ctx->a_ctx.mac_len;
147562306a36Sopenharmony_ci	u32 data_size = aead_req->cryptlen;
147662306a36Sopenharmony_ci	u8 flage = 0;
147762306a36Sopenharmony_ci	u8 cm, cl;
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	/* the specification has been checked in aead_iv_demension_check() */
148062306a36Sopenharmony_ci	cl = c_req->c_ivin[0] + 1;
148162306a36Sopenharmony_ci	c_req->c_ivin[ctx->c_ctx.ivsize - cl] = 0x00;
148262306a36Sopenharmony_ci	memset(&c_req->c_ivin[ctx->c_ctx.ivsize - cl], 0, cl);
148362306a36Sopenharmony_ci	c_req->c_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE1] = IV_CTR_INIT;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	/* the last 3bit is L' */
148662306a36Sopenharmony_ci	flage |= c_req->c_ivin[0] & IV_CL_MASK;
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	/* the M' is bit3~bit5, the Flags is bit6 */
148962306a36Sopenharmony_ci	cm = (authsize - IV_CM_CAL_NUM) / IV_CM_CAL_NUM;
149062306a36Sopenharmony_ci	flage |= cm << IV_CM_OFFSET;
149162306a36Sopenharmony_ci	if (aead_req->assoclen)
149262306a36Sopenharmony_ci		flage |= 0x01 << IV_FLAGS_OFFSET;
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	memcpy(a_req->a_ivin, c_req->c_ivin, ctx->c_ctx.ivsize);
149562306a36Sopenharmony_ci	a_req->a_ivin[0] = flage;
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	/*
149862306a36Sopenharmony_ci	 * the last 32bit is counter's initial number,
149962306a36Sopenharmony_ci	 * but the nonce uses the first 16bit
150062306a36Sopenharmony_ci	 * the tail 16bit fill with the cipher length
150162306a36Sopenharmony_ci	 */
150262306a36Sopenharmony_ci	if (!c_req->encrypt)
150362306a36Sopenharmony_ci		data_size = aead_req->cryptlen - authsize;
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE1] =
150662306a36Sopenharmony_ci			data_size & IV_LAST_BYTE_MASK;
150762306a36Sopenharmony_ci	data_size >>= IV_BYTE_OFFSET;
150862306a36Sopenharmony_ci	a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE2] =
150962306a36Sopenharmony_ci			data_size & IV_LAST_BYTE_MASK;
151062306a36Sopenharmony_ci}
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_cistatic void sec_aead_set_iv(struct sec_ctx *ctx, struct sec_req *req)
151362306a36Sopenharmony_ci{
151462306a36Sopenharmony_ci	struct aead_request *aead_req = req->aead_req.aead_req;
151562306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
151662306a36Sopenharmony_ci	size_t authsize = crypto_aead_authsize(tfm);
151762306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
151862306a36Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	memcpy(c_req->c_ivin, aead_req->iv, ctx->c_ctx.ivsize);
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_ci	if (ctx->c_ctx.c_mode == SEC_CMODE_CCM) {
152362306a36Sopenharmony_ci		/*
152462306a36Sopenharmony_ci		 * CCM 16Byte Cipher_IV: {1B_Flage,13B_IV,2B_counter},
152562306a36Sopenharmony_ci		 * the  counter must set to 0x01
152662306a36Sopenharmony_ci		 */
152762306a36Sopenharmony_ci		ctx->a_ctx.mac_len = authsize;
152862306a36Sopenharmony_ci		/* CCM 16Byte Auth_IV: {1B_AFlage,13B_IV,2B_Ptext_length} */
152962306a36Sopenharmony_ci		set_aead_auth_iv(ctx, req);
153062306a36Sopenharmony_ci	}
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	/* GCM 12Byte Cipher_IV == Auth_IV */
153362306a36Sopenharmony_ci	if (ctx->c_ctx.c_mode == SEC_CMODE_GCM) {
153462306a36Sopenharmony_ci		ctx->a_ctx.mac_len = authsize;
153562306a36Sopenharmony_ci		memcpy(a_req->a_ivin, c_req->c_ivin, SEC_AIV_SIZE);
153662306a36Sopenharmony_ci	}
153762306a36Sopenharmony_ci}
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_cistatic void sec_auth_bd_fill_xcm(struct sec_auth_ctx *ctx, int dir,
154062306a36Sopenharmony_ci				 struct sec_req *req, struct sec_sqe *sec_sqe)
154162306a36Sopenharmony_ci{
154262306a36Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
154362306a36Sopenharmony_ci	struct aead_request *aq = a_req->aead_req;
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci	/* C_ICV_Len is MAC size, 0x4 ~ 0x10 */
154662306a36Sopenharmony_ci	sec_sqe->type2.icvw_kmode |= cpu_to_le16((u16)ctx->mac_len);
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	/* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */
154962306a36Sopenharmony_ci	sec_sqe->type2.a_key_addr = sec_sqe->type2.c_key_addr;
155062306a36Sopenharmony_ci	sec_sqe->type2.a_ivin_addr = cpu_to_le64(a_req->a_ivin_dma);
155162306a36Sopenharmony_ci	sec_sqe->type_cipher_auth |= SEC_NO_AUTH << SEC_AUTH_OFFSET;
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci	if (dir)
155462306a36Sopenharmony_ci		sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH;
155562306a36Sopenharmony_ci	else
155662306a36Sopenharmony_ci		sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER;
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	sec_sqe->type2.alen_ivllen = cpu_to_le32(aq->assoclen);
155962306a36Sopenharmony_ci	sec_sqe->type2.auth_src_offset = cpu_to_le16(0x0);
156062306a36Sopenharmony_ci	sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	sec_sqe->type2.mac_addr = cpu_to_le64(a_req->out_mac_dma);
156362306a36Sopenharmony_ci}
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_cistatic void sec_auth_bd_fill_xcm_v3(struct sec_auth_ctx *ctx, int dir,
156662306a36Sopenharmony_ci				    struct sec_req *req, struct sec_sqe3 *sqe3)
156762306a36Sopenharmony_ci{
156862306a36Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
156962306a36Sopenharmony_ci	struct aead_request *aq = a_req->aead_req;
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	/* C_ICV_Len is MAC size, 0x4 ~ 0x10 */
157262306a36Sopenharmony_ci	sqe3->c_icv_key |= cpu_to_le16((u16)ctx->mac_len << SEC_MAC_OFFSET_V3);
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci	/* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */
157562306a36Sopenharmony_ci	sqe3->a_key_addr = sqe3->c_key_addr;
157662306a36Sopenharmony_ci	sqe3->auth_ivin.a_ivin_addr = cpu_to_le64(a_req->a_ivin_dma);
157762306a36Sopenharmony_ci	sqe3->auth_mac_key |= SEC_NO_AUTH;
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	if (dir)
158062306a36Sopenharmony_ci		sqe3->huk_iv_seq &= SEC_CIPHER_AUTH_V3;
158162306a36Sopenharmony_ci	else
158262306a36Sopenharmony_ci		sqe3->huk_iv_seq |= SEC_AUTH_CIPHER_V3;
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	sqe3->a_len_key = cpu_to_le32(aq->assoclen);
158562306a36Sopenharmony_ci	sqe3->auth_src_offset = cpu_to_le16(0x0);
158662306a36Sopenharmony_ci	sqe3->cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
158762306a36Sopenharmony_ci	sqe3->mac_addr = cpu_to_le64(a_req->out_mac_dma);
158862306a36Sopenharmony_ci}
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_cistatic void sec_auth_bd_fill_ex(struct sec_auth_ctx *ctx, int dir,
159162306a36Sopenharmony_ci			       struct sec_req *req, struct sec_sqe *sec_sqe)
159262306a36Sopenharmony_ci{
159362306a36Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
159462306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
159562306a36Sopenharmony_ci	struct aead_request *aq = a_req->aead_req;
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma);
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci	sec_sqe->type2.mac_key_alg =
160062306a36Sopenharmony_ci			cpu_to_le32(ctx->mac_len / SEC_SQE_LEN_RATE);
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ci	sec_sqe->type2.mac_key_alg |=
160362306a36Sopenharmony_ci			cpu_to_le32((u32)((ctx->a_key_len) /
160462306a36Sopenharmony_ci			SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET);
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	sec_sqe->type2.mac_key_alg |=
160762306a36Sopenharmony_ci			cpu_to_le32((u32)(ctx->a_alg) << SEC_AEAD_ALG_OFFSET);
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	if (dir) {
161062306a36Sopenharmony_ci		sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE1 << SEC_AUTH_OFFSET;
161162306a36Sopenharmony_ci		sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH;
161262306a36Sopenharmony_ci	} else {
161362306a36Sopenharmony_ci		sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE2 << SEC_AUTH_OFFSET;
161462306a36Sopenharmony_ci		sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER;
161562306a36Sopenharmony_ci	}
161662306a36Sopenharmony_ci	sec_sqe->type2.alen_ivllen = cpu_to_le32(c_req->c_len + aq->assoclen);
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_ci	sec_sqe->type2.mac_addr = cpu_to_le64(a_req->out_mac_dma);
162162306a36Sopenharmony_ci}
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_cistatic int sec_aead_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
162462306a36Sopenharmony_ci{
162562306a36Sopenharmony_ci	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
162662306a36Sopenharmony_ci	struct sec_sqe *sec_sqe = &req->sec_sqe;
162762306a36Sopenharmony_ci	int ret;
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	ret = sec_skcipher_bd_fill(ctx, req);
163062306a36Sopenharmony_ci	if (unlikely(ret)) {
163162306a36Sopenharmony_ci		dev_err(ctx->dev, "skcipher bd fill is error!\n");
163262306a36Sopenharmony_ci		return ret;
163362306a36Sopenharmony_ci	}
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci	if (ctx->c_ctx.c_mode == SEC_CMODE_CCM ||
163662306a36Sopenharmony_ci	    ctx->c_ctx.c_mode == SEC_CMODE_GCM)
163762306a36Sopenharmony_ci		sec_auth_bd_fill_xcm(auth_ctx, req->c_req.encrypt, req, sec_sqe);
163862306a36Sopenharmony_ci	else
163962306a36Sopenharmony_ci		sec_auth_bd_fill_ex(auth_ctx, req->c_req.encrypt, req, sec_sqe);
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	return 0;
164262306a36Sopenharmony_ci}
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_cistatic void sec_auth_bd_fill_ex_v3(struct sec_auth_ctx *ctx, int dir,
164562306a36Sopenharmony_ci				   struct sec_req *req, struct sec_sqe3 *sqe3)
164662306a36Sopenharmony_ci{
164762306a36Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
164862306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
164962306a36Sopenharmony_ci	struct aead_request *aq = a_req->aead_req;
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	sqe3->a_key_addr = cpu_to_le64(ctx->a_key_dma);
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci	sqe3->auth_mac_key |=
165462306a36Sopenharmony_ci			cpu_to_le32((u32)(ctx->mac_len /
165562306a36Sopenharmony_ci			SEC_SQE_LEN_RATE) << SEC_MAC_OFFSET_V3);
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci	sqe3->auth_mac_key |=
165862306a36Sopenharmony_ci			cpu_to_le32((u32)(ctx->a_key_len /
165962306a36Sopenharmony_ci			SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET_V3);
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	sqe3->auth_mac_key |=
166262306a36Sopenharmony_ci			cpu_to_le32((u32)(ctx->a_alg) << SEC_AUTH_ALG_OFFSET_V3);
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci	if (dir) {
166562306a36Sopenharmony_ci		sqe3->auth_mac_key |= cpu_to_le32((u32)SEC_AUTH_TYPE1);
166662306a36Sopenharmony_ci		sqe3->huk_iv_seq &= SEC_CIPHER_AUTH_V3;
166762306a36Sopenharmony_ci	} else {
166862306a36Sopenharmony_ci		sqe3->auth_mac_key |= cpu_to_le32((u32)SEC_AUTH_TYPE2);
166962306a36Sopenharmony_ci		sqe3->huk_iv_seq |= SEC_AUTH_CIPHER_V3;
167062306a36Sopenharmony_ci	}
167162306a36Sopenharmony_ci	sqe3->a_len_key = cpu_to_le32(c_req->c_len + aq->assoclen);
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	sqe3->cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	sqe3->mac_addr = cpu_to_le64(a_req->out_mac_dma);
167662306a36Sopenharmony_ci}
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_cistatic int sec_aead_bd_fill_v3(struct sec_ctx *ctx, struct sec_req *req)
167962306a36Sopenharmony_ci{
168062306a36Sopenharmony_ci	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
168162306a36Sopenharmony_ci	struct sec_sqe3 *sec_sqe3 = &req->sec_sqe3;
168262306a36Sopenharmony_ci	int ret;
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	ret = sec_skcipher_bd_fill_v3(ctx, req);
168562306a36Sopenharmony_ci	if (unlikely(ret)) {
168662306a36Sopenharmony_ci		dev_err(ctx->dev, "skcipher bd3 fill is error!\n");
168762306a36Sopenharmony_ci		return ret;
168862306a36Sopenharmony_ci	}
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	if (ctx->c_ctx.c_mode == SEC_CMODE_CCM ||
169162306a36Sopenharmony_ci	    ctx->c_ctx.c_mode == SEC_CMODE_GCM)
169262306a36Sopenharmony_ci		sec_auth_bd_fill_xcm_v3(auth_ctx, req->c_req.encrypt,
169362306a36Sopenharmony_ci					req, sec_sqe3);
169462306a36Sopenharmony_ci	else
169562306a36Sopenharmony_ci		sec_auth_bd_fill_ex_v3(auth_ctx, req->c_req.encrypt,
169662306a36Sopenharmony_ci				       req, sec_sqe3);
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci	return 0;
169962306a36Sopenharmony_ci}
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_cistatic void sec_aead_callback(struct sec_ctx *c, struct sec_req *req, int err)
170262306a36Sopenharmony_ci{
170362306a36Sopenharmony_ci	struct aead_request *a_req = req->aead_req.aead_req;
170462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
170562306a36Sopenharmony_ci	struct sec_aead_req *aead_req = &req->aead_req;
170662306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
170762306a36Sopenharmony_ci	size_t authsize = crypto_aead_authsize(tfm);
170862306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
170962306a36Sopenharmony_ci	struct aead_request *backlog_aead_req;
171062306a36Sopenharmony_ci	struct sec_req *backlog_req;
171162306a36Sopenharmony_ci	size_t sz;
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	if (!err && c->c_ctx.c_mode == SEC_CMODE_CBC && c_req->encrypt)
171462306a36Sopenharmony_ci		sec_update_iv(req, SEC_AEAD);
171562306a36Sopenharmony_ci
171662306a36Sopenharmony_ci	/* Copy output mac */
171762306a36Sopenharmony_ci	if (!err && c_req->encrypt) {
171862306a36Sopenharmony_ci		struct scatterlist *sgl = a_req->dst;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci		sz = sg_pcopy_from_buffer(sgl, sg_nents(sgl),
172162306a36Sopenharmony_ci					  aead_req->out_mac,
172262306a36Sopenharmony_ci					  authsize, a_req->cryptlen +
172362306a36Sopenharmony_ci					  a_req->assoclen);
172462306a36Sopenharmony_ci		if (unlikely(sz != authsize)) {
172562306a36Sopenharmony_ci			dev_err(c->dev, "copy out mac err!\n");
172662306a36Sopenharmony_ci			err = -EINVAL;
172762306a36Sopenharmony_ci		}
172862306a36Sopenharmony_ci	}
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	sec_free_req_id(req);
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci	while (1) {
173362306a36Sopenharmony_ci		backlog_req = sec_back_req_clear(c, qp_ctx);
173462306a36Sopenharmony_ci		if (!backlog_req)
173562306a36Sopenharmony_ci			break;
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci		backlog_aead_req = backlog_req->aead_req.aead_req;
173862306a36Sopenharmony_ci		aead_request_complete(backlog_aead_req, -EINPROGRESS);
173962306a36Sopenharmony_ci		atomic64_inc(&c->sec->debug.dfx.recv_busy_cnt);
174062306a36Sopenharmony_ci	}
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci	aead_request_complete(a_req, err);
174362306a36Sopenharmony_ci}
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_cistatic void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req)
174662306a36Sopenharmony_ci{
174762306a36Sopenharmony_ci	sec_free_req_id(req);
174862306a36Sopenharmony_ci	sec_free_queue_id(ctx, req);
174962306a36Sopenharmony_ci}
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_cistatic int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
175262306a36Sopenharmony_ci{
175362306a36Sopenharmony_ci	struct sec_qp_ctx *qp_ctx;
175462306a36Sopenharmony_ci	int queue_id;
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	/* To load balance */
175762306a36Sopenharmony_ci	queue_id = sec_alloc_queue_id(ctx, req);
175862306a36Sopenharmony_ci	qp_ctx = &ctx->qp_ctx[queue_id];
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	req->req_id = sec_alloc_req_id(req, qp_ctx);
176162306a36Sopenharmony_ci	if (unlikely(req->req_id < 0)) {
176262306a36Sopenharmony_ci		sec_free_queue_id(ctx, req);
176362306a36Sopenharmony_ci		return req->req_id;
176462306a36Sopenharmony_ci	}
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	return 0;
176762306a36Sopenharmony_ci}
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_cistatic int sec_process(struct sec_ctx *ctx, struct sec_req *req)
177062306a36Sopenharmony_ci{
177162306a36Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
177262306a36Sopenharmony_ci	int ret;
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci	ret = sec_request_init(ctx, req);
177562306a36Sopenharmony_ci	if (unlikely(ret))
177662306a36Sopenharmony_ci		return ret;
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	ret = sec_request_transfer(ctx, req);
177962306a36Sopenharmony_ci	if (unlikely(ret))
178062306a36Sopenharmony_ci		goto err_uninit_req;
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci	/* Output IV as decrypto */
178362306a36Sopenharmony_ci	if (!req->c_req.encrypt && (ctx->c_ctx.c_mode == SEC_CMODE_CBC ||
178462306a36Sopenharmony_ci	    ctx->c_ctx.c_mode == SEC_CMODE_CTR))
178562306a36Sopenharmony_ci		sec_update_iv(req, ctx->alg_type);
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	ret = ctx->req_op->bd_send(ctx, req);
178862306a36Sopenharmony_ci	if (unlikely((ret != -EBUSY && ret != -EINPROGRESS) ||
178962306a36Sopenharmony_ci		(ret == -EBUSY && !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
179062306a36Sopenharmony_ci		dev_err_ratelimited(ctx->dev, "send sec request failed!\n");
179162306a36Sopenharmony_ci		goto err_send_req;
179262306a36Sopenharmony_ci	}
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci	return ret;
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_cierr_send_req:
179762306a36Sopenharmony_ci	/* As failing, restore the IV from user */
179862306a36Sopenharmony_ci	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) {
179962306a36Sopenharmony_ci		if (ctx->alg_type == SEC_SKCIPHER)
180062306a36Sopenharmony_ci			memcpy(req->c_req.sk_req->iv, c_req->c_ivin,
180162306a36Sopenharmony_ci			       ctx->c_ctx.ivsize);
180262306a36Sopenharmony_ci		else
180362306a36Sopenharmony_ci			memcpy(req->aead_req.aead_req->iv, c_req->c_ivin,
180462306a36Sopenharmony_ci			       ctx->c_ctx.ivsize);
180562306a36Sopenharmony_ci	}
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	sec_request_untransfer(ctx, req);
180862306a36Sopenharmony_cierr_uninit_req:
180962306a36Sopenharmony_ci	sec_request_uninit(ctx, req);
181062306a36Sopenharmony_ci	return ret;
181162306a36Sopenharmony_ci}
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_cistatic const struct sec_req_op sec_skcipher_req_ops = {
181462306a36Sopenharmony_ci	.buf_map	= sec_skcipher_sgl_map,
181562306a36Sopenharmony_ci	.buf_unmap	= sec_skcipher_sgl_unmap,
181662306a36Sopenharmony_ci	.do_transfer	= sec_skcipher_copy_iv,
181762306a36Sopenharmony_ci	.bd_fill	= sec_skcipher_bd_fill,
181862306a36Sopenharmony_ci	.bd_send	= sec_bd_send,
181962306a36Sopenharmony_ci	.callback	= sec_skcipher_callback,
182062306a36Sopenharmony_ci	.process	= sec_process,
182162306a36Sopenharmony_ci};
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_cistatic const struct sec_req_op sec_aead_req_ops = {
182462306a36Sopenharmony_ci	.buf_map	= sec_aead_sgl_map,
182562306a36Sopenharmony_ci	.buf_unmap	= sec_aead_sgl_unmap,
182662306a36Sopenharmony_ci	.do_transfer	= sec_aead_set_iv,
182762306a36Sopenharmony_ci	.bd_fill	= sec_aead_bd_fill,
182862306a36Sopenharmony_ci	.bd_send	= sec_bd_send,
182962306a36Sopenharmony_ci	.callback	= sec_aead_callback,
183062306a36Sopenharmony_ci	.process	= sec_process,
183162306a36Sopenharmony_ci};
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_cistatic const struct sec_req_op sec_skcipher_req_ops_v3 = {
183462306a36Sopenharmony_ci	.buf_map	= sec_skcipher_sgl_map,
183562306a36Sopenharmony_ci	.buf_unmap	= sec_skcipher_sgl_unmap,
183662306a36Sopenharmony_ci	.do_transfer	= sec_skcipher_copy_iv,
183762306a36Sopenharmony_ci	.bd_fill	= sec_skcipher_bd_fill_v3,
183862306a36Sopenharmony_ci	.bd_send	= sec_bd_send,
183962306a36Sopenharmony_ci	.callback	= sec_skcipher_callback,
184062306a36Sopenharmony_ci	.process	= sec_process,
184162306a36Sopenharmony_ci};
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_cistatic const struct sec_req_op sec_aead_req_ops_v3 = {
184462306a36Sopenharmony_ci	.buf_map	= sec_aead_sgl_map,
184562306a36Sopenharmony_ci	.buf_unmap	= sec_aead_sgl_unmap,
184662306a36Sopenharmony_ci	.do_transfer	= sec_aead_set_iv,
184762306a36Sopenharmony_ci	.bd_fill	= sec_aead_bd_fill_v3,
184862306a36Sopenharmony_ci	.bd_send	= sec_bd_send,
184962306a36Sopenharmony_ci	.callback	= sec_aead_callback,
185062306a36Sopenharmony_ci	.process	= sec_process,
185162306a36Sopenharmony_ci};
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_cistatic int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
185462306a36Sopenharmony_ci{
185562306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
185662306a36Sopenharmony_ci	int ret;
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci	ret = sec_skcipher_init(tfm);
185962306a36Sopenharmony_ci	if (ret)
186062306a36Sopenharmony_ci		return ret;
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ci	if (ctx->sec->qm.ver < QM_HW_V3) {
186362306a36Sopenharmony_ci		ctx->type_supported = SEC_BD_TYPE2;
186462306a36Sopenharmony_ci		ctx->req_op = &sec_skcipher_req_ops;
186562306a36Sopenharmony_ci	} else {
186662306a36Sopenharmony_ci		ctx->type_supported = SEC_BD_TYPE3;
186762306a36Sopenharmony_ci		ctx->req_op = &sec_skcipher_req_ops_v3;
186862306a36Sopenharmony_ci	}
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_ci	return ret;
187162306a36Sopenharmony_ci}
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_cistatic void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm)
187462306a36Sopenharmony_ci{
187562306a36Sopenharmony_ci	sec_skcipher_uninit(tfm);
187662306a36Sopenharmony_ci}
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_cistatic int sec_aead_init(struct crypto_aead *tfm)
187962306a36Sopenharmony_ci{
188062306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
188162306a36Sopenharmony_ci	int ret;
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci	crypto_aead_set_reqsize(tfm, sizeof(struct sec_req));
188462306a36Sopenharmony_ci	ctx->alg_type = SEC_AEAD;
188562306a36Sopenharmony_ci	ctx->c_ctx.ivsize = crypto_aead_ivsize(tfm);
188662306a36Sopenharmony_ci	if (ctx->c_ctx.ivsize < SEC_AIV_SIZE ||
188762306a36Sopenharmony_ci	    ctx->c_ctx.ivsize > SEC_IV_SIZE) {
188862306a36Sopenharmony_ci		pr_err("get error aead iv size!\n");
188962306a36Sopenharmony_ci		return -EINVAL;
189062306a36Sopenharmony_ci	}
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	ret = sec_ctx_base_init(ctx);
189362306a36Sopenharmony_ci	if (ret)
189462306a36Sopenharmony_ci		return ret;
189562306a36Sopenharmony_ci	if (ctx->sec->qm.ver < QM_HW_V3) {
189662306a36Sopenharmony_ci		ctx->type_supported = SEC_BD_TYPE2;
189762306a36Sopenharmony_ci		ctx->req_op = &sec_aead_req_ops;
189862306a36Sopenharmony_ci	} else {
189962306a36Sopenharmony_ci		ctx->type_supported = SEC_BD_TYPE3;
190062306a36Sopenharmony_ci		ctx->req_op = &sec_aead_req_ops_v3;
190162306a36Sopenharmony_ci	}
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	ret = sec_auth_init(ctx);
190462306a36Sopenharmony_ci	if (ret)
190562306a36Sopenharmony_ci		goto err_auth_init;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	ret = sec_cipher_init(ctx);
190862306a36Sopenharmony_ci	if (ret)
190962306a36Sopenharmony_ci		goto err_cipher_init;
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci	return ret;
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_cierr_cipher_init:
191462306a36Sopenharmony_ci	sec_auth_uninit(ctx);
191562306a36Sopenharmony_cierr_auth_init:
191662306a36Sopenharmony_ci	sec_ctx_base_uninit(ctx);
191762306a36Sopenharmony_ci	return ret;
191862306a36Sopenharmony_ci}
191962306a36Sopenharmony_ci
192062306a36Sopenharmony_cistatic void sec_aead_exit(struct crypto_aead *tfm)
192162306a36Sopenharmony_ci{
192262306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	sec_cipher_uninit(ctx);
192562306a36Sopenharmony_ci	sec_auth_uninit(ctx);
192662306a36Sopenharmony_ci	sec_ctx_base_uninit(ctx);
192762306a36Sopenharmony_ci}
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_cistatic int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name)
193062306a36Sopenharmony_ci{
193162306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
193262306a36Sopenharmony_ci	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
193362306a36Sopenharmony_ci	int ret;
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci	ret = sec_aead_init(tfm);
193662306a36Sopenharmony_ci	if (ret) {
193762306a36Sopenharmony_ci		pr_err("hisi_sec2: aead init error!\n");
193862306a36Sopenharmony_ci		return ret;
193962306a36Sopenharmony_ci	}
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci	auth_ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
194262306a36Sopenharmony_ci	if (IS_ERR(auth_ctx->hash_tfm)) {
194362306a36Sopenharmony_ci		dev_err(ctx->dev, "aead alloc shash error!\n");
194462306a36Sopenharmony_ci		sec_aead_exit(tfm);
194562306a36Sopenharmony_ci		return PTR_ERR(auth_ctx->hash_tfm);
194662306a36Sopenharmony_ci	}
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	return 0;
194962306a36Sopenharmony_ci}
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_cistatic void sec_aead_ctx_exit(struct crypto_aead *tfm)
195262306a36Sopenharmony_ci{
195362306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
195462306a36Sopenharmony_ci
195562306a36Sopenharmony_ci	crypto_free_shash(ctx->a_ctx.hash_tfm);
195662306a36Sopenharmony_ci	sec_aead_exit(tfm);
195762306a36Sopenharmony_ci}
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_cistatic int sec_aead_xcm_ctx_init(struct crypto_aead *tfm)
196062306a36Sopenharmony_ci{
196162306a36Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(tfm);
196262306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
196362306a36Sopenharmony_ci	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
196462306a36Sopenharmony_ci	const char *aead_name = alg->base.cra_name;
196562306a36Sopenharmony_ci	int ret;
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	ret = sec_aead_init(tfm);
196862306a36Sopenharmony_ci	if (ret) {
196962306a36Sopenharmony_ci		dev_err(ctx->dev, "hisi_sec2: aead xcm init error!\n");
197062306a36Sopenharmony_ci		return ret;
197162306a36Sopenharmony_ci	}
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci	a_ctx->fallback_aead_tfm = crypto_alloc_aead(aead_name, 0,
197462306a36Sopenharmony_ci						     CRYPTO_ALG_NEED_FALLBACK |
197562306a36Sopenharmony_ci						     CRYPTO_ALG_ASYNC);
197662306a36Sopenharmony_ci	if (IS_ERR(a_ctx->fallback_aead_tfm)) {
197762306a36Sopenharmony_ci		dev_err(ctx->dev, "aead driver alloc fallback tfm error!\n");
197862306a36Sopenharmony_ci		sec_aead_exit(tfm);
197962306a36Sopenharmony_ci		return PTR_ERR(a_ctx->fallback_aead_tfm);
198062306a36Sopenharmony_ci	}
198162306a36Sopenharmony_ci	a_ctx->fallback = false;
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci	return 0;
198462306a36Sopenharmony_ci}
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_cistatic void sec_aead_xcm_ctx_exit(struct crypto_aead *tfm)
198762306a36Sopenharmony_ci{
198862306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci	crypto_free_aead(ctx->a_ctx.fallback_aead_tfm);
199162306a36Sopenharmony_ci	sec_aead_exit(tfm);
199262306a36Sopenharmony_ci}
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_cistatic int sec_aead_sha1_ctx_init(struct crypto_aead *tfm)
199562306a36Sopenharmony_ci{
199662306a36Sopenharmony_ci	return sec_aead_ctx_init(tfm, "sha1");
199762306a36Sopenharmony_ci}
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_cistatic int sec_aead_sha256_ctx_init(struct crypto_aead *tfm)
200062306a36Sopenharmony_ci{
200162306a36Sopenharmony_ci	return sec_aead_ctx_init(tfm, "sha256");
200262306a36Sopenharmony_ci}
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_cistatic int sec_aead_sha512_ctx_init(struct crypto_aead *tfm)
200562306a36Sopenharmony_ci{
200662306a36Sopenharmony_ci	return sec_aead_ctx_init(tfm, "sha512");
200762306a36Sopenharmony_ci}
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_cistatic int sec_skcipher_cryptlen_check(struct sec_ctx *ctx,
201062306a36Sopenharmony_ci	struct sec_req *sreq)
201162306a36Sopenharmony_ci{
201262306a36Sopenharmony_ci	u32 cryptlen = sreq->c_req.sk_req->cryptlen;
201362306a36Sopenharmony_ci	struct device *dev = ctx->dev;
201462306a36Sopenharmony_ci	u8 c_mode = ctx->c_ctx.c_mode;
201562306a36Sopenharmony_ci	int ret = 0;
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	switch (c_mode) {
201862306a36Sopenharmony_ci	case SEC_CMODE_XTS:
201962306a36Sopenharmony_ci		if (unlikely(cryptlen < AES_BLOCK_SIZE)) {
202062306a36Sopenharmony_ci			dev_err(dev, "skcipher XTS mode input length error!\n");
202162306a36Sopenharmony_ci			ret = -EINVAL;
202262306a36Sopenharmony_ci		}
202362306a36Sopenharmony_ci		break;
202462306a36Sopenharmony_ci	case SEC_CMODE_ECB:
202562306a36Sopenharmony_ci	case SEC_CMODE_CBC:
202662306a36Sopenharmony_ci		if (unlikely(cryptlen & (AES_BLOCK_SIZE - 1))) {
202762306a36Sopenharmony_ci			dev_err(dev, "skcipher AES input length error!\n");
202862306a36Sopenharmony_ci			ret = -EINVAL;
202962306a36Sopenharmony_ci		}
203062306a36Sopenharmony_ci		break;
203162306a36Sopenharmony_ci	case SEC_CMODE_CFB:
203262306a36Sopenharmony_ci	case SEC_CMODE_OFB:
203362306a36Sopenharmony_ci	case SEC_CMODE_CTR:
203462306a36Sopenharmony_ci		if (unlikely(ctx->sec->qm.ver < QM_HW_V3)) {
203562306a36Sopenharmony_ci			dev_err(dev, "skcipher HW version error!\n");
203662306a36Sopenharmony_ci			ret = -EINVAL;
203762306a36Sopenharmony_ci		}
203862306a36Sopenharmony_ci		break;
203962306a36Sopenharmony_ci	default:
204062306a36Sopenharmony_ci		ret = -EINVAL;
204162306a36Sopenharmony_ci	}
204262306a36Sopenharmony_ci
204362306a36Sopenharmony_ci	return ret;
204462306a36Sopenharmony_ci}
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_cistatic int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
204762306a36Sopenharmony_ci{
204862306a36Sopenharmony_ci	struct skcipher_request *sk_req = sreq->c_req.sk_req;
204962306a36Sopenharmony_ci	struct device *dev = ctx->dev;
205062306a36Sopenharmony_ci	u8 c_alg = ctx->c_ctx.c_alg;
205162306a36Sopenharmony_ci
205262306a36Sopenharmony_ci	if (unlikely(!sk_req->src || !sk_req->dst ||
205362306a36Sopenharmony_ci		     sk_req->cryptlen > MAX_INPUT_DATA_LEN)) {
205462306a36Sopenharmony_ci		dev_err(dev, "skcipher input param error!\n");
205562306a36Sopenharmony_ci		return -EINVAL;
205662306a36Sopenharmony_ci	}
205762306a36Sopenharmony_ci	sreq->c_req.c_len = sk_req->cryptlen;
205862306a36Sopenharmony_ci
205962306a36Sopenharmony_ci	if (ctx->pbuf_supported && sk_req->cryptlen <= SEC_PBUF_SZ)
206062306a36Sopenharmony_ci		sreq->use_pbuf = true;
206162306a36Sopenharmony_ci	else
206262306a36Sopenharmony_ci		sreq->use_pbuf = false;
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	if (c_alg == SEC_CALG_3DES) {
206562306a36Sopenharmony_ci		if (unlikely(sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1))) {
206662306a36Sopenharmony_ci			dev_err(dev, "skcipher 3des input length error!\n");
206762306a36Sopenharmony_ci			return -EINVAL;
206862306a36Sopenharmony_ci		}
206962306a36Sopenharmony_ci		return 0;
207062306a36Sopenharmony_ci	} else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) {
207162306a36Sopenharmony_ci		return sec_skcipher_cryptlen_check(ctx, sreq);
207262306a36Sopenharmony_ci	}
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ci	dev_err(dev, "skcipher algorithm error!\n");
207562306a36Sopenharmony_ci
207662306a36Sopenharmony_ci	return -EINVAL;
207762306a36Sopenharmony_ci}
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_cistatic int sec_skcipher_soft_crypto(struct sec_ctx *ctx,
208062306a36Sopenharmony_ci				    struct skcipher_request *sreq, bool encrypt)
208162306a36Sopenharmony_ci{
208262306a36Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
208362306a36Sopenharmony_ci	SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, c_ctx->fbtfm);
208462306a36Sopenharmony_ci	struct device *dev = ctx->dev;
208562306a36Sopenharmony_ci	int ret;
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	if (!c_ctx->fbtfm) {
208862306a36Sopenharmony_ci		dev_err_ratelimited(dev, "the soft tfm isn't supported in the current system.\n");
208962306a36Sopenharmony_ci		return -EINVAL;
209062306a36Sopenharmony_ci	}
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	skcipher_request_set_sync_tfm(subreq, c_ctx->fbtfm);
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci	/* software need sync mode to do crypto */
209562306a36Sopenharmony_ci	skcipher_request_set_callback(subreq, sreq->base.flags,
209662306a36Sopenharmony_ci				      NULL, NULL);
209762306a36Sopenharmony_ci	skcipher_request_set_crypt(subreq, sreq->src, sreq->dst,
209862306a36Sopenharmony_ci				   sreq->cryptlen, sreq->iv);
209962306a36Sopenharmony_ci	if (encrypt)
210062306a36Sopenharmony_ci		ret = crypto_skcipher_encrypt(subreq);
210162306a36Sopenharmony_ci	else
210262306a36Sopenharmony_ci		ret = crypto_skcipher_decrypt(subreq);
210362306a36Sopenharmony_ci
210462306a36Sopenharmony_ci	skcipher_request_zero(subreq);
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci	return ret;
210762306a36Sopenharmony_ci}
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_cistatic int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt)
211062306a36Sopenharmony_ci{
211162306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req);
211262306a36Sopenharmony_ci	struct sec_req *req = skcipher_request_ctx(sk_req);
211362306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
211462306a36Sopenharmony_ci	int ret;
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci	if (!sk_req->cryptlen) {
211762306a36Sopenharmony_ci		if (ctx->c_ctx.c_mode == SEC_CMODE_XTS)
211862306a36Sopenharmony_ci			return -EINVAL;
211962306a36Sopenharmony_ci		return 0;
212062306a36Sopenharmony_ci	}
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	req->flag = sk_req->base.flags;
212362306a36Sopenharmony_ci	req->c_req.sk_req = sk_req;
212462306a36Sopenharmony_ci	req->c_req.encrypt = encrypt;
212562306a36Sopenharmony_ci	req->ctx = ctx;
212662306a36Sopenharmony_ci
212762306a36Sopenharmony_ci	ret = sec_skcipher_param_check(ctx, req);
212862306a36Sopenharmony_ci	if (unlikely(ret))
212962306a36Sopenharmony_ci		return -EINVAL;
213062306a36Sopenharmony_ci
213162306a36Sopenharmony_ci	if (unlikely(ctx->c_ctx.fallback))
213262306a36Sopenharmony_ci		return sec_skcipher_soft_crypto(ctx, sk_req, encrypt);
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_ci	return ctx->req_op->process(ctx, req);
213562306a36Sopenharmony_ci}
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_cistatic int sec_skcipher_encrypt(struct skcipher_request *sk_req)
213862306a36Sopenharmony_ci{
213962306a36Sopenharmony_ci	return sec_skcipher_crypto(sk_req, true);
214062306a36Sopenharmony_ci}
214162306a36Sopenharmony_ci
214262306a36Sopenharmony_cistatic int sec_skcipher_decrypt(struct skcipher_request *sk_req)
214362306a36Sopenharmony_ci{
214462306a36Sopenharmony_ci	return sec_skcipher_crypto(sk_req, false);
214562306a36Sopenharmony_ci}
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci#define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \
214862306a36Sopenharmony_ci	sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\
214962306a36Sopenharmony_ci{\
215062306a36Sopenharmony_ci	.base = {\
215162306a36Sopenharmony_ci		.cra_name = sec_cra_name,\
215262306a36Sopenharmony_ci		.cra_driver_name = "hisi_sec_"sec_cra_name,\
215362306a36Sopenharmony_ci		.cra_priority = SEC_PRIORITY,\
215462306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC |\
215562306a36Sopenharmony_ci		 CRYPTO_ALG_NEED_FALLBACK,\
215662306a36Sopenharmony_ci		.cra_blocksize = blk_size,\
215762306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct sec_ctx),\
215862306a36Sopenharmony_ci		.cra_module = THIS_MODULE,\
215962306a36Sopenharmony_ci	},\
216062306a36Sopenharmony_ci	.init = ctx_init,\
216162306a36Sopenharmony_ci	.exit = ctx_exit,\
216262306a36Sopenharmony_ci	.setkey = sec_set_key,\
216362306a36Sopenharmony_ci	.decrypt = sec_skcipher_decrypt,\
216462306a36Sopenharmony_ci	.encrypt = sec_skcipher_encrypt,\
216562306a36Sopenharmony_ci	.min_keysize = sec_min_key_size,\
216662306a36Sopenharmony_ci	.max_keysize = sec_max_key_size,\
216762306a36Sopenharmony_ci	.ivsize = iv_size,\
216862306a36Sopenharmony_ci}
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci#define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \
217162306a36Sopenharmony_ci	max_key_size, blk_size, iv_size) \
217262306a36Sopenharmony_ci	SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \
217362306a36Sopenharmony_ci	sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size)
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_cistatic struct sec_skcipher sec_skciphers[] = {
217662306a36Sopenharmony_ci	{
217762306a36Sopenharmony_ci		.alg_msk = BIT(0),
217862306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb, AES_MIN_KEY_SIZE,
217962306a36Sopenharmony_ci					AES_MAX_KEY_SIZE, AES_BLOCK_SIZE, 0),
218062306a36Sopenharmony_ci	},
218162306a36Sopenharmony_ci	{
218262306a36Sopenharmony_ci		.alg_msk = BIT(1),
218362306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc, AES_MIN_KEY_SIZE,
218462306a36Sopenharmony_ci					AES_MAX_KEY_SIZE, AES_BLOCK_SIZE, AES_BLOCK_SIZE),
218562306a36Sopenharmony_ci	},
218662306a36Sopenharmony_ci	{
218762306a36Sopenharmony_ci		.alg_msk = BIT(2),
218862306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("ctr(aes)", sec_setkey_aes_ctr,	AES_MIN_KEY_SIZE,
218962306a36Sopenharmony_ci					AES_MAX_KEY_SIZE, SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE),
219062306a36Sopenharmony_ci	},
219162306a36Sopenharmony_ci	{
219262306a36Sopenharmony_ci		.alg_msk = BIT(3),
219362306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts,	SEC_XTS_MIN_KEY_SIZE,
219462306a36Sopenharmony_ci					SEC_XTS_MAX_KEY_SIZE, AES_BLOCK_SIZE, AES_BLOCK_SIZE),
219562306a36Sopenharmony_ci	},
219662306a36Sopenharmony_ci	{
219762306a36Sopenharmony_ci		.alg_msk = BIT(4),
219862306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("ofb(aes)", sec_setkey_aes_ofb,	AES_MIN_KEY_SIZE,
219962306a36Sopenharmony_ci					AES_MAX_KEY_SIZE, SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE),
220062306a36Sopenharmony_ci	},
220162306a36Sopenharmony_ci	{
220262306a36Sopenharmony_ci		.alg_msk = BIT(5),
220362306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("cfb(aes)", sec_setkey_aes_cfb,	AES_MIN_KEY_SIZE,
220462306a36Sopenharmony_ci					AES_MAX_KEY_SIZE, SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE),
220562306a36Sopenharmony_ci	},
220662306a36Sopenharmony_ci	{
220762306a36Sopenharmony_ci		.alg_msk = BIT(12),
220862306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc,	AES_MIN_KEY_SIZE,
220962306a36Sopenharmony_ci					AES_MIN_KEY_SIZE, AES_BLOCK_SIZE, AES_BLOCK_SIZE),
221062306a36Sopenharmony_ci	},
221162306a36Sopenharmony_ci	{
221262306a36Sopenharmony_ci		.alg_msk = BIT(13),
221362306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("ctr(sm4)", sec_setkey_sm4_ctr, AES_MIN_KEY_SIZE,
221462306a36Sopenharmony_ci					AES_MIN_KEY_SIZE, SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE),
221562306a36Sopenharmony_ci	},
221662306a36Sopenharmony_ci	{
221762306a36Sopenharmony_ci		.alg_msk = BIT(14),
221862306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,	SEC_XTS_MIN_KEY_SIZE,
221962306a36Sopenharmony_ci					SEC_XTS_MIN_KEY_SIZE, AES_BLOCK_SIZE, AES_BLOCK_SIZE),
222062306a36Sopenharmony_ci	},
222162306a36Sopenharmony_ci	{
222262306a36Sopenharmony_ci		.alg_msk = BIT(15),
222362306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("ofb(sm4)", sec_setkey_sm4_ofb,	AES_MIN_KEY_SIZE,
222462306a36Sopenharmony_ci					AES_MIN_KEY_SIZE, SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE),
222562306a36Sopenharmony_ci	},
222662306a36Sopenharmony_ci	{
222762306a36Sopenharmony_ci		.alg_msk = BIT(16),
222862306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("cfb(sm4)", sec_setkey_sm4_cfb,	AES_MIN_KEY_SIZE,
222962306a36Sopenharmony_ci					AES_MIN_KEY_SIZE, SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE),
223062306a36Sopenharmony_ci	},
223162306a36Sopenharmony_ci	{
223262306a36Sopenharmony_ci		.alg_msk = BIT(23),
223362306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb, SEC_DES3_3KEY_SIZE,
223462306a36Sopenharmony_ci					SEC_DES3_3KEY_SIZE, DES3_EDE_BLOCK_SIZE, 0),
223562306a36Sopenharmony_ci	},
223662306a36Sopenharmony_ci	{
223762306a36Sopenharmony_ci		.alg_msk = BIT(24),
223862306a36Sopenharmony_ci		.alg = SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc, SEC_DES3_3KEY_SIZE,
223962306a36Sopenharmony_ci					SEC_DES3_3KEY_SIZE, DES3_EDE_BLOCK_SIZE,
224062306a36Sopenharmony_ci					DES3_EDE_BLOCK_SIZE),
224162306a36Sopenharmony_ci	},
224262306a36Sopenharmony_ci};
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_cistatic int aead_iv_demension_check(struct aead_request *aead_req)
224562306a36Sopenharmony_ci{
224662306a36Sopenharmony_ci	u8 cl;
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	cl = aead_req->iv[0] + 1;
224962306a36Sopenharmony_ci	if (cl < IV_CL_MIN || cl > IV_CL_MAX)
225062306a36Sopenharmony_ci		return -EINVAL;
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci	if (cl < IV_CL_MID && aead_req->cryptlen >> (BYTE_BITS * cl))
225362306a36Sopenharmony_ci		return -EOVERFLOW;
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci	return 0;
225662306a36Sopenharmony_ci}
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_cistatic int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq)
225962306a36Sopenharmony_ci{
226062306a36Sopenharmony_ci	struct aead_request *req = sreq->aead_req.aead_req;
226162306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
226262306a36Sopenharmony_ci	size_t authsize = crypto_aead_authsize(tfm);
226362306a36Sopenharmony_ci	u8 c_mode = ctx->c_ctx.c_mode;
226462306a36Sopenharmony_ci	struct device *dev = ctx->dev;
226562306a36Sopenharmony_ci	int ret;
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	if (unlikely(req->cryptlen + req->assoclen > MAX_INPUT_DATA_LEN ||
226862306a36Sopenharmony_ci	    req->assoclen > SEC_MAX_AAD_LEN)) {
226962306a36Sopenharmony_ci		dev_err(dev, "aead input spec error!\n");
227062306a36Sopenharmony_ci		return -EINVAL;
227162306a36Sopenharmony_ci	}
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci	if (unlikely((c_mode == SEC_CMODE_GCM && authsize < DES_BLOCK_SIZE) ||
227462306a36Sopenharmony_ci	   (c_mode == SEC_CMODE_CCM && (authsize < MIN_MAC_LEN ||
227562306a36Sopenharmony_ci		authsize & MAC_LEN_MASK)))) {
227662306a36Sopenharmony_ci		dev_err(dev, "aead input mac length error!\n");
227762306a36Sopenharmony_ci		return -EINVAL;
227862306a36Sopenharmony_ci	}
227962306a36Sopenharmony_ci
228062306a36Sopenharmony_ci	if (c_mode == SEC_CMODE_CCM) {
228162306a36Sopenharmony_ci		if (unlikely(req->assoclen > SEC_MAX_CCM_AAD_LEN)) {
228262306a36Sopenharmony_ci			dev_err_ratelimited(dev, "CCM input aad parameter is too long!\n");
228362306a36Sopenharmony_ci			return -EINVAL;
228462306a36Sopenharmony_ci		}
228562306a36Sopenharmony_ci		ret = aead_iv_demension_check(req);
228662306a36Sopenharmony_ci		if (ret) {
228762306a36Sopenharmony_ci			dev_err(dev, "aead input iv param error!\n");
228862306a36Sopenharmony_ci			return ret;
228962306a36Sopenharmony_ci		}
229062306a36Sopenharmony_ci	}
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_ci	if (sreq->c_req.encrypt)
229362306a36Sopenharmony_ci		sreq->c_req.c_len = req->cryptlen;
229462306a36Sopenharmony_ci	else
229562306a36Sopenharmony_ci		sreq->c_req.c_len = req->cryptlen - authsize;
229662306a36Sopenharmony_ci	if (c_mode == SEC_CMODE_CBC) {
229762306a36Sopenharmony_ci		if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) {
229862306a36Sopenharmony_ci			dev_err(dev, "aead crypto length error!\n");
229962306a36Sopenharmony_ci			return -EINVAL;
230062306a36Sopenharmony_ci		}
230162306a36Sopenharmony_ci	}
230262306a36Sopenharmony_ci
230362306a36Sopenharmony_ci	return 0;
230462306a36Sopenharmony_ci}
230562306a36Sopenharmony_ci
230662306a36Sopenharmony_cistatic int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
230762306a36Sopenharmony_ci{
230862306a36Sopenharmony_ci	struct aead_request *req = sreq->aead_req.aead_req;
230962306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
231062306a36Sopenharmony_ci	size_t authsize = crypto_aead_authsize(tfm);
231162306a36Sopenharmony_ci	struct device *dev = ctx->dev;
231262306a36Sopenharmony_ci	u8 c_alg = ctx->c_ctx.c_alg;
231362306a36Sopenharmony_ci
231462306a36Sopenharmony_ci	if (unlikely(!req->src || !req->dst)) {
231562306a36Sopenharmony_ci		dev_err(dev, "aead input param error!\n");
231662306a36Sopenharmony_ci		return -EINVAL;
231762306a36Sopenharmony_ci	}
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci	if (ctx->sec->qm.ver == QM_HW_V2) {
232062306a36Sopenharmony_ci		if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt &&
232162306a36Sopenharmony_ci		    req->cryptlen <= authsize))) {
232262306a36Sopenharmony_ci			ctx->a_ctx.fallback = true;
232362306a36Sopenharmony_ci			return -EINVAL;
232462306a36Sopenharmony_ci		}
232562306a36Sopenharmony_ci	}
232662306a36Sopenharmony_ci
232762306a36Sopenharmony_ci	/* Support AES or SM4 */
232862306a36Sopenharmony_ci	if (unlikely(c_alg != SEC_CALG_AES && c_alg != SEC_CALG_SM4)) {
232962306a36Sopenharmony_ci		dev_err(dev, "aead crypto alg error!\n");
233062306a36Sopenharmony_ci		return -EINVAL;
233162306a36Sopenharmony_ci	}
233262306a36Sopenharmony_ci
233362306a36Sopenharmony_ci	if (unlikely(sec_aead_spec_check(ctx, sreq)))
233462306a36Sopenharmony_ci		return -EINVAL;
233562306a36Sopenharmony_ci
233662306a36Sopenharmony_ci	if (ctx->pbuf_supported && (req->cryptlen + req->assoclen) <=
233762306a36Sopenharmony_ci		SEC_PBUF_SZ)
233862306a36Sopenharmony_ci		sreq->use_pbuf = true;
233962306a36Sopenharmony_ci	else
234062306a36Sopenharmony_ci		sreq->use_pbuf = false;
234162306a36Sopenharmony_ci
234262306a36Sopenharmony_ci	return 0;
234362306a36Sopenharmony_ci}
234462306a36Sopenharmony_ci
234562306a36Sopenharmony_cistatic int sec_aead_soft_crypto(struct sec_ctx *ctx,
234662306a36Sopenharmony_ci				struct aead_request *aead_req,
234762306a36Sopenharmony_ci				bool encrypt)
234862306a36Sopenharmony_ci{
234962306a36Sopenharmony_ci	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
235062306a36Sopenharmony_ci	struct device *dev = ctx->dev;
235162306a36Sopenharmony_ci	struct aead_request *subreq;
235262306a36Sopenharmony_ci	int ret;
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ci	/* Kunpeng920 aead mode not support input 0 size */
235562306a36Sopenharmony_ci	if (!a_ctx->fallback_aead_tfm) {
235662306a36Sopenharmony_ci		dev_err(dev, "aead fallback tfm is NULL!\n");
235762306a36Sopenharmony_ci		return -EINVAL;
235862306a36Sopenharmony_ci	}
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_ci	subreq = aead_request_alloc(a_ctx->fallback_aead_tfm, GFP_KERNEL);
236162306a36Sopenharmony_ci	if (!subreq)
236262306a36Sopenharmony_ci		return -ENOMEM;
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_ci	aead_request_set_tfm(subreq, a_ctx->fallback_aead_tfm);
236562306a36Sopenharmony_ci	aead_request_set_callback(subreq, aead_req->base.flags,
236662306a36Sopenharmony_ci				  aead_req->base.complete, aead_req->base.data);
236762306a36Sopenharmony_ci	aead_request_set_crypt(subreq, aead_req->src, aead_req->dst,
236862306a36Sopenharmony_ci			       aead_req->cryptlen, aead_req->iv);
236962306a36Sopenharmony_ci	aead_request_set_ad(subreq, aead_req->assoclen);
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci	if (encrypt)
237262306a36Sopenharmony_ci		ret = crypto_aead_encrypt(subreq);
237362306a36Sopenharmony_ci	else
237462306a36Sopenharmony_ci		ret = crypto_aead_decrypt(subreq);
237562306a36Sopenharmony_ci	aead_request_free(subreq);
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci	return ret;
237862306a36Sopenharmony_ci}
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_cistatic int sec_aead_crypto(struct aead_request *a_req, bool encrypt)
238162306a36Sopenharmony_ci{
238262306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
238362306a36Sopenharmony_ci	struct sec_req *req = aead_request_ctx(a_req);
238462306a36Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
238562306a36Sopenharmony_ci	int ret;
238662306a36Sopenharmony_ci
238762306a36Sopenharmony_ci	req->flag = a_req->base.flags;
238862306a36Sopenharmony_ci	req->aead_req.aead_req = a_req;
238962306a36Sopenharmony_ci	req->c_req.encrypt = encrypt;
239062306a36Sopenharmony_ci	req->ctx = ctx;
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_ci	ret = sec_aead_param_check(ctx, req);
239362306a36Sopenharmony_ci	if (unlikely(ret)) {
239462306a36Sopenharmony_ci		if (ctx->a_ctx.fallback)
239562306a36Sopenharmony_ci			return sec_aead_soft_crypto(ctx, a_req, encrypt);
239662306a36Sopenharmony_ci		return -EINVAL;
239762306a36Sopenharmony_ci	}
239862306a36Sopenharmony_ci
239962306a36Sopenharmony_ci	return ctx->req_op->process(ctx, req);
240062306a36Sopenharmony_ci}
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_cistatic int sec_aead_encrypt(struct aead_request *a_req)
240362306a36Sopenharmony_ci{
240462306a36Sopenharmony_ci	return sec_aead_crypto(a_req, true);
240562306a36Sopenharmony_ci}
240662306a36Sopenharmony_ci
240762306a36Sopenharmony_cistatic int sec_aead_decrypt(struct aead_request *a_req)
240862306a36Sopenharmony_ci{
240962306a36Sopenharmony_ci	return sec_aead_crypto(a_req, false);
241062306a36Sopenharmony_ci}
241162306a36Sopenharmony_ci
241262306a36Sopenharmony_ci#define SEC_AEAD_ALG(sec_cra_name, sec_set_key, ctx_init,\
241362306a36Sopenharmony_ci			 ctx_exit, blk_size, iv_size, max_authsize)\
241462306a36Sopenharmony_ci{\
241562306a36Sopenharmony_ci	.base = {\
241662306a36Sopenharmony_ci		.cra_name = sec_cra_name,\
241762306a36Sopenharmony_ci		.cra_driver_name = "hisi_sec_"sec_cra_name,\
241862306a36Sopenharmony_ci		.cra_priority = SEC_PRIORITY,\
241962306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC |\
242062306a36Sopenharmony_ci		 CRYPTO_ALG_NEED_FALLBACK,\
242162306a36Sopenharmony_ci		.cra_blocksize = blk_size,\
242262306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct sec_ctx),\
242362306a36Sopenharmony_ci		.cra_module = THIS_MODULE,\
242462306a36Sopenharmony_ci	},\
242562306a36Sopenharmony_ci	.init = ctx_init,\
242662306a36Sopenharmony_ci	.exit = ctx_exit,\
242762306a36Sopenharmony_ci	.setkey = sec_set_key,\
242862306a36Sopenharmony_ci	.setauthsize = sec_aead_setauthsize,\
242962306a36Sopenharmony_ci	.decrypt = sec_aead_decrypt,\
243062306a36Sopenharmony_ci	.encrypt = sec_aead_encrypt,\
243162306a36Sopenharmony_ci	.ivsize = iv_size,\
243262306a36Sopenharmony_ci	.maxauthsize = max_authsize,\
243362306a36Sopenharmony_ci}
243462306a36Sopenharmony_ci
243562306a36Sopenharmony_cistatic struct sec_aead sec_aeads[] = {
243662306a36Sopenharmony_ci	{
243762306a36Sopenharmony_ci		.alg_msk = BIT(6),
243862306a36Sopenharmony_ci		.alg = SEC_AEAD_ALG("ccm(aes)", sec_setkey_aes_ccm, sec_aead_xcm_ctx_init,
243962306a36Sopenharmony_ci				    sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE,
244062306a36Sopenharmony_ci				    AES_BLOCK_SIZE),
244162306a36Sopenharmony_ci	},
244262306a36Sopenharmony_ci	{
244362306a36Sopenharmony_ci		.alg_msk = BIT(7),
244462306a36Sopenharmony_ci		.alg = SEC_AEAD_ALG("gcm(aes)", sec_setkey_aes_gcm, sec_aead_xcm_ctx_init,
244562306a36Sopenharmony_ci				    sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ, SEC_AIV_SIZE,
244662306a36Sopenharmony_ci				    AES_BLOCK_SIZE),
244762306a36Sopenharmony_ci	},
244862306a36Sopenharmony_ci	{
244962306a36Sopenharmony_ci		.alg_msk = BIT(17),
245062306a36Sopenharmony_ci		.alg = SEC_AEAD_ALG("ccm(sm4)", sec_setkey_sm4_ccm, sec_aead_xcm_ctx_init,
245162306a36Sopenharmony_ci				    sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE,
245262306a36Sopenharmony_ci				    AES_BLOCK_SIZE),
245362306a36Sopenharmony_ci	},
245462306a36Sopenharmony_ci	{
245562306a36Sopenharmony_ci		.alg_msk = BIT(18),
245662306a36Sopenharmony_ci		.alg = SEC_AEAD_ALG("gcm(sm4)", sec_setkey_sm4_gcm, sec_aead_xcm_ctx_init,
245762306a36Sopenharmony_ci				    sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ, SEC_AIV_SIZE,
245862306a36Sopenharmony_ci				    AES_BLOCK_SIZE),
245962306a36Sopenharmony_ci	},
246062306a36Sopenharmony_ci	{
246162306a36Sopenharmony_ci		.alg_msk = BIT(43),
246262306a36Sopenharmony_ci		.alg = SEC_AEAD_ALG("authenc(hmac(sha1),cbc(aes))", sec_setkey_aes_cbc_sha1,
246362306a36Sopenharmony_ci				    sec_aead_sha1_ctx_init, sec_aead_ctx_exit, AES_BLOCK_SIZE,
246462306a36Sopenharmony_ci				    AES_BLOCK_SIZE, SHA1_DIGEST_SIZE),
246562306a36Sopenharmony_ci	},
246662306a36Sopenharmony_ci	{
246762306a36Sopenharmony_ci		.alg_msk = BIT(44),
246862306a36Sopenharmony_ci		.alg = SEC_AEAD_ALG("authenc(hmac(sha256),cbc(aes))", sec_setkey_aes_cbc_sha256,
246962306a36Sopenharmony_ci				    sec_aead_sha256_ctx_init, sec_aead_ctx_exit, AES_BLOCK_SIZE,
247062306a36Sopenharmony_ci				    AES_BLOCK_SIZE, SHA256_DIGEST_SIZE),
247162306a36Sopenharmony_ci	},
247262306a36Sopenharmony_ci	{
247362306a36Sopenharmony_ci		.alg_msk = BIT(45),
247462306a36Sopenharmony_ci		.alg = SEC_AEAD_ALG("authenc(hmac(sha512),cbc(aes))", sec_setkey_aes_cbc_sha512,
247562306a36Sopenharmony_ci				    sec_aead_sha512_ctx_init, sec_aead_ctx_exit, AES_BLOCK_SIZE,
247662306a36Sopenharmony_ci				    AES_BLOCK_SIZE, SHA512_DIGEST_SIZE),
247762306a36Sopenharmony_ci	},
247862306a36Sopenharmony_ci};
247962306a36Sopenharmony_ci
248062306a36Sopenharmony_cistatic void sec_unregister_skcipher(u64 alg_mask, int end)
248162306a36Sopenharmony_ci{
248262306a36Sopenharmony_ci	int i;
248362306a36Sopenharmony_ci
248462306a36Sopenharmony_ci	for (i = 0; i < end; i++)
248562306a36Sopenharmony_ci		if (sec_skciphers[i].alg_msk & alg_mask)
248662306a36Sopenharmony_ci			crypto_unregister_skcipher(&sec_skciphers[i].alg);
248762306a36Sopenharmony_ci}
248862306a36Sopenharmony_ci
248962306a36Sopenharmony_cistatic int sec_register_skcipher(u64 alg_mask)
249062306a36Sopenharmony_ci{
249162306a36Sopenharmony_ci	int i, ret, count;
249262306a36Sopenharmony_ci
249362306a36Sopenharmony_ci	count = ARRAY_SIZE(sec_skciphers);
249462306a36Sopenharmony_ci
249562306a36Sopenharmony_ci	for (i = 0; i < count; i++) {
249662306a36Sopenharmony_ci		if (!(sec_skciphers[i].alg_msk & alg_mask))
249762306a36Sopenharmony_ci			continue;
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci		ret = crypto_register_skcipher(&sec_skciphers[i].alg);
250062306a36Sopenharmony_ci		if (ret)
250162306a36Sopenharmony_ci			goto err;
250262306a36Sopenharmony_ci	}
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci	return 0;
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_cierr:
250762306a36Sopenharmony_ci	sec_unregister_skcipher(alg_mask, i);
250862306a36Sopenharmony_ci
250962306a36Sopenharmony_ci	return ret;
251062306a36Sopenharmony_ci}
251162306a36Sopenharmony_ci
251262306a36Sopenharmony_cistatic void sec_unregister_aead(u64 alg_mask, int end)
251362306a36Sopenharmony_ci{
251462306a36Sopenharmony_ci	int i;
251562306a36Sopenharmony_ci
251662306a36Sopenharmony_ci	for (i = 0; i < end; i++)
251762306a36Sopenharmony_ci		if (sec_aeads[i].alg_msk & alg_mask)
251862306a36Sopenharmony_ci			crypto_unregister_aead(&sec_aeads[i].alg);
251962306a36Sopenharmony_ci}
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_cistatic int sec_register_aead(u64 alg_mask)
252262306a36Sopenharmony_ci{
252362306a36Sopenharmony_ci	int i, ret, count;
252462306a36Sopenharmony_ci
252562306a36Sopenharmony_ci	count = ARRAY_SIZE(sec_aeads);
252662306a36Sopenharmony_ci
252762306a36Sopenharmony_ci	for (i = 0; i < count; i++) {
252862306a36Sopenharmony_ci		if (!(sec_aeads[i].alg_msk & alg_mask))
252962306a36Sopenharmony_ci			continue;
253062306a36Sopenharmony_ci
253162306a36Sopenharmony_ci		ret = crypto_register_aead(&sec_aeads[i].alg);
253262306a36Sopenharmony_ci		if (ret)
253362306a36Sopenharmony_ci			goto err;
253462306a36Sopenharmony_ci	}
253562306a36Sopenharmony_ci
253662306a36Sopenharmony_ci	return 0;
253762306a36Sopenharmony_ci
253862306a36Sopenharmony_cierr:
253962306a36Sopenharmony_ci	sec_unregister_aead(alg_mask, i);
254062306a36Sopenharmony_ci
254162306a36Sopenharmony_ci	return ret;
254262306a36Sopenharmony_ci}
254362306a36Sopenharmony_ci
254462306a36Sopenharmony_ciint sec_register_to_crypto(struct hisi_qm *qm)
254562306a36Sopenharmony_ci{
254662306a36Sopenharmony_ci	u64 alg_mask;
254762306a36Sopenharmony_ci	int ret = 0;
254862306a36Sopenharmony_ci
254962306a36Sopenharmony_ci	alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH_IDX,
255062306a36Sopenharmony_ci				      SEC_DRV_ALG_BITMAP_LOW_IDX);
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ci
255362306a36Sopenharmony_ci	ret = sec_register_skcipher(alg_mask);
255462306a36Sopenharmony_ci	if (ret)
255562306a36Sopenharmony_ci		return ret;
255662306a36Sopenharmony_ci
255762306a36Sopenharmony_ci	ret = sec_register_aead(alg_mask);
255862306a36Sopenharmony_ci	if (ret)
255962306a36Sopenharmony_ci		sec_unregister_skcipher(alg_mask, ARRAY_SIZE(sec_skciphers));
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	return ret;
256262306a36Sopenharmony_ci}
256362306a36Sopenharmony_ci
256462306a36Sopenharmony_civoid sec_unregister_from_crypto(struct hisi_qm *qm)
256562306a36Sopenharmony_ci{
256662306a36Sopenharmony_ci	u64 alg_mask;
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci	alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH_IDX,
256962306a36Sopenharmony_ci				      SEC_DRV_ALG_BITMAP_LOW_IDX);
257062306a36Sopenharmony_ci
257162306a36Sopenharmony_ci	sec_unregister_aead(alg_mask, ARRAY_SIZE(sec_aeads));
257262306a36Sopenharmony_ci	sec_unregister_skcipher(alg_mask, ARRAY_SIZE(sec_skciphers));
257362306a36Sopenharmony_ci}
2574