18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (c) 2019 HiSilicon Limited. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <crypto/aes.h>
58c2ecf20Sopenharmony_ci#include <crypto/algapi.h>
68c2ecf20Sopenharmony_ci#include <crypto/authenc.h>
78c2ecf20Sopenharmony_ci#include <crypto/des.h>
88c2ecf20Sopenharmony_ci#include <crypto/hash.h>
98c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h>
108c2ecf20Sopenharmony_ci#include <crypto/sha.h>
118c2ecf20Sopenharmony_ci#include <crypto/skcipher.h>
128c2ecf20Sopenharmony_ci#include <crypto/xts.h>
138c2ecf20Sopenharmony_ci#include <linux/crypto.h>
148c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
158c2ecf20Sopenharmony_ci#include <linux/idr.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include "sec.h"
188c2ecf20Sopenharmony_ci#include "sec_crypto.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define SEC_PRIORITY		4001
218c2ecf20Sopenharmony_ci#define SEC_XTS_MIN_KEY_SIZE	(2 * AES_MIN_KEY_SIZE)
228c2ecf20Sopenharmony_ci#define SEC_XTS_MAX_KEY_SIZE	(2 * AES_MAX_KEY_SIZE)
238c2ecf20Sopenharmony_ci#define SEC_DES3_2KEY_SIZE	(2 * DES_KEY_SIZE)
248c2ecf20Sopenharmony_ci#define SEC_DES3_3KEY_SIZE	(3 * DES_KEY_SIZE)
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* SEC sqe(bd) bit operational relative MACRO */
278c2ecf20Sopenharmony_ci#define SEC_DE_OFFSET		1
288c2ecf20Sopenharmony_ci#define SEC_CIPHER_OFFSET	4
298c2ecf20Sopenharmony_ci#define SEC_SCENE_OFFSET	3
308c2ecf20Sopenharmony_ci#define SEC_DST_SGL_OFFSET	2
318c2ecf20Sopenharmony_ci#define SEC_SRC_SGL_OFFSET	7
328c2ecf20Sopenharmony_ci#define SEC_CKEY_OFFSET		9
338c2ecf20Sopenharmony_ci#define SEC_CMODE_OFFSET	12
348c2ecf20Sopenharmony_ci#define SEC_AKEY_OFFSET         5
358c2ecf20Sopenharmony_ci#define SEC_AEAD_ALG_OFFSET     11
368c2ecf20Sopenharmony_ci#define SEC_AUTH_OFFSET		6
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define SEC_FLAG_OFFSET		7
398c2ecf20Sopenharmony_ci#define SEC_FLAG_MASK		0x0780
408c2ecf20Sopenharmony_ci#define SEC_TYPE_MASK		0x0F
418c2ecf20Sopenharmony_ci#define SEC_DONE_MASK		0x0001
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define SEC_TOTAL_IV_SZ		(SEC_IV_SIZE * QM_Q_DEPTH)
448c2ecf20Sopenharmony_ci#define SEC_SGL_SGE_NR		128
458c2ecf20Sopenharmony_ci#define SEC_CIPHER_AUTH		0xfe
468c2ecf20Sopenharmony_ci#define SEC_AUTH_CIPHER		0x1
478c2ecf20Sopenharmony_ci#define SEC_MAX_MAC_LEN		64
488c2ecf20Sopenharmony_ci#define SEC_MAX_AAD_LEN		65535
498c2ecf20Sopenharmony_ci#define SEC_TOTAL_MAC_SZ	(SEC_MAX_MAC_LEN * QM_Q_DEPTH)
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define SEC_PBUF_SZ			512
528c2ecf20Sopenharmony_ci#define SEC_PBUF_IV_OFFSET		SEC_PBUF_SZ
538c2ecf20Sopenharmony_ci#define SEC_PBUF_MAC_OFFSET		(SEC_PBUF_SZ + SEC_IV_SIZE)
548c2ecf20Sopenharmony_ci#define SEC_PBUF_PKG		(SEC_PBUF_SZ + SEC_IV_SIZE +	\
558c2ecf20Sopenharmony_ci			SEC_MAX_MAC_LEN * 2)
568c2ecf20Sopenharmony_ci#define SEC_PBUF_NUM		(PAGE_SIZE / SEC_PBUF_PKG)
578c2ecf20Sopenharmony_ci#define SEC_PBUF_PAGE_NUM	(QM_Q_DEPTH / SEC_PBUF_NUM)
588c2ecf20Sopenharmony_ci#define SEC_PBUF_LEFT_SZ	(SEC_PBUF_PKG * (QM_Q_DEPTH -	\
598c2ecf20Sopenharmony_ci			SEC_PBUF_PAGE_NUM * SEC_PBUF_NUM))
608c2ecf20Sopenharmony_ci#define SEC_TOTAL_PBUF_SZ	(PAGE_SIZE * SEC_PBUF_PAGE_NUM +	\
618c2ecf20Sopenharmony_ci			SEC_PBUF_LEFT_SZ)
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci#define SEC_SQE_LEN_RATE	4
648c2ecf20Sopenharmony_ci#define SEC_SQE_CFLAG		2
658c2ecf20Sopenharmony_ci#define SEC_SQE_AEAD_FLAG	3
668c2ecf20Sopenharmony_ci#define SEC_SQE_DONE		0x1
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/* Get an en/de-cipher queue cyclically to balance load over queues of TFM */
698c2ecf20Sopenharmony_cistatic inline int sec_alloc_queue_id(struct sec_ctx *ctx, struct sec_req *req)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	if (req->c_req.encrypt)
728c2ecf20Sopenharmony_ci		return (u32)atomic_inc_return(&ctx->enc_qcyclic) %
738c2ecf20Sopenharmony_ci				 ctx->hlf_q_num;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num +
768c2ecf20Sopenharmony_ci				 ctx->hlf_q_num;
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic inline void sec_free_queue_id(struct sec_ctx *ctx, struct sec_req *req)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	if (req->c_req.encrypt)
828c2ecf20Sopenharmony_ci		atomic_dec(&ctx->enc_qcyclic);
838c2ecf20Sopenharmony_ci	else
848c2ecf20Sopenharmony_ci		atomic_dec(&ctx->dec_qcyclic);
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistatic int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	int req_id;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	spin_lock_bh(&qp_ctx->req_lock);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL,
948c2ecf20Sopenharmony_ci				  0, QM_Q_DEPTH, GFP_ATOMIC);
958c2ecf20Sopenharmony_ci	spin_unlock_bh(&qp_ctx->req_lock);
968c2ecf20Sopenharmony_ci	if (unlikely(req_id < 0)) {
978c2ecf20Sopenharmony_ci		dev_err(req->ctx->dev, "alloc req id fail!\n");
988c2ecf20Sopenharmony_ci		return req_id;
998c2ecf20Sopenharmony_ci	}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	req->qp_ctx = qp_ctx;
1028c2ecf20Sopenharmony_ci	qp_ctx->req_list[req_id] = req;
1038c2ecf20Sopenharmony_ci	return req_id;
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistatic void sec_free_req_id(struct sec_req *req)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
1098c2ecf20Sopenharmony_ci	int req_id = req->req_id;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	if (unlikely(req_id < 0 || req_id >= QM_Q_DEPTH)) {
1128c2ecf20Sopenharmony_ci		dev_err(req->ctx->dev, "free request id invalid!\n");
1138c2ecf20Sopenharmony_ci		return;
1148c2ecf20Sopenharmony_ci	}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	qp_ctx->req_list[req_id] = NULL;
1178c2ecf20Sopenharmony_ci	req->qp_ctx = NULL;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	spin_lock_bh(&qp_ctx->req_lock);
1208c2ecf20Sopenharmony_ci	idr_remove(&qp_ctx->req_idr, req_id);
1218c2ecf20Sopenharmony_ci	spin_unlock_bh(&qp_ctx->req_lock);
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic int sec_aead_verify(struct sec_req *req)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	struct aead_request *aead_req = req->aead_req.aead_req;
1278c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
1288c2ecf20Sopenharmony_ci	size_t authsize = crypto_aead_authsize(tfm);
1298c2ecf20Sopenharmony_ci	u8 *mac_out = req->aead_req.out_mac;
1308c2ecf20Sopenharmony_ci	u8 *mac = mac_out + SEC_MAX_MAC_LEN;
1318c2ecf20Sopenharmony_ci	struct scatterlist *sgl = aead_req->src;
1328c2ecf20Sopenharmony_ci	size_t sz;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), mac, authsize,
1358c2ecf20Sopenharmony_ci				aead_req->cryptlen + aead_req->assoclen -
1368c2ecf20Sopenharmony_ci				authsize);
1378c2ecf20Sopenharmony_ci	if (unlikely(sz != authsize || memcmp(mac_out, mac, sz))) {
1388c2ecf20Sopenharmony_ci		dev_err(req->ctx->dev, "aead verify failure!\n");
1398c2ecf20Sopenharmony_ci		return -EBADMSG;
1408c2ecf20Sopenharmony_ci	}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	return 0;
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic void sec_req_cb(struct hisi_qp *qp, void *resp)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = qp->qp_ctx;
1488c2ecf20Sopenharmony_ci	struct sec_dfx *dfx = &qp_ctx->ctx->sec->debug.dfx;
1498c2ecf20Sopenharmony_ci	struct sec_sqe *bd = resp;
1508c2ecf20Sopenharmony_ci	struct sec_ctx *ctx;
1518c2ecf20Sopenharmony_ci	struct sec_req *req;
1528c2ecf20Sopenharmony_ci	u16 done, flag;
1538c2ecf20Sopenharmony_ci	int err = 0;
1548c2ecf20Sopenharmony_ci	u8 type;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	type = bd->type_cipher_auth & SEC_TYPE_MASK;
1578c2ecf20Sopenharmony_ci	if (unlikely(type != SEC_BD_TYPE2)) {
1588c2ecf20Sopenharmony_ci		atomic64_inc(&dfx->err_bd_cnt);
1598c2ecf20Sopenharmony_ci		pr_err("err bd type [%d]\n", type);
1608c2ecf20Sopenharmony_ci		return;
1618c2ecf20Sopenharmony_ci	}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	req = qp_ctx->req_list[le16_to_cpu(bd->type2.tag)];
1648c2ecf20Sopenharmony_ci	if (unlikely(!req)) {
1658c2ecf20Sopenharmony_ci		atomic64_inc(&dfx->invalid_req_cnt);
1668c2ecf20Sopenharmony_ci		atomic_inc(&qp->qp_status.used);
1678c2ecf20Sopenharmony_ci		return;
1688c2ecf20Sopenharmony_ci	}
1698c2ecf20Sopenharmony_ci	req->err_type = bd->type2.error_type;
1708c2ecf20Sopenharmony_ci	ctx = req->ctx;
1718c2ecf20Sopenharmony_ci	done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK;
1728c2ecf20Sopenharmony_ci	flag = (le16_to_cpu(bd->type2.done_flag) &
1738c2ecf20Sopenharmony_ci		SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
1748c2ecf20Sopenharmony_ci	if (unlikely(req->err_type || done != SEC_SQE_DONE ||
1758c2ecf20Sopenharmony_ci	    (ctx->alg_type == SEC_SKCIPHER && flag != SEC_SQE_CFLAG) ||
1768c2ecf20Sopenharmony_ci	    (ctx->alg_type == SEC_AEAD && flag != SEC_SQE_AEAD_FLAG))) {
1778c2ecf20Sopenharmony_ci		dev_err_ratelimited(ctx->dev,
1788c2ecf20Sopenharmony_ci			"err_type[%d],done[%d],flag[%d]\n",
1798c2ecf20Sopenharmony_ci			req->err_type, done, flag);
1808c2ecf20Sopenharmony_ci		err = -EIO;
1818c2ecf20Sopenharmony_ci		atomic64_inc(&dfx->done_flag_cnt);
1828c2ecf20Sopenharmony_ci	}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD && !req->c_req.encrypt)
1858c2ecf20Sopenharmony_ci		err = sec_aead_verify(req);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	atomic64_inc(&dfx->recv_cnt);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	ctx->req_op->buf_unmap(ctx, req);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	ctx->req_op->callback(ctx, req, err);
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
1978c2ecf20Sopenharmony_ci	int ret;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	if (ctx->fake_req_limit <=
2008c2ecf20Sopenharmony_ci	    atomic_read(&qp_ctx->qp->qp_status.used) &&
2018c2ecf20Sopenharmony_ci	    !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG))
2028c2ecf20Sopenharmony_ci		return -EBUSY;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	spin_lock_bh(&qp_ctx->req_lock);
2058c2ecf20Sopenharmony_ci	ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	if (ctx->fake_req_limit <=
2088c2ecf20Sopenharmony_ci	    atomic_read(&qp_ctx->qp->qp_status.used) && !ret) {
2098c2ecf20Sopenharmony_ci		list_add_tail(&req->backlog_head, &qp_ctx->backlog);
2108c2ecf20Sopenharmony_ci		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
2118c2ecf20Sopenharmony_ci		atomic64_inc(&ctx->sec->debug.dfx.send_busy_cnt);
2128c2ecf20Sopenharmony_ci		spin_unlock_bh(&qp_ctx->req_lock);
2138c2ecf20Sopenharmony_ci		return -EBUSY;
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci	spin_unlock_bh(&qp_ctx->req_lock);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	if (unlikely(ret == -EBUSY))
2188c2ecf20Sopenharmony_ci		return -ENOBUFS;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	if (likely(!ret)) {
2218c2ecf20Sopenharmony_ci		ret = -EINPROGRESS;
2228c2ecf20Sopenharmony_ci		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	return ret;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/* Get DMA memory resources */
2298c2ecf20Sopenharmony_cistatic int sec_alloc_civ_resource(struct device *dev, struct sec_alg_res *res)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	int i;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ,
2348c2ecf20Sopenharmony_ci					 &res->c_ivin_dma, GFP_KERNEL);
2358c2ecf20Sopenharmony_ci	if (!res->c_ivin)
2368c2ecf20Sopenharmony_ci		return -ENOMEM;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	for (i = 1; i < QM_Q_DEPTH; i++) {
2398c2ecf20Sopenharmony_ci		res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE;
2408c2ecf20Sopenharmony_ci		res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE;
2418c2ecf20Sopenharmony_ci	}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	return 0;
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic void sec_free_civ_resource(struct device *dev, struct sec_alg_res *res)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	if (res->c_ivin)
2498c2ecf20Sopenharmony_ci		dma_free_coherent(dev, SEC_TOTAL_IV_SZ,
2508c2ecf20Sopenharmony_ci				  res->c_ivin, res->c_ivin_dma);
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic int sec_alloc_mac_resource(struct device *dev, struct sec_alg_res *res)
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	int i;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	res->out_mac = dma_alloc_coherent(dev, SEC_TOTAL_MAC_SZ << 1,
2588c2ecf20Sopenharmony_ci					  &res->out_mac_dma, GFP_KERNEL);
2598c2ecf20Sopenharmony_ci	if (!res->out_mac)
2608c2ecf20Sopenharmony_ci		return -ENOMEM;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	for (i = 1; i < QM_Q_DEPTH; i++) {
2638c2ecf20Sopenharmony_ci		res[i].out_mac_dma = res->out_mac_dma +
2648c2ecf20Sopenharmony_ci				     i * (SEC_MAX_MAC_LEN << 1);
2658c2ecf20Sopenharmony_ci		res[i].out_mac = res->out_mac + i * (SEC_MAX_MAC_LEN << 1);
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	return 0;
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistatic void sec_free_mac_resource(struct device *dev, struct sec_alg_res *res)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	if (res->out_mac)
2748c2ecf20Sopenharmony_ci		dma_free_coherent(dev, SEC_TOTAL_MAC_SZ << 1,
2758c2ecf20Sopenharmony_ci				  res->out_mac, res->out_mac_dma);
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_cistatic void sec_free_pbuf_resource(struct device *dev, struct sec_alg_res *res)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	if (res->pbuf)
2818c2ecf20Sopenharmony_ci		dma_free_coherent(dev, SEC_TOTAL_PBUF_SZ,
2828c2ecf20Sopenharmony_ci				  res->pbuf, res->pbuf_dma);
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci/*
2868c2ecf20Sopenharmony_ci * To improve performance, pbuffer is used for
2878c2ecf20Sopenharmony_ci * small packets (< 512Bytes) as IOMMU translation using.
2888c2ecf20Sopenharmony_ci */
2898c2ecf20Sopenharmony_cistatic int sec_alloc_pbuf_resource(struct device *dev, struct sec_alg_res *res)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	int pbuf_page_offset;
2928c2ecf20Sopenharmony_ci	int i, j, k;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	res->pbuf = dma_alloc_coherent(dev, SEC_TOTAL_PBUF_SZ,
2958c2ecf20Sopenharmony_ci				&res->pbuf_dma, GFP_KERNEL);
2968c2ecf20Sopenharmony_ci	if (!res->pbuf)
2978c2ecf20Sopenharmony_ci		return -ENOMEM;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	/*
3008c2ecf20Sopenharmony_ci	 * SEC_PBUF_PKG contains data pbuf, iv and
3018c2ecf20Sopenharmony_ci	 * out_mac : <SEC_PBUF|SEC_IV|SEC_MAC>
3028c2ecf20Sopenharmony_ci	 * Every PAGE contains six SEC_PBUF_PKG
3038c2ecf20Sopenharmony_ci	 * The sec_qp_ctx contains QM_Q_DEPTH numbers of SEC_PBUF_PKG
3048c2ecf20Sopenharmony_ci	 * So we need SEC_PBUF_PAGE_NUM numbers of PAGE
3058c2ecf20Sopenharmony_ci	 * for the SEC_TOTAL_PBUF_SZ
3068c2ecf20Sopenharmony_ci	 */
3078c2ecf20Sopenharmony_ci	for (i = 0; i <= SEC_PBUF_PAGE_NUM; i++) {
3088c2ecf20Sopenharmony_ci		pbuf_page_offset = PAGE_SIZE * i;
3098c2ecf20Sopenharmony_ci		for (j = 0; j < SEC_PBUF_NUM; j++) {
3108c2ecf20Sopenharmony_ci			k = i * SEC_PBUF_NUM + j;
3118c2ecf20Sopenharmony_ci			if (k == QM_Q_DEPTH)
3128c2ecf20Sopenharmony_ci				break;
3138c2ecf20Sopenharmony_ci			res[k].pbuf = res->pbuf +
3148c2ecf20Sopenharmony_ci				j * SEC_PBUF_PKG + pbuf_page_offset;
3158c2ecf20Sopenharmony_ci			res[k].pbuf_dma = res->pbuf_dma +
3168c2ecf20Sopenharmony_ci				j * SEC_PBUF_PKG + pbuf_page_offset;
3178c2ecf20Sopenharmony_ci		}
3188c2ecf20Sopenharmony_ci	}
3198c2ecf20Sopenharmony_ci	return 0;
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic int sec_alg_resource_alloc(struct sec_ctx *ctx,
3238c2ecf20Sopenharmony_ci				  struct sec_qp_ctx *qp_ctx)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	struct sec_alg_res *res = qp_ctx->res;
3268c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
3278c2ecf20Sopenharmony_ci	int ret;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	ret = sec_alloc_civ_resource(dev, res);
3308c2ecf20Sopenharmony_ci	if (ret)
3318c2ecf20Sopenharmony_ci		return ret;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD) {
3348c2ecf20Sopenharmony_ci		ret = sec_alloc_mac_resource(dev, res);
3358c2ecf20Sopenharmony_ci		if (ret)
3368c2ecf20Sopenharmony_ci			goto alloc_fail;
3378c2ecf20Sopenharmony_ci	}
3388c2ecf20Sopenharmony_ci	if (ctx->pbuf_supported) {
3398c2ecf20Sopenharmony_ci		ret = sec_alloc_pbuf_resource(dev, res);
3408c2ecf20Sopenharmony_ci		if (ret) {
3418c2ecf20Sopenharmony_ci			dev_err(dev, "fail to alloc pbuf dma resource!\n");
3428c2ecf20Sopenharmony_ci			goto alloc_pbuf_fail;
3438c2ecf20Sopenharmony_ci		}
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	return 0;
3478c2ecf20Sopenharmony_cialloc_pbuf_fail:
3488c2ecf20Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD)
3498c2ecf20Sopenharmony_ci		sec_free_mac_resource(dev, qp_ctx->res);
3508c2ecf20Sopenharmony_cialloc_fail:
3518c2ecf20Sopenharmony_ci	sec_free_civ_resource(dev, res);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	return ret;
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cistatic void sec_alg_resource_free(struct sec_ctx *ctx,
3578c2ecf20Sopenharmony_ci				  struct sec_qp_ctx *qp_ctx)
3588c2ecf20Sopenharmony_ci{
3598c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	sec_free_civ_resource(dev, qp_ctx->res);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	if (ctx->pbuf_supported)
3648c2ecf20Sopenharmony_ci		sec_free_pbuf_resource(dev, qp_ctx->res);
3658c2ecf20Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD)
3668c2ecf20Sopenharmony_ci		sec_free_mac_resource(dev, qp_ctx->res);
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistatic int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx,
3708c2ecf20Sopenharmony_ci			     int qp_ctx_id, int alg_type)
3718c2ecf20Sopenharmony_ci{
3728c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
3738c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx;
3748c2ecf20Sopenharmony_ci	struct hisi_qp *qp;
3758c2ecf20Sopenharmony_ci	int ret = -ENOMEM;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	qp_ctx = &ctx->qp_ctx[qp_ctx_id];
3788c2ecf20Sopenharmony_ci	qp = ctx->qps[qp_ctx_id];
3798c2ecf20Sopenharmony_ci	qp->req_type = 0;
3808c2ecf20Sopenharmony_ci	qp->qp_ctx = qp_ctx;
3818c2ecf20Sopenharmony_ci	qp->req_cb = sec_req_cb;
3828c2ecf20Sopenharmony_ci	qp_ctx->qp = qp;
3838c2ecf20Sopenharmony_ci	qp_ctx->ctx = ctx;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	spin_lock_init(&qp_ctx->req_lock);
3868c2ecf20Sopenharmony_ci	idr_init(&qp_ctx->req_idr);
3878c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&qp_ctx->backlog);
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
3908c2ecf20Sopenharmony_ci						     SEC_SGL_SGE_NR);
3918c2ecf20Sopenharmony_ci	if (IS_ERR(qp_ctx->c_in_pool)) {
3928c2ecf20Sopenharmony_ci		dev_err(dev, "fail to create sgl pool for input!\n");
3938c2ecf20Sopenharmony_ci		goto err_destroy_idr;
3948c2ecf20Sopenharmony_ci	}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
3978c2ecf20Sopenharmony_ci						      SEC_SGL_SGE_NR);
3988c2ecf20Sopenharmony_ci	if (IS_ERR(qp_ctx->c_out_pool)) {
3998c2ecf20Sopenharmony_ci		dev_err(dev, "fail to create sgl pool for output!\n");
4008c2ecf20Sopenharmony_ci		goto err_free_c_in_pool;
4018c2ecf20Sopenharmony_ci	}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	ret = sec_alg_resource_alloc(ctx, qp_ctx);
4048c2ecf20Sopenharmony_ci	if (ret)
4058c2ecf20Sopenharmony_ci		goto err_free_c_out_pool;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	ret = hisi_qm_start_qp(qp, 0);
4088c2ecf20Sopenharmony_ci	if (ret < 0)
4098c2ecf20Sopenharmony_ci		goto err_queue_free;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	return 0;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cierr_queue_free:
4148c2ecf20Sopenharmony_ci	sec_alg_resource_free(ctx, qp_ctx);
4158c2ecf20Sopenharmony_cierr_free_c_out_pool:
4168c2ecf20Sopenharmony_ci	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
4178c2ecf20Sopenharmony_cierr_free_c_in_pool:
4188c2ecf20Sopenharmony_ci	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
4198c2ecf20Sopenharmony_cierr_destroy_idr:
4208c2ecf20Sopenharmony_ci	idr_destroy(&qp_ctx->req_idr);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	return ret;
4238c2ecf20Sopenharmony_ci}
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_cistatic void sec_release_qp_ctx(struct sec_ctx *ctx,
4268c2ecf20Sopenharmony_ci			       struct sec_qp_ctx *qp_ctx)
4278c2ecf20Sopenharmony_ci{
4288c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	hisi_qm_stop_qp(qp_ctx->qp);
4318c2ecf20Sopenharmony_ci	sec_alg_resource_free(ctx, qp_ctx);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
4348c2ecf20Sopenharmony_ci	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	idr_destroy(&qp_ctx->req_idr);
4378c2ecf20Sopenharmony_ci}
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_cistatic int sec_ctx_base_init(struct sec_ctx *ctx)
4408c2ecf20Sopenharmony_ci{
4418c2ecf20Sopenharmony_ci	struct sec_dev *sec;
4428c2ecf20Sopenharmony_ci	int i, ret;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	ctx->qps = sec_create_qps();
4458c2ecf20Sopenharmony_ci	if (!ctx->qps) {
4468c2ecf20Sopenharmony_ci		pr_err("Can not create sec qps!\n");
4478c2ecf20Sopenharmony_ci		return -ENODEV;
4488c2ecf20Sopenharmony_ci	}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	sec = container_of(ctx->qps[0]->qm, struct sec_dev, qm);
4518c2ecf20Sopenharmony_ci	ctx->sec = sec;
4528c2ecf20Sopenharmony_ci	ctx->dev = &sec->qm.pdev->dev;
4538c2ecf20Sopenharmony_ci	ctx->hlf_q_num = sec->ctx_q_num >> 1;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	ctx->pbuf_supported = ctx->sec->iommu_used;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	/* Half of queue depth is taken as fake requests limit in the queue. */
4588c2ecf20Sopenharmony_ci	ctx->fake_req_limit = QM_Q_DEPTH >> 1;
4598c2ecf20Sopenharmony_ci	ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx),
4608c2ecf20Sopenharmony_ci			      GFP_KERNEL);
4618c2ecf20Sopenharmony_ci	if (!ctx->qp_ctx) {
4628c2ecf20Sopenharmony_ci		ret = -ENOMEM;
4638c2ecf20Sopenharmony_ci		goto err_destroy_qps;
4648c2ecf20Sopenharmony_ci	}
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	for (i = 0; i < sec->ctx_q_num; i++) {
4678c2ecf20Sopenharmony_ci		ret = sec_create_qp_ctx(&sec->qm, ctx, i, 0);
4688c2ecf20Sopenharmony_ci		if (ret)
4698c2ecf20Sopenharmony_ci			goto err_sec_release_qp_ctx;
4708c2ecf20Sopenharmony_ci	}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	return 0;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_cierr_sec_release_qp_ctx:
4758c2ecf20Sopenharmony_ci	for (i = i - 1; i >= 0; i--)
4768c2ecf20Sopenharmony_ci		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
4778c2ecf20Sopenharmony_ci	kfree(ctx->qp_ctx);
4788c2ecf20Sopenharmony_cierr_destroy_qps:
4798c2ecf20Sopenharmony_ci	sec_destroy_qps(ctx->qps, sec->ctx_q_num);
4808c2ecf20Sopenharmony_ci	return ret;
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_cistatic void sec_ctx_base_uninit(struct sec_ctx *ctx)
4848c2ecf20Sopenharmony_ci{
4858c2ecf20Sopenharmony_ci	int i;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	for (i = 0; i < ctx->sec->ctx_q_num; i++)
4888c2ecf20Sopenharmony_ci		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	sec_destroy_qps(ctx->qps, ctx->sec->ctx_q_num);
4918c2ecf20Sopenharmony_ci	kfree(ctx->qp_ctx);
4928c2ecf20Sopenharmony_ci}
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_cistatic int sec_cipher_init(struct sec_ctx *ctx)
4958c2ecf20Sopenharmony_ci{
4968c2ecf20Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	c_ctx->c_key = dma_alloc_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
4998c2ecf20Sopenharmony_ci					  &c_ctx->c_key_dma, GFP_KERNEL);
5008c2ecf20Sopenharmony_ci	if (!c_ctx->c_key)
5018c2ecf20Sopenharmony_ci		return -ENOMEM;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	return 0;
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_cistatic void sec_cipher_uninit(struct sec_ctx *ctx)
5078c2ecf20Sopenharmony_ci{
5088c2ecf20Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	memzero_explicit(c_ctx->c_key, SEC_MAX_KEY_SIZE);
5118c2ecf20Sopenharmony_ci	dma_free_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
5128c2ecf20Sopenharmony_ci			  c_ctx->c_key, c_ctx->c_key_dma);
5138c2ecf20Sopenharmony_ci}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_cistatic int sec_auth_init(struct sec_ctx *ctx)
5168c2ecf20Sopenharmony_ci{
5178c2ecf20Sopenharmony_ci	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	a_ctx->a_key = dma_alloc_coherent(ctx->dev, SEC_MAX_AKEY_SIZE,
5208c2ecf20Sopenharmony_ci					  &a_ctx->a_key_dma, GFP_KERNEL);
5218c2ecf20Sopenharmony_ci	if (!a_ctx->a_key)
5228c2ecf20Sopenharmony_ci		return -ENOMEM;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	return 0;
5258c2ecf20Sopenharmony_ci}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_cistatic void sec_auth_uninit(struct sec_ctx *ctx)
5288c2ecf20Sopenharmony_ci{
5298c2ecf20Sopenharmony_ci	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	memzero_explicit(a_ctx->a_key, SEC_MAX_AKEY_SIZE);
5328c2ecf20Sopenharmony_ci	dma_free_coherent(ctx->dev, SEC_MAX_AKEY_SIZE,
5338c2ecf20Sopenharmony_ci			  a_ctx->a_key, a_ctx->a_key_dma);
5348c2ecf20Sopenharmony_ci}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_cistatic int sec_skcipher_init(struct crypto_skcipher *tfm)
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
5398c2ecf20Sopenharmony_ci	int ret;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	ctx->alg_type = SEC_SKCIPHER;
5428c2ecf20Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req));
5438c2ecf20Sopenharmony_ci	ctx->c_ctx.ivsize = crypto_skcipher_ivsize(tfm);
5448c2ecf20Sopenharmony_ci	if (ctx->c_ctx.ivsize > SEC_IV_SIZE) {
5458c2ecf20Sopenharmony_ci		pr_err("get error skcipher iv size!\n");
5468c2ecf20Sopenharmony_ci		return -EINVAL;
5478c2ecf20Sopenharmony_ci	}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	ret = sec_ctx_base_init(ctx);
5508c2ecf20Sopenharmony_ci	if (ret)
5518c2ecf20Sopenharmony_ci		return ret;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	ret = sec_cipher_init(ctx);
5548c2ecf20Sopenharmony_ci	if (ret)
5558c2ecf20Sopenharmony_ci		goto err_cipher_init;
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return 0;
5588c2ecf20Sopenharmony_cierr_cipher_init:
5598c2ecf20Sopenharmony_ci	sec_ctx_base_uninit(ctx);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	return ret;
5628c2ecf20Sopenharmony_ci}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_cistatic void sec_skcipher_uninit(struct crypto_skcipher *tfm)
5658c2ecf20Sopenharmony_ci{
5668c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	sec_cipher_uninit(ctx);
5698c2ecf20Sopenharmony_ci	sec_ctx_base_uninit(ctx);
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_cistatic int sec_skcipher_3des_setkey(struct sec_cipher_ctx *c_ctx,
5738c2ecf20Sopenharmony_ci				    const u32 keylen,
5748c2ecf20Sopenharmony_ci				    const enum sec_cmode c_mode)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	switch (keylen) {
5778c2ecf20Sopenharmony_ci	case SEC_DES3_2KEY_SIZE:
5788c2ecf20Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_3DES_2KEY;
5798c2ecf20Sopenharmony_ci		break;
5808c2ecf20Sopenharmony_ci	case SEC_DES3_3KEY_SIZE:
5818c2ecf20Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_3DES_3KEY;
5828c2ecf20Sopenharmony_ci		break;
5838c2ecf20Sopenharmony_ci	default:
5848c2ecf20Sopenharmony_ci		return -EINVAL;
5858c2ecf20Sopenharmony_ci	}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	return 0;
5888c2ecf20Sopenharmony_ci}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_cistatic int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx,
5918c2ecf20Sopenharmony_ci				       const u32 keylen,
5928c2ecf20Sopenharmony_ci				       const enum sec_cmode c_mode)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	if (c_mode == SEC_CMODE_XTS) {
5958c2ecf20Sopenharmony_ci		switch (keylen) {
5968c2ecf20Sopenharmony_ci		case SEC_XTS_MIN_KEY_SIZE:
5978c2ecf20Sopenharmony_ci			c_ctx->c_key_len = SEC_CKEY_128BIT;
5988c2ecf20Sopenharmony_ci			break;
5998c2ecf20Sopenharmony_ci		case SEC_XTS_MAX_KEY_SIZE:
6008c2ecf20Sopenharmony_ci			c_ctx->c_key_len = SEC_CKEY_256BIT;
6018c2ecf20Sopenharmony_ci			break;
6028c2ecf20Sopenharmony_ci		default:
6038c2ecf20Sopenharmony_ci			pr_err("hisi_sec2: xts mode key error!\n");
6048c2ecf20Sopenharmony_ci			return -EINVAL;
6058c2ecf20Sopenharmony_ci		}
6068c2ecf20Sopenharmony_ci	} else {
6078c2ecf20Sopenharmony_ci		switch (keylen) {
6088c2ecf20Sopenharmony_ci		case AES_KEYSIZE_128:
6098c2ecf20Sopenharmony_ci			c_ctx->c_key_len = SEC_CKEY_128BIT;
6108c2ecf20Sopenharmony_ci			break;
6118c2ecf20Sopenharmony_ci		case AES_KEYSIZE_192:
6128c2ecf20Sopenharmony_ci			c_ctx->c_key_len = SEC_CKEY_192BIT;
6138c2ecf20Sopenharmony_ci			break;
6148c2ecf20Sopenharmony_ci		case AES_KEYSIZE_256:
6158c2ecf20Sopenharmony_ci			c_ctx->c_key_len = SEC_CKEY_256BIT;
6168c2ecf20Sopenharmony_ci			break;
6178c2ecf20Sopenharmony_ci		default:
6188c2ecf20Sopenharmony_ci			pr_err("hisi_sec2: aes key error!\n");
6198c2ecf20Sopenharmony_ci			return -EINVAL;
6208c2ecf20Sopenharmony_ci		}
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	return 0;
6248c2ecf20Sopenharmony_ci}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_cistatic int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
6278c2ecf20Sopenharmony_ci			       const u32 keylen, const enum sec_calg c_alg,
6288c2ecf20Sopenharmony_ci			       const enum sec_cmode c_mode)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
6318c2ecf20Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
6328c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
6338c2ecf20Sopenharmony_ci	int ret;
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	if (c_mode == SEC_CMODE_XTS) {
6368c2ecf20Sopenharmony_ci		ret = xts_verify_key(tfm, key, keylen);
6378c2ecf20Sopenharmony_ci		if (ret) {
6388c2ecf20Sopenharmony_ci			dev_err(dev, "xts mode key err!\n");
6398c2ecf20Sopenharmony_ci			return ret;
6408c2ecf20Sopenharmony_ci		}
6418c2ecf20Sopenharmony_ci	}
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	c_ctx->c_alg  = c_alg;
6448c2ecf20Sopenharmony_ci	c_ctx->c_mode = c_mode;
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	switch (c_alg) {
6478c2ecf20Sopenharmony_ci	case SEC_CALG_3DES:
6488c2ecf20Sopenharmony_ci		ret = sec_skcipher_3des_setkey(c_ctx, keylen, c_mode);
6498c2ecf20Sopenharmony_ci		break;
6508c2ecf20Sopenharmony_ci	case SEC_CALG_AES:
6518c2ecf20Sopenharmony_ci	case SEC_CALG_SM4:
6528c2ecf20Sopenharmony_ci		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
6538c2ecf20Sopenharmony_ci		break;
6548c2ecf20Sopenharmony_ci	default:
6558c2ecf20Sopenharmony_ci		return -EINVAL;
6568c2ecf20Sopenharmony_ci	}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	if (ret) {
6598c2ecf20Sopenharmony_ci		dev_err(dev, "set sec key err!\n");
6608c2ecf20Sopenharmony_ci		return ret;
6618c2ecf20Sopenharmony_ci	}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	memcpy(c_ctx->c_key, key, keylen);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	return 0;
6668c2ecf20Sopenharmony_ci}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci#define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode)			\
6698c2ecf20Sopenharmony_cistatic int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\
6708c2ecf20Sopenharmony_ci	u32 keylen)							\
6718c2ecf20Sopenharmony_ci{									\
6728c2ecf20Sopenharmony_ci	return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode);	\
6738c2ecf20Sopenharmony_ci}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB)
6768c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC)
6778c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS)
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB)
6808c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC)
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS)
6838c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC)
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_cistatic int sec_cipher_pbuf_map(struct sec_ctx *ctx, struct sec_req *req,
6868c2ecf20Sopenharmony_ci			struct scatterlist *src)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	struct aead_request *aead_req = req->aead_req.aead_req;
6898c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
6908c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
6918c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
6928c2ecf20Sopenharmony_ci	int copy_size, pbuf_length;
6938c2ecf20Sopenharmony_ci	int req_id = req->req_id;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD)
6968c2ecf20Sopenharmony_ci		copy_size = aead_req->cryptlen + aead_req->assoclen;
6978c2ecf20Sopenharmony_ci	else
6988c2ecf20Sopenharmony_ci		copy_size = c_req->c_len;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	pbuf_length = sg_copy_to_buffer(src, sg_nents(src),
7018c2ecf20Sopenharmony_ci							qp_ctx->res[req_id].pbuf,
7028c2ecf20Sopenharmony_ci							copy_size);
7038c2ecf20Sopenharmony_ci	if (unlikely(pbuf_length != copy_size)) {
7048c2ecf20Sopenharmony_ci		dev_err(dev, "copy src data to pbuf error!\n");
7058c2ecf20Sopenharmony_ci		return -EINVAL;
7068c2ecf20Sopenharmony_ci	}
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	c_req->c_in_dma = qp_ctx->res[req_id].pbuf_dma;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	if (!c_req->c_in_dma) {
7118c2ecf20Sopenharmony_ci		dev_err(dev, "fail to set pbuffer address!\n");
7128c2ecf20Sopenharmony_ci		return -ENOMEM;
7138c2ecf20Sopenharmony_ci	}
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	c_req->c_out_dma = c_req->c_in_dma;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	return 0;
7188c2ecf20Sopenharmony_ci}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_cistatic void sec_cipher_pbuf_unmap(struct sec_ctx *ctx, struct sec_req *req,
7218c2ecf20Sopenharmony_ci			struct scatterlist *dst)
7228c2ecf20Sopenharmony_ci{
7238c2ecf20Sopenharmony_ci	struct aead_request *aead_req = req->aead_req.aead_req;
7248c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
7258c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
7268c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
7278c2ecf20Sopenharmony_ci	int copy_size, pbuf_length;
7288c2ecf20Sopenharmony_ci	int req_id = req->req_id;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD)
7318c2ecf20Sopenharmony_ci		copy_size = c_req->c_len + aead_req->assoclen;
7328c2ecf20Sopenharmony_ci	else
7338c2ecf20Sopenharmony_ci		copy_size = c_req->c_len;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	pbuf_length = sg_copy_from_buffer(dst, sg_nents(dst),
7368c2ecf20Sopenharmony_ci				qp_ctx->res[req_id].pbuf,
7378c2ecf20Sopenharmony_ci				copy_size);
7388c2ecf20Sopenharmony_ci	if (unlikely(pbuf_length != copy_size))
7398c2ecf20Sopenharmony_ci		dev_err(dev, "copy pbuf data to dst error!\n");
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_cistatic int sec_cipher_map(struct sec_ctx *ctx, struct sec_req *req,
7448c2ecf20Sopenharmony_ci			  struct scatterlist *src, struct scatterlist *dst)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
7478c2ecf20Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
7488c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
7498c2ecf20Sopenharmony_ci	struct sec_alg_res *res = &qp_ctx->res[req->req_id];
7508c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
7518c2ecf20Sopenharmony_ci	int ret;
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	if (req->use_pbuf) {
7548c2ecf20Sopenharmony_ci		ret = sec_cipher_pbuf_map(ctx, req, src);
7558c2ecf20Sopenharmony_ci		c_req->c_ivin = res->pbuf + SEC_PBUF_IV_OFFSET;
7568c2ecf20Sopenharmony_ci		c_req->c_ivin_dma = res->pbuf_dma + SEC_PBUF_IV_OFFSET;
7578c2ecf20Sopenharmony_ci		if (ctx->alg_type == SEC_AEAD) {
7588c2ecf20Sopenharmony_ci			a_req->out_mac = res->pbuf + SEC_PBUF_MAC_OFFSET;
7598c2ecf20Sopenharmony_ci			a_req->out_mac_dma = res->pbuf_dma +
7608c2ecf20Sopenharmony_ci					SEC_PBUF_MAC_OFFSET;
7618c2ecf20Sopenharmony_ci		}
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci		return ret;
7648c2ecf20Sopenharmony_ci	}
7658c2ecf20Sopenharmony_ci	c_req->c_ivin = res->c_ivin;
7668c2ecf20Sopenharmony_ci	c_req->c_ivin_dma = res->c_ivin_dma;
7678c2ecf20Sopenharmony_ci	if (ctx->alg_type == SEC_AEAD) {
7688c2ecf20Sopenharmony_ci		a_req->out_mac = res->out_mac;
7698c2ecf20Sopenharmony_ci		a_req->out_mac_dma = res->out_mac_dma;
7708c2ecf20Sopenharmony_ci	}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	c_req->c_in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src,
7738c2ecf20Sopenharmony_ci						    qp_ctx->c_in_pool,
7748c2ecf20Sopenharmony_ci						    req->req_id,
7758c2ecf20Sopenharmony_ci						    &c_req->c_in_dma);
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	if (IS_ERR(c_req->c_in)) {
7788c2ecf20Sopenharmony_ci		dev_err(dev, "fail to dma map input sgl buffers!\n");
7798c2ecf20Sopenharmony_ci		return PTR_ERR(c_req->c_in);
7808c2ecf20Sopenharmony_ci	}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	if (dst == src) {
7838c2ecf20Sopenharmony_ci		c_req->c_out = c_req->c_in;
7848c2ecf20Sopenharmony_ci		c_req->c_out_dma = c_req->c_in_dma;
7858c2ecf20Sopenharmony_ci	} else {
7868c2ecf20Sopenharmony_ci		c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst,
7878c2ecf20Sopenharmony_ci							     qp_ctx->c_out_pool,
7888c2ecf20Sopenharmony_ci							     req->req_id,
7898c2ecf20Sopenharmony_ci							     &c_req->c_out_dma);
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci		if (IS_ERR(c_req->c_out)) {
7928c2ecf20Sopenharmony_ci			dev_err(dev, "fail to dma map output sgl buffers!\n");
7938c2ecf20Sopenharmony_ci			hisi_acc_sg_buf_unmap(dev, src, c_req->c_in);
7948c2ecf20Sopenharmony_ci			return PTR_ERR(c_req->c_out);
7958c2ecf20Sopenharmony_ci		}
7968c2ecf20Sopenharmony_ci	}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	return 0;
7998c2ecf20Sopenharmony_ci}
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_cistatic void sec_cipher_unmap(struct sec_ctx *ctx, struct sec_req *req,
8028c2ecf20Sopenharmony_ci			     struct scatterlist *src, struct scatterlist *dst)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
8058c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	if (req->use_pbuf) {
8088c2ecf20Sopenharmony_ci		sec_cipher_pbuf_unmap(ctx, req, dst);
8098c2ecf20Sopenharmony_ci	} else {
8108c2ecf20Sopenharmony_ci		if (dst != src)
8118c2ecf20Sopenharmony_ci			hisi_acc_sg_buf_unmap(dev, src, c_req->c_in);
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci		hisi_acc_sg_buf_unmap(dev, dst, c_req->c_out);
8148c2ecf20Sopenharmony_ci	}
8158c2ecf20Sopenharmony_ci}
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_cistatic int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
8188c2ecf20Sopenharmony_ci{
8198c2ecf20Sopenharmony_ci	struct skcipher_request *sq = req->c_req.sk_req;
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	return sec_cipher_map(ctx, req, sq->src, sq->dst);
8228c2ecf20Sopenharmony_ci}
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_cistatic void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
8258c2ecf20Sopenharmony_ci{
8268c2ecf20Sopenharmony_ci	struct skcipher_request *sq = req->c_req.sk_req;
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	sec_cipher_unmap(ctx, req, sq->src, sq->dst);
8298c2ecf20Sopenharmony_ci}
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_cistatic int sec_aead_aes_set_key(struct sec_cipher_ctx *c_ctx,
8328c2ecf20Sopenharmony_ci				struct crypto_authenc_keys *keys)
8338c2ecf20Sopenharmony_ci{
8348c2ecf20Sopenharmony_ci	switch (keys->enckeylen) {
8358c2ecf20Sopenharmony_ci	case AES_KEYSIZE_128:
8368c2ecf20Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_128BIT;
8378c2ecf20Sopenharmony_ci		break;
8388c2ecf20Sopenharmony_ci	case AES_KEYSIZE_192:
8398c2ecf20Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_192BIT;
8408c2ecf20Sopenharmony_ci		break;
8418c2ecf20Sopenharmony_ci	case AES_KEYSIZE_256:
8428c2ecf20Sopenharmony_ci		c_ctx->c_key_len = SEC_CKEY_256BIT;
8438c2ecf20Sopenharmony_ci		break;
8448c2ecf20Sopenharmony_ci	default:
8458c2ecf20Sopenharmony_ci		pr_err("hisi_sec2: aead aes key error!\n");
8468c2ecf20Sopenharmony_ci		return -EINVAL;
8478c2ecf20Sopenharmony_ci	}
8488c2ecf20Sopenharmony_ci	memcpy(c_ctx->c_key, keys->enckey, keys->enckeylen);
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	return 0;
8518c2ecf20Sopenharmony_ci}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_cistatic int sec_aead_auth_set_key(struct sec_auth_ctx *ctx,
8548c2ecf20Sopenharmony_ci				 struct crypto_authenc_keys *keys)
8558c2ecf20Sopenharmony_ci{
8568c2ecf20Sopenharmony_ci	struct crypto_shash *hash_tfm = ctx->hash_tfm;
8578c2ecf20Sopenharmony_ci	int blocksize, ret;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	if (!keys->authkeylen) {
8608c2ecf20Sopenharmony_ci		pr_err("hisi_sec2: aead auth key error!\n");
8618c2ecf20Sopenharmony_ci		return -EINVAL;
8628c2ecf20Sopenharmony_ci	}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	blocksize = crypto_shash_blocksize(hash_tfm);
8658c2ecf20Sopenharmony_ci	if (keys->authkeylen > blocksize) {
8668c2ecf20Sopenharmony_ci		ret = crypto_shash_tfm_digest(hash_tfm, keys->authkey,
8678c2ecf20Sopenharmony_ci					      keys->authkeylen, ctx->a_key);
8688c2ecf20Sopenharmony_ci		if (ret) {
8698c2ecf20Sopenharmony_ci			pr_err("hisi_sec2: aead auth digest error!\n");
8708c2ecf20Sopenharmony_ci			return -EINVAL;
8718c2ecf20Sopenharmony_ci		}
8728c2ecf20Sopenharmony_ci		ctx->a_key_len = blocksize;
8738c2ecf20Sopenharmony_ci	} else {
8748c2ecf20Sopenharmony_ci		memcpy(ctx->a_key, keys->authkey, keys->authkeylen);
8758c2ecf20Sopenharmony_ci		ctx->a_key_len = keys->authkeylen;
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	return 0;
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_cistatic int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
8828c2ecf20Sopenharmony_ci			   const u32 keylen, const enum sec_hash_alg a_alg,
8838c2ecf20Sopenharmony_ci			   const enum sec_calg c_alg,
8848c2ecf20Sopenharmony_ci			   const enum sec_mac_len mac_len,
8858c2ecf20Sopenharmony_ci			   const enum sec_cmode c_mode)
8868c2ecf20Sopenharmony_ci{
8878c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
8888c2ecf20Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
8898c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
8908c2ecf20Sopenharmony_ci	struct crypto_authenc_keys keys;
8918c2ecf20Sopenharmony_ci	int ret;
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	ctx->a_ctx.a_alg = a_alg;
8948c2ecf20Sopenharmony_ci	ctx->c_ctx.c_alg = c_alg;
8958c2ecf20Sopenharmony_ci	ctx->a_ctx.mac_len = mac_len;
8968c2ecf20Sopenharmony_ci	c_ctx->c_mode = c_mode;
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen))
8998c2ecf20Sopenharmony_ci		goto bad_key;
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	ret = sec_aead_aes_set_key(c_ctx, &keys);
9028c2ecf20Sopenharmony_ci	if (ret) {
9038c2ecf20Sopenharmony_ci		dev_err(dev, "set sec cipher key err!\n");
9048c2ecf20Sopenharmony_ci		goto bad_key;
9058c2ecf20Sopenharmony_ci	}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	ret = sec_aead_auth_set_key(&ctx->a_ctx, &keys);
9088c2ecf20Sopenharmony_ci	if (ret) {
9098c2ecf20Sopenharmony_ci		dev_err(dev, "set sec auth key err!\n");
9108c2ecf20Sopenharmony_ci		goto bad_key;
9118c2ecf20Sopenharmony_ci	}
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	return 0;
9148c2ecf20Sopenharmony_cibad_key:
9158c2ecf20Sopenharmony_ci	memzero_explicit(&keys, sizeof(struct crypto_authenc_keys));
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	return -EINVAL;
9188c2ecf20Sopenharmony_ci}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci#define GEN_SEC_AEAD_SETKEY_FUNC(name, aalg, calg, maclen, cmode)	\
9228c2ecf20Sopenharmony_cistatic int sec_setkey_##name(struct crypto_aead *tfm, const u8 *key,	\
9238c2ecf20Sopenharmony_ci	u32 keylen)							\
9248c2ecf20Sopenharmony_ci{									\
9258c2ecf20Sopenharmony_ci	return sec_aead_setkey(tfm, key, keylen, aalg, calg, maclen, cmode);\
9268c2ecf20Sopenharmony_ci}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha1, SEC_A_HMAC_SHA1,
9298c2ecf20Sopenharmony_ci			 SEC_CALG_AES, SEC_HMAC_SHA1_MAC, SEC_CMODE_CBC)
9308c2ecf20Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha256, SEC_A_HMAC_SHA256,
9318c2ecf20Sopenharmony_ci			 SEC_CALG_AES, SEC_HMAC_SHA256_MAC, SEC_CMODE_CBC)
9328c2ecf20Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha512, SEC_A_HMAC_SHA512,
9338c2ecf20Sopenharmony_ci			 SEC_CALG_AES, SEC_HMAC_SHA512_MAC, SEC_CMODE_CBC)
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_cistatic int sec_aead_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	struct aead_request *aq = req->aead_req.aead_req;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	return sec_cipher_map(ctx, req, aq->src, aq->dst);
9408c2ecf20Sopenharmony_ci}
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_cistatic void sec_aead_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
9438c2ecf20Sopenharmony_ci{
9448c2ecf20Sopenharmony_ci	struct aead_request *aq = req->aead_req.aead_req;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	sec_cipher_unmap(ctx, req, aq->src, aq->dst);
9478c2ecf20Sopenharmony_ci}
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_cistatic int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req)
9508c2ecf20Sopenharmony_ci{
9518c2ecf20Sopenharmony_ci	int ret;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	ret = ctx->req_op->buf_map(ctx, req);
9548c2ecf20Sopenharmony_ci	if (unlikely(ret))
9558c2ecf20Sopenharmony_ci		return ret;
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci	ctx->req_op->do_transfer(ctx, req);
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	ret = ctx->req_op->bd_fill(ctx, req);
9608c2ecf20Sopenharmony_ci	if (unlikely(ret))
9618c2ecf20Sopenharmony_ci		goto unmap_req_buf;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	return ret;
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ciunmap_req_buf:
9668c2ecf20Sopenharmony_ci	ctx->req_op->buf_unmap(ctx, req);
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	return ret;
9698c2ecf20Sopenharmony_ci}
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_cistatic void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req)
9728c2ecf20Sopenharmony_ci{
9738c2ecf20Sopenharmony_ci	ctx->req_op->buf_unmap(ctx, req);
9748c2ecf20Sopenharmony_ci}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_cistatic void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
9778c2ecf20Sopenharmony_ci{
9788c2ecf20Sopenharmony_ci	struct skcipher_request *sk_req = req->c_req.sk_req;
9798c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	memcpy(c_req->c_ivin, sk_req->iv, ctx->c_ctx.ivsize);
9828c2ecf20Sopenharmony_ci}
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_cistatic int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
9858c2ecf20Sopenharmony_ci{
9868c2ecf20Sopenharmony_ci	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
9878c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
9888c2ecf20Sopenharmony_ci	struct sec_sqe *sec_sqe = &req->sec_sqe;
9898c2ecf20Sopenharmony_ci	u8 scene, sa_type, da_type;
9908c2ecf20Sopenharmony_ci	u8 bd_type, cipher;
9918c2ecf20Sopenharmony_ci	u8 de = 0;
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	memset(sec_sqe, 0, sizeof(struct sec_sqe));
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
9968c2ecf20Sopenharmony_ci	sec_sqe->type2.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
9978c2ecf20Sopenharmony_ci	sec_sqe->type2.data_src_addr = cpu_to_le64(c_req->c_in_dma);
9988c2ecf20Sopenharmony_ci	sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma);
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) <<
10018c2ecf20Sopenharmony_ci						SEC_CMODE_OFFSET);
10028c2ecf20Sopenharmony_ci	sec_sqe->type2.c_alg = c_ctx->c_alg;
10038c2ecf20Sopenharmony_ci	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
10048c2ecf20Sopenharmony_ci						SEC_CKEY_OFFSET);
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	bd_type = SEC_BD_TYPE2;
10078c2ecf20Sopenharmony_ci	if (c_req->encrypt)
10088c2ecf20Sopenharmony_ci		cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET;
10098c2ecf20Sopenharmony_ci	else
10108c2ecf20Sopenharmony_ci		cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET;
10118c2ecf20Sopenharmony_ci	sec_sqe->type_cipher_auth = bd_type | cipher;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	if (req->use_pbuf)
10148c2ecf20Sopenharmony_ci		sa_type = SEC_PBUF << SEC_SRC_SGL_OFFSET;
10158c2ecf20Sopenharmony_ci	else
10168c2ecf20Sopenharmony_ci		sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET;
10178c2ecf20Sopenharmony_ci	scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET;
10188c2ecf20Sopenharmony_ci	if (c_req->c_in_dma != c_req->c_out_dma)
10198c2ecf20Sopenharmony_ci		de = 0x1 << SEC_DE_OFFSET;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	sec_sqe->sds_sa_type = (de | scene | sa_type);
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	/* Just set DST address type */
10248c2ecf20Sopenharmony_ci	if (req->use_pbuf)
10258c2ecf20Sopenharmony_ci		da_type = SEC_PBUF << SEC_DST_SGL_OFFSET;
10268c2ecf20Sopenharmony_ci	else
10278c2ecf20Sopenharmony_ci		da_type = SEC_SGL << SEC_DST_SGL_OFFSET;
10288c2ecf20Sopenharmony_ci	sec_sqe->sdm_addr_type |= da_type;
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci	sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len);
10318c2ecf20Sopenharmony_ci	sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id);
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	return 0;
10348c2ecf20Sopenharmony_ci}
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_cistatic void sec_update_iv(struct sec_req *req, enum sec_alg_type alg_type)
10378c2ecf20Sopenharmony_ci{
10388c2ecf20Sopenharmony_ci	struct aead_request *aead_req = req->aead_req.aead_req;
10398c2ecf20Sopenharmony_ci	struct skcipher_request *sk_req = req->c_req.sk_req;
10408c2ecf20Sopenharmony_ci	u32 iv_size = req->ctx->c_ctx.ivsize;
10418c2ecf20Sopenharmony_ci	struct scatterlist *sgl;
10428c2ecf20Sopenharmony_ci	unsigned int cryptlen;
10438c2ecf20Sopenharmony_ci	size_t sz;
10448c2ecf20Sopenharmony_ci	u8 *iv;
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	if (req->c_req.encrypt)
10478c2ecf20Sopenharmony_ci		sgl = alg_type == SEC_SKCIPHER ? sk_req->dst : aead_req->dst;
10488c2ecf20Sopenharmony_ci	else
10498c2ecf20Sopenharmony_ci		sgl = alg_type == SEC_SKCIPHER ? sk_req->src : aead_req->src;
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	if (alg_type == SEC_SKCIPHER) {
10528c2ecf20Sopenharmony_ci		iv = sk_req->iv;
10538c2ecf20Sopenharmony_ci		cryptlen = sk_req->cryptlen;
10548c2ecf20Sopenharmony_ci	} else {
10558c2ecf20Sopenharmony_ci		iv = aead_req->iv;
10568c2ecf20Sopenharmony_ci		cryptlen = aead_req->cryptlen;
10578c2ecf20Sopenharmony_ci	}
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), iv, iv_size,
10608c2ecf20Sopenharmony_ci				cryptlen - iv_size);
10618c2ecf20Sopenharmony_ci	if (unlikely(sz != iv_size))
10628c2ecf20Sopenharmony_ci		dev_err(req->ctx->dev, "copy output iv error!\n");
10638c2ecf20Sopenharmony_ci}
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_cistatic struct sec_req *sec_back_req_clear(struct sec_ctx *ctx,
10668c2ecf20Sopenharmony_ci				struct sec_qp_ctx *qp_ctx)
10678c2ecf20Sopenharmony_ci{
10688c2ecf20Sopenharmony_ci	struct sec_req *backlog_req = NULL;
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	spin_lock_bh(&qp_ctx->req_lock);
10718c2ecf20Sopenharmony_ci	if (ctx->fake_req_limit >=
10728c2ecf20Sopenharmony_ci	    atomic_read(&qp_ctx->qp->qp_status.used) &&
10738c2ecf20Sopenharmony_ci	    !list_empty(&qp_ctx->backlog)) {
10748c2ecf20Sopenharmony_ci		backlog_req = list_first_entry(&qp_ctx->backlog,
10758c2ecf20Sopenharmony_ci				typeof(*backlog_req), backlog_head);
10768c2ecf20Sopenharmony_ci		list_del(&backlog_req->backlog_head);
10778c2ecf20Sopenharmony_ci	}
10788c2ecf20Sopenharmony_ci	spin_unlock_bh(&qp_ctx->req_lock);
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	return backlog_req;
10818c2ecf20Sopenharmony_ci}
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_cistatic void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req,
10848c2ecf20Sopenharmony_ci				  int err)
10858c2ecf20Sopenharmony_ci{
10868c2ecf20Sopenharmony_ci	struct skcipher_request *sk_req = req->c_req.sk_req;
10878c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
10888c2ecf20Sopenharmony_ci	struct skcipher_request *backlog_sk_req;
10898c2ecf20Sopenharmony_ci	struct sec_req *backlog_req;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	sec_free_req_id(req);
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	/* IV output at encrypto of CBC mode */
10948c2ecf20Sopenharmony_ci	if (!err && ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt)
10958c2ecf20Sopenharmony_ci		sec_update_iv(req, SEC_SKCIPHER);
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci	while (1) {
10988c2ecf20Sopenharmony_ci		backlog_req = sec_back_req_clear(ctx, qp_ctx);
10998c2ecf20Sopenharmony_ci		if (!backlog_req)
11008c2ecf20Sopenharmony_ci			break;
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci		backlog_sk_req = backlog_req->c_req.sk_req;
11038c2ecf20Sopenharmony_ci		backlog_sk_req->base.complete(&backlog_sk_req->base,
11048c2ecf20Sopenharmony_ci						-EINPROGRESS);
11058c2ecf20Sopenharmony_ci		atomic64_inc(&ctx->sec->debug.dfx.recv_busy_cnt);
11068c2ecf20Sopenharmony_ci	}
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci	sk_req->base.complete(&sk_req->base, err);
11108c2ecf20Sopenharmony_ci}
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_cistatic void sec_aead_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
11138c2ecf20Sopenharmony_ci{
11148c2ecf20Sopenharmony_ci	struct aead_request *aead_req = req->aead_req.aead_req;
11158c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	memcpy(c_req->c_ivin, aead_req->iv, ctx->c_ctx.ivsize);
11188c2ecf20Sopenharmony_ci}
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_cistatic void sec_auth_bd_fill_ex(struct sec_auth_ctx *ctx, int dir,
11218c2ecf20Sopenharmony_ci			       struct sec_req *req, struct sec_sqe *sec_sqe)
11228c2ecf20Sopenharmony_ci{
11238c2ecf20Sopenharmony_ci	struct sec_aead_req *a_req = &req->aead_req;
11248c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
11258c2ecf20Sopenharmony_ci	struct aead_request *aq = a_req->aead_req;
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma);
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	sec_sqe->type2.mac_key_alg =
11308c2ecf20Sopenharmony_ci			cpu_to_le32(ctx->mac_len / SEC_SQE_LEN_RATE);
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	sec_sqe->type2.mac_key_alg |=
11338c2ecf20Sopenharmony_ci			cpu_to_le32((u32)((ctx->a_key_len) /
11348c2ecf20Sopenharmony_ci			SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET);
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	sec_sqe->type2.mac_key_alg |=
11378c2ecf20Sopenharmony_ci			cpu_to_le32((u32)(ctx->a_alg) << SEC_AEAD_ALG_OFFSET);
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE1 << SEC_AUTH_OFFSET;
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	if (dir)
11428c2ecf20Sopenharmony_ci		sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH;
11438c2ecf20Sopenharmony_ci	else
11448c2ecf20Sopenharmony_ci		sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	sec_sqe->type2.alen_ivllen = cpu_to_le32(c_req->c_len + aq->assoclen);
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	sec_sqe->type2.mac_addr = cpu_to_le64(a_req->out_mac_dma);
11518c2ecf20Sopenharmony_ci}
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_cistatic int sec_aead_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
11548c2ecf20Sopenharmony_ci{
11558c2ecf20Sopenharmony_ci	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
11568c2ecf20Sopenharmony_ci	struct sec_sqe *sec_sqe = &req->sec_sqe;
11578c2ecf20Sopenharmony_ci	int ret;
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	ret = sec_skcipher_bd_fill(ctx, req);
11608c2ecf20Sopenharmony_ci	if (unlikely(ret)) {
11618c2ecf20Sopenharmony_ci		dev_err(ctx->dev, "skcipher bd fill is error!\n");
11628c2ecf20Sopenharmony_ci		return ret;
11638c2ecf20Sopenharmony_ci	}
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci	sec_auth_bd_fill_ex(auth_ctx, req->c_req.encrypt, req, sec_sqe);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	return 0;
11688c2ecf20Sopenharmony_ci}
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_cistatic void sec_aead_callback(struct sec_ctx *c, struct sec_req *req, int err)
11718c2ecf20Sopenharmony_ci{
11728c2ecf20Sopenharmony_ci	struct aead_request *a_req = req->aead_req.aead_req;
11738c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
11748c2ecf20Sopenharmony_ci	struct sec_aead_req *aead_req = &req->aead_req;
11758c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
11768c2ecf20Sopenharmony_ci	size_t authsize = crypto_aead_authsize(tfm);
11778c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
11788c2ecf20Sopenharmony_ci	struct aead_request *backlog_aead_req;
11798c2ecf20Sopenharmony_ci	struct sec_req *backlog_req;
11808c2ecf20Sopenharmony_ci	size_t sz;
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	if (!err && c->c_ctx.c_mode == SEC_CMODE_CBC && c_req->encrypt)
11838c2ecf20Sopenharmony_ci		sec_update_iv(req, SEC_AEAD);
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci	/* Copy output mac */
11868c2ecf20Sopenharmony_ci	if (!err && c_req->encrypt) {
11878c2ecf20Sopenharmony_ci		struct scatterlist *sgl = a_req->dst;
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci		sz = sg_pcopy_from_buffer(sgl, sg_nents(sgl),
11908c2ecf20Sopenharmony_ci					  aead_req->out_mac,
11918c2ecf20Sopenharmony_ci					  authsize, a_req->cryptlen +
11928c2ecf20Sopenharmony_ci					  a_req->assoclen);
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci		if (unlikely(sz != authsize)) {
11958c2ecf20Sopenharmony_ci			dev_err(c->dev, "copy out mac err!\n");
11968c2ecf20Sopenharmony_ci			err = -EINVAL;
11978c2ecf20Sopenharmony_ci		}
11988c2ecf20Sopenharmony_ci	}
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	sec_free_req_id(req);
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	while (1) {
12038c2ecf20Sopenharmony_ci		backlog_req = sec_back_req_clear(c, qp_ctx);
12048c2ecf20Sopenharmony_ci		if (!backlog_req)
12058c2ecf20Sopenharmony_ci			break;
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci		backlog_aead_req = backlog_req->aead_req.aead_req;
12088c2ecf20Sopenharmony_ci		backlog_aead_req->base.complete(&backlog_aead_req->base,
12098c2ecf20Sopenharmony_ci						-EINPROGRESS);
12108c2ecf20Sopenharmony_ci		atomic64_inc(&c->sec->debug.dfx.recv_busy_cnt);
12118c2ecf20Sopenharmony_ci	}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	a_req->base.complete(&a_req->base, err);
12148c2ecf20Sopenharmony_ci}
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_cistatic void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req)
12178c2ecf20Sopenharmony_ci{
12188c2ecf20Sopenharmony_ci	sec_free_req_id(req);
12198c2ecf20Sopenharmony_ci	sec_free_queue_id(ctx, req);
12208c2ecf20Sopenharmony_ci}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_cistatic int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
12238c2ecf20Sopenharmony_ci{
12248c2ecf20Sopenharmony_ci	struct sec_qp_ctx *qp_ctx;
12258c2ecf20Sopenharmony_ci	int queue_id;
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	/* To load balance */
12288c2ecf20Sopenharmony_ci	queue_id = sec_alloc_queue_id(ctx, req);
12298c2ecf20Sopenharmony_ci	qp_ctx = &ctx->qp_ctx[queue_id];
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	req->req_id = sec_alloc_req_id(req, qp_ctx);
12328c2ecf20Sopenharmony_ci	if (unlikely(req->req_id < 0)) {
12338c2ecf20Sopenharmony_ci		sec_free_queue_id(ctx, req);
12348c2ecf20Sopenharmony_ci		return req->req_id;
12358c2ecf20Sopenharmony_ci	}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	return 0;
12388c2ecf20Sopenharmony_ci}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_cistatic int sec_process(struct sec_ctx *ctx, struct sec_req *req)
12418c2ecf20Sopenharmony_ci{
12428c2ecf20Sopenharmony_ci	struct sec_cipher_req *c_req = &req->c_req;
12438c2ecf20Sopenharmony_ci	int ret;
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	ret = sec_request_init(ctx, req);
12468c2ecf20Sopenharmony_ci	if (unlikely(ret))
12478c2ecf20Sopenharmony_ci		return ret;
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	ret = sec_request_transfer(ctx, req);
12508c2ecf20Sopenharmony_ci	if (unlikely(ret))
12518c2ecf20Sopenharmony_ci		goto err_uninit_req;
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	/* Output IV as decrypto */
12548c2ecf20Sopenharmony_ci	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt)
12558c2ecf20Sopenharmony_ci		sec_update_iv(req, ctx->alg_type);
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	ret = ctx->req_op->bd_send(ctx, req);
12588c2ecf20Sopenharmony_ci	if (unlikely((ret != -EBUSY && ret != -EINPROGRESS) ||
12598c2ecf20Sopenharmony_ci		(ret == -EBUSY && !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
12608c2ecf20Sopenharmony_ci		dev_err_ratelimited(ctx->dev, "send sec request failed!\n");
12618c2ecf20Sopenharmony_ci		goto err_send_req;
12628c2ecf20Sopenharmony_ci	}
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	return ret;
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_cierr_send_req:
12678c2ecf20Sopenharmony_ci	/* As failing, restore the IV from user */
12688c2ecf20Sopenharmony_ci	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) {
12698c2ecf20Sopenharmony_ci		if (ctx->alg_type == SEC_SKCIPHER)
12708c2ecf20Sopenharmony_ci			memcpy(req->c_req.sk_req->iv, c_req->c_ivin,
12718c2ecf20Sopenharmony_ci			       ctx->c_ctx.ivsize);
12728c2ecf20Sopenharmony_ci		else
12738c2ecf20Sopenharmony_ci			memcpy(req->aead_req.aead_req->iv, c_req->c_ivin,
12748c2ecf20Sopenharmony_ci			       ctx->c_ctx.ivsize);
12758c2ecf20Sopenharmony_ci	}
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	sec_request_untransfer(ctx, req);
12788c2ecf20Sopenharmony_cierr_uninit_req:
12798c2ecf20Sopenharmony_ci	sec_request_uninit(ctx, req);
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	return ret;
12828c2ecf20Sopenharmony_ci}
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_cistatic const struct sec_req_op sec_skcipher_req_ops = {
12858c2ecf20Sopenharmony_ci	.buf_map	= sec_skcipher_sgl_map,
12868c2ecf20Sopenharmony_ci	.buf_unmap	= sec_skcipher_sgl_unmap,
12878c2ecf20Sopenharmony_ci	.do_transfer	= sec_skcipher_copy_iv,
12888c2ecf20Sopenharmony_ci	.bd_fill	= sec_skcipher_bd_fill,
12898c2ecf20Sopenharmony_ci	.bd_send	= sec_bd_send,
12908c2ecf20Sopenharmony_ci	.callback	= sec_skcipher_callback,
12918c2ecf20Sopenharmony_ci	.process	= sec_process,
12928c2ecf20Sopenharmony_ci};
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_cistatic const struct sec_req_op sec_aead_req_ops = {
12958c2ecf20Sopenharmony_ci	.buf_map	= sec_aead_sgl_map,
12968c2ecf20Sopenharmony_ci	.buf_unmap	= sec_aead_sgl_unmap,
12978c2ecf20Sopenharmony_ci	.do_transfer	= sec_aead_copy_iv,
12988c2ecf20Sopenharmony_ci	.bd_fill	= sec_aead_bd_fill,
12998c2ecf20Sopenharmony_ci	.bd_send	= sec_bd_send,
13008c2ecf20Sopenharmony_ci	.callback	= sec_aead_callback,
13018c2ecf20Sopenharmony_ci	.process	= sec_process,
13028c2ecf20Sopenharmony_ci};
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_cistatic int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
13058c2ecf20Sopenharmony_ci{
13068c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	ctx->req_op = &sec_skcipher_req_ops;
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci	return sec_skcipher_init(tfm);
13118c2ecf20Sopenharmony_ci}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_cistatic void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm)
13148c2ecf20Sopenharmony_ci{
13158c2ecf20Sopenharmony_ci	sec_skcipher_uninit(tfm);
13168c2ecf20Sopenharmony_ci}
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_cistatic int sec_aead_init(struct crypto_aead *tfm)
13198c2ecf20Sopenharmony_ci{
13208c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
13218c2ecf20Sopenharmony_ci	int ret;
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci	crypto_aead_set_reqsize(tfm, sizeof(struct sec_req));
13248c2ecf20Sopenharmony_ci	ctx->alg_type = SEC_AEAD;
13258c2ecf20Sopenharmony_ci	ctx->c_ctx.ivsize = crypto_aead_ivsize(tfm);
13268c2ecf20Sopenharmony_ci	if (ctx->c_ctx.ivsize > SEC_IV_SIZE) {
13278c2ecf20Sopenharmony_ci		dev_err(ctx->dev, "get error aead iv size!\n");
13288c2ecf20Sopenharmony_ci		return -EINVAL;
13298c2ecf20Sopenharmony_ci	}
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci	ctx->req_op = &sec_aead_req_ops;
13328c2ecf20Sopenharmony_ci	ret = sec_ctx_base_init(ctx);
13338c2ecf20Sopenharmony_ci	if (ret)
13348c2ecf20Sopenharmony_ci		return ret;
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci	ret = sec_auth_init(ctx);
13378c2ecf20Sopenharmony_ci	if (ret)
13388c2ecf20Sopenharmony_ci		goto err_auth_init;
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	ret = sec_cipher_init(ctx);
13418c2ecf20Sopenharmony_ci	if (ret)
13428c2ecf20Sopenharmony_ci		goto err_cipher_init;
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	return ret;
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_cierr_cipher_init:
13478c2ecf20Sopenharmony_ci	sec_auth_uninit(ctx);
13488c2ecf20Sopenharmony_cierr_auth_init:
13498c2ecf20Sopenharmony_ci	sec_ctx_base_uninit(ctx);
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	return ret;
13528c2ecf20Sopenharmony_ci}
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_cistatic void sec_aead_exit(struct crypto_aead *tfm)
13558c2ecf20Sopenharmony_ci{
13568c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci	sec_cipher_uninit(ctx);
13598c2ecf20Sopenharmony_ci	sec_auth_uninit(ctx);
13608c2ecf20Sopenharmony_ci	sec_ctx_base_uninit(ctx);
13618c2ecf20Sopenharmony_ci}
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_cistatic int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name)
13648c2ecf20Sopenharmony_ci{
13658c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
13668c2ecf20Sopenharmony_ci	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
13678c2ecf20Sopenharmony_ci	int ret;
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	ret = sec_aead_init(tfm);
13708c2ecf20Sopenharmony_ci	if (ret) {
13718c2ecf20Sopenharmony_ci		pr_err("hisi_sec2: aead init error!\n");
13728c2ecf20Sopenharmony_ci		return ret;
13738c2ecf20Sopenharmony_ci	}
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	auth_ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
13768c2ecf20Sopenharmony_ci	if (IS_ERR(auth_ctx->hash_tfm)) {
13778c2ecf20Sopenharmony_ci		dev_err(ctx->dev, "aead alloc shash error!\n");
13788c2ecf20Sopenharmony_ci		sec_aead_exit(tfm);
13798c2ecf20Sopenharmony_ci		return PTR_ERR(auth_ctx->hash_tfm);
13808c2ecf20Sopenharmony_ci	}
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_ci	return 0;
13838c2ecf20Sopenharmony_ci}
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_cistatic void sec_aead_ctx_exit(struct crypto_aead *tfm)
13868c2ecf20Sopenharmony_ci{
13878c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	crypto_free_shash(ctx->a_ctx.hash_tfm);
13908c2ecf20Sopenharmony_ci	sec_aead_exit(tfm);
13918c2ecf20Sopenharmony_ci}
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_cistatic int sec_aead_sha1_ctx_init(struct crypto_aead *tfm)
13948c2ecf20Sopenharmony_ci{
13958c2ecf20Sopenharmony_ci	return sec_aead_ctx_init(tfm, "sha1");
13968c2ecf20Sopenharmony_ci}
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_cistatic int sec_aead_sha256_ctx_init(struct crypto_aead *tfm)
13998c2ecf20Sopenharmony_ci{
14008c2ecf20Sopenharmony_ci	return sec_aead_ctx_init(tfm, "sha256");
14018c2ecf20Sopenharmony_ci}
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_cistatic int sec_aead_sha512_ctx_init(struct crypto_aead *tfm)
14048c2ecf20Sopenharmony_ci{
14058c2ecf20Sopenharmony_ci	return sec_aead_ctx_init(tfm, "sha512");
14068c2ecf20Sopenharmony_ci}
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_cistatic int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
14098c2ecf20Sopenharmony_ci{
14108c2ecf20Sopenharmony_ci	struct skcipher_request *sk_req = sreq->c_req.sk_req;
14118c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
14128c2ecf20Sopenharmony_ci	u8 c_alg = ctx->c_ctx.c_alg;
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci	if (unlikely(!sk_req->src || !sk_req->dst)) {
14158c2ecf20Sopenharmony_ci		dev_err(dev, "skcipher input param error!\n");
14168c2ecf20Sopenharmony_ci		return -EINVAL;
14178c2ecf20Sopenharmony_ci	}
14188c2ecf20Sopenharmony_ci	sreq->c_req.c_len = sk_req->cryptlen;
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci	if (ctx->pbuf_supported && sk_req->cryptlen <= SEC_PBUF_SZ)
14218c2ecf20Sopenharmony_ci		sreq->use_pbuf = true;
14228c2ecf20Sopenharmony_ci	else
14238c2ecf20Sopenharmony_ci		sreq->use_pbuf = false;
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	if (c_alg == SEC_CALG_3DES) {
14268c2ecf20Sopenharmony_ci		if (unlikely(sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1))) {
14278c2ecf20Sopenharmony_ci			dev_err(dev, "skcipher 3des input length error!\n");
14288c2ecf20Sopenharmony_ci			return -EINVAL;
14298c2ecf20Sopenharmony_ci		}
14308c2ecf20Sopenharmony_ci		return 0;
14318c2ecf20Sopenharmony_ci	} else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) {
14328c2ecf20Sopenharmony_ci		if (unlikely(sk_req->cryptlen & (AES_BLOCK_SIZE - 1))) {
14338c2ecf20Sopenharmony_ci			dev_err(dev, "skcipher aes input length error!\n");
14348c2ecf20Sopenharmony_ci			return -EINVAL;
14358c2ecf20Sopenharmony_ci		}
14368c2ecf20Sopenharmony_ci		return 0;
14378c2ecf20Sopenharmony_ci	}
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci	dev_err(dev, "skcipher algorithm error!\n");
14408c2ecf20Sopenharmony_ci	return -EINVAL;
14418c2ecf20Sopenharmony_ci}
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_cistatic int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt)
14448c2ecf20Sopenharmony_ci{
14458c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req);
14468c2ecf20Sopenharmony_ci	struct sec_req *req = skcipher_request_ctx(sk_req);
14478c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
14488c2ecf20Sopenharmony_ci	int ret;
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	if (!sk_req->cryptlen)
14518c2ecf20Sopenharmony_ci		return 0;
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	req->flag = sk_req->base.flags;
14548c2ecf20Sopenharmony_ci	req->c_req.sk_req = sk_req;
14558c2ecf20Sopenharmony_ci	req->c_req.encrypt = encrypt;
14568c2ecf20Sopenharmony_ci	req->ctx = ctx;
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	ret = sec_skcipher_param_check(ctx, req);
14598c2ecf20Sopenharmony_ci	if (unlikely(ret))
14608c2ecf20Sopenharmony_ci		return -EINVAL;
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_ci	return ctx->req_op->process(ctx, req);
14638c2ecf20Sopenharmony_ci}
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_cistatic int sec_skcipher_encrypt(struct skcipher_request *sk_req)
14668c2ecf20Sopenharmony_ci{
14678c2ecf20Sopenharmony_ci	return sec_skcipher_crypto(sk_req, true);
14688c2ecf20Sopenharmony_ci}
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_cistatic int sec_skcipher_decrypt(struct skcipher_request *sk_req)
14718c2ecf20Sopenharmony_ci{
14728c2ecf20Sopenharmony_ci	return sec_skcipher_crypto(sk_req, false);
14738c2ecf20Sopenharmony_ci}
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci#define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \
14768c2ecf20Sopenharmony_ci	sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\
14778c2ecf20Sopenharmony_ci{\
14788c2ecf20Sopenharmony_ci	.base = {\
14798c2ecf20Sopenharmony_ci		.cra_name = sec_cra_name,\
14808c2ecf20Sopenharmony_ci		.cra_driver_name = "hisi_sec_"sec_cra_name,\
14818c2ecf20Sopenharmony_ci		.cra_priority = SEC_PRIORITY,\
14828c2ecf20Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,\
14838c2ecf20Sopenharmony_ci		.cra_blocksize = blk_size,\
14848c2ecf20Sopenharmony_ci		.cra_ctxsize = sizeof(struct sec_ctx),\
14858c2ecf20Sopenharmony_ci		.cra_module = THIS_MODULE,\
14868c2ecf20Sopenharmony_ci	},\
14878c2ecf20Sopenharmony_ci	.init = ctx_init,\
14888c2ecf20Sopenharmony_ci	.exit = ctx_exit,\
14898c2ecf20Sopenharmony_ci	.setkey = sec_set_key,\
14908c2ecf20Sopenharmony_ci	.decrypt = sec_skcipher_decrypt,\
14918c2ecf20Sopenharmony_ci	.encrypt = sec_skcipher_encrypt,\
14928c2ecf20Sopenharmony_ci	.min_keysize = sec_min_key_size,\
14938c2ecf20Sopenharmony_ci	.max_keysize = sec_max_key_size,\
14948c2ecf20Sopenharmony_ci	.ivsize = iv_size,\
14958c2ecf20Sopenharmony_ci},
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci#define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \
14988c2ecf20Sopenharmony_ci	max_key_size, blk_size, iv_size) \
14998c2ecf20Sopenharmony_ci	SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \
15008c2ecf20Sopenharmony_ci	sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size)
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_cistatic struct skcipher_alg sec_skciphers[] = {
15038c2ecf20Sopenharmony_ci	SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb,
15048c2ecf20Sopenharmony_ci			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
15058c2ecf20Sopenharmony_ci			 AES_BLOCK_SIZE, 0)
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci	SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc,
15088c2ecf20Sopenharmony_ci			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
15098c2ecf20Sopenharmony_ci			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci	SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts,
15128c2ecf20Sopenharmony_ci			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE,
15138c2ecf20Sopenharmony_ci			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_ci	SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb,
15168c2ecf20Sopenharmony_ci			 SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE,
15178c2ecf20Sopenharmony_ci			 DES3_EDE_BLOCK_SIZE, 0)
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc,
15208c2ecf20Sopenharmony_ci			 SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE,
15218c2ecf20Sopenharmony_ci			 DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE)
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,
15248c2ecf20Sopenharmony_ci			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE,
15258c2ecf20Sopenharmony_ci			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc,
15288c2ecf20Sopenharmony_ci			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
15298c2ecf20Sopenharmony_ci			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
15308c2ecf20Sopenharmony_ci};
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_cistatic int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
15338c2ecf20Sopenharmony_ci{
15348c2ecf20Sopenharmony_ci	struct aead_request *req = sreq->aead_req.aead_req;
15358c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
15368c2ecf20Sopenharmony_ci	size_t authsize = crypto_aead_authsize(tfm);
15378c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
15388c2ecf20Sopenharmony_ci	u8 c_alg = ctx->c_ctx.c_alg;
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	if (unlikely(!req->src || !req->dst || !req->cryptlen ||
15418c2ecf20Sopenharmony_ci		req->assoclen > SEC_MAX_AAD_LEN)) {
15428c2ecf20Sopenharmony_ci		dev_err(dev, "aead input param error!\n");
15438c2ecf20Sopenharmony_ci		return -EINVAL;
15448c2ecf20Sopenharmony_ci	}
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	if (ctx->pbuf_supported && (req->cryptlen + req->assoclen) <=
15478c2ecf20Sopenharmony_ci		SEC_PBUF_SZ)
15488c2ecf20Sopenharmony_ci		sreq->use_pbuf = true;
15498c2ecf20Sopenharmony_ci	else
15508c2ecf20Sopenharmony_ci		sreq->use_pbuf = false;
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	/* Support AES only */
15538c2ecf20Sopenharmony_ci	if (unlikely(c_alg != SEC_CALG_AES)) {
15548c2ecf20Sopenharmony_ci		dev_err(dev, "aead crypto alg error!\n");
15558c2ecf20Sopenharmony_ci		return -EINVAL;
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci	}
15588c2ecf20Sopenharmony_ci	if (sreq->c_req.encrypt)
15598c2ecf20Sopenharmony_ci		sreq->c_req.c_len = req->cryptlen;
15608c2ecf20Sopenharmony_ci	else
15618c2ecf20Sopenharmony_ci		sreq->c_req.c_len = req->cryptlen - authsize;
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci	if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) {
15648c2ecf20Sopenharmony_ci		dev_err(dev, "aead crypto length error!\n");
15658c2ecf20Sopenharmony_ci		return -EINVAL;
15668c2ecf20Sopenharmony_ci	}
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci	return 0;
15698c2ecf20Sopenharmony_ci}
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_cistatic int sec_aead_crypto(struct aead_request *a_req, bool encrypt)
15728c2ecf20Sopenharmony_ci{
15738c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
15748c2ecf20Sopenharmony_ci	struct sec_req *req = aead_request_ctx(a_req);
15758c2ecf20Sopenharmony_ci	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
15768c2ecf20Sopenharmony_ci	int ret;
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	req->flag = a_req->base.flags;
15798c2ecf20Sopenharmony_ci	req->aead_req.aead_req = a_req;
15808c2ecf20Sopenharmony_ci	req->c_req.encrypt = encrypt;
15818c2ecf20Sopenharmony_ci	req->ctx = ctx;
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci	ret = sec_aead_param_check(ctx, req);
15848c2ecf20Sopenharmony_ci	if (unlikely(ret))
15858c2ecf20Sopenharmony_ci		return -EINVAL;
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	return ctx->req_op->process(ctx, req);
15888c2ecf20Sopenharmony_ci}
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_cistatic int sec_aead_encrypt(struct aead_request *a_req)
15918c2ecf20Sopenharmony_ci{
15928c2ecf20Sopenharmony_ci	return sec_aead_crypto(a_req, true);
15938c2ecf20Sopenharmony_ci}
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_cistatic int sec_aead_decrypt(struct aead_request *a_req)
15968c2ecf20Sopenharmony_ci{
15978c2ecf20Sopenharmony_ci	return sec_aead_crypto(a_req, false);
15988c2ecf20Sopenharmony_ci}
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci#define SEC_AEAD_GEN_ALG(sec_cra_name, sec_set_key, ctx_init,\
16018c2ecf20Sopenharmony_ci			 ctx_exit, blk_size, iv_size, max_authsize)\
16028c2ecf20Sopenharmony_ci{\
16038c2ecf20Sopenharmony_ci	.base = {\
16048c2ecf20Sopenharmony_ci		.cra_name = sec_cra_name,\
16058c2ecf20Sopenharmony_ci		.cra_driver_name = "hisi_sec_"sec_cra_name,\
16068c2ecf20Sopenharmony_ci		.cra_priority = SEC_PRIORITY,\
16078c2ecf20Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,\
16088c2ecf20Sopenharmony_ci		.cra_blocksize = blk_size,\
16098c2ecf20Sopenharmony_ci		.cra_ctxsize = sizeof(struct sec_ctx),\
16108c2ecf20Sopenharmony_ci		.cra_module = THIS_MODULE,\
16118c2ecf20Sopenharmony_ci	},\
16128c2ecf20Sopenharmony_ci	.init = ctx_init,\
16138c2ecf20Sopenharmony_ci	.exit = ctx_exit,\
16148c2ecf20Sopenharmony_ci	.setkey = sec_set_key,\
16158c2ecf20Sopenharmony_ci	.decrypt = sec_aead_decrypt,\
16168c2ecf20Sopenharmony_ci	.encrypt = sec_aead_encrypt,\
16178c2ecf20Sopenharmony_ci	.ivsize = iv_size,\
16188c2ecf20Sopenharmony_ci	.maxauthsize = max_authsize,\
16198c2ecf20Sopenharmony_ci}
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci#define SEC_AEAD_ALG(algname, keyfunc, aead_init, blksize, ivsize, authsize)\
16228c2ecf20Sopenharmony_ci	SEC_AEAD_GEN_ALG(algname, keyfunc, aead_init,\
16238c2ecf20Sopenharmony_ci			sec_aead_ctx_exit, blksize, ivsize, authsize)
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_cistatic struct aead_alg sec_aeads[] = {
16268c2ecf20Sopenharmony_ci	SEC_AEAD_ALG("authenc(hmac(sha1),cbc(aes))",
16278c2ecf20Sopenharmony_ci		     sec_setkey_aes_cbc_sha1, sec_aead_sha1_ctx_init,
16288c2ecf20Sopenharmony_ci		     AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA1_DIGEST_SIZE),
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	SEC_AEAD_ALG("authenc(hmac(sha256),cbc(aes))",
16318c2ecf20Sopenharmony_ci		     sec_setkey_aes_cbc_sha256, sec_aead_sha256_ctx_init,
16328c2ecf20Sopenharmony_ci		     AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA256_DIGEST_SIZE),
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci	SEC_AEAD_ALG("authenc(hmac(sha512),cbc(aes))",
16358c2ecf20Sopenharmony_ci		     sec_setkey_aes_cbc_sha512, sec_aead_sha512_ctx_init,
16368c2ecf20Sopenharmony_ci		     AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA512_DIGEST_SIZE),
16378c2ecf20Sopenharmony_ci};
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ciint sec_register_to_crypto(void)
16408c2ecf20Sopenharmony_ci{
16418c2ecf20Sopenharmony_ci	int ret;
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci	/* To avoid repeat register */
16448c2ecf20Sopenharmony_ci	ret = crypto_register_skciphers(sec_skciphers,
16458c2ecf20Sopenharmony_ci					ARRAY_SIZE(sec_skciphers));
16468c2ecf20Sopenharmony_ci	if (ret)
16478c2ecf20Sopenharmony_ci		return ret;
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	ret = crypto_register_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
16508c2ecf20Sopenharmony_ci	if (ret)
16518c2ecf20Sopenharmony_ci		crypto_unregister_skciphers(sec_skciphers,
16528c2ecf20Sopenharmony_ci					    ARRAY_SIZE(sec_skciphers));
16538c2ecf20Sopenharmony_ci	return ret;
16548c2ecf20Sopenharmony_ci}
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_civoid sec_unregister_from_crypto(void)
16578c2ecf20Sopenharmony_ci{
16588c2ecf20Sopenharmony_ci	crypto_unregister_skciphers(sec_skciphers,
16598c2ecf20Sopenharmony_ci				    ARRAY_SIZE(sec_skciphers));
16608c2ecf20Sopenharmony_ci	crypto_unregister_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
16618c2ecf20Sopenharmony_ci}
1662