1416d8220SZaibo Xu // SPDX-License-Identifier: GPL-2.0
2416d8220SZaibo Xu /* Copyright (c) 2019 HiSilicon Limited. */
3416d8220SZaibo Xu 
4416d8220SZaibo Xu #include <crypto/aes.h>
5416d8220SZaibo Xu #include <crypto/algapi.h>
62f072d75SZaibo Xu #include <crypto/authenc.h>
7416d8220SZaibo Xu #include <crypto/des.h>
82f072d75SZaibo Xu #include <crypto/hash.h>
92f072d75SZaibo Xu #include <crypto/internal/aead.h>
10*a24d22b2SEric Biggers #include <crypto/sha1.h>
11*a24d22b2SEric Biggers #include <crypto/sha2.h>
12416d8220SZaibo Xu #include <crypto/skcipher.h>
13416d8220SZaibo Xu #include <crypto/xts.h>
14416d8220SZaibo Xu #include <linux/crypto.h>
15416d8220SZaibo Xu #include <linux/dma-mapping.h>
16416d8220SZaibo Xu #include <linux/idr.h>
17416d8220SZaibo Xu 
18416d8220SZaibo Xu #include "sec.h"
19416d8220SZaibo Xu #include "sec_crypto.h"
20416d8220SZaibo Xu 
21416d8220SZaibo Xu #define SEC_PRIORITY		4001
22416d8220SZaibo Xu #define SEC_XTS_MIN_KEY_SIZE	(2 * AES_MIN_KEY_SIZE)
23416d8220SZaibo Xu #define SEC_XTS_MAX_KEY_SIZE	(2 * AES_MAX_KEY_SIZE)
24416d8220SZaibo Xu #define SEC_DES3_2KEY_SIZE	(2 * DES_KEY_SIZE)
25416d8220SZaibo Xu #define SEC_DES3_3KEY_SIZE	(3 * DES_KEY_SIZE)
26416d8220SZaibo Xu 
27416d8220SZaibo Xu /* SEC sqe(bd) bit operational relative MACRO */
28416d8220SZaibo Xu #define SEC_DE_OFFSET		1
29416d8220SZaibo Xu #define SEC_CIPHER_OFFSET	4
30416d8220SZaibo Xu #define SEC_SCENE_OFFSET	3
31416d8220SZaibo Xu #define SEC_DST_SGL_OFFSET	2
32416d8220SZaibo Xu #define SEC_SRC_SGL_OFFSET	7
33416d8220SZaibo Xu #define SEC_CKEY_OFFSET		9
34416d8220SZaibo Xu #define SEC_CMODE_OFFSET	12
352f072d75SZaibo Xu #define SEC_AKEY_OFFSET         5
362f072d75SZaibo Xu #define SEC_AEAD_ALG_OFFSET     11
372f072d75SZaibo Xu #define SEC_AUTH_OFFSET		6
382f072d75SZaibo Xu 
39416d8220SZaibo Xu #define SEC_FLAG_OFFSET		7
40416d8220SZaibo Xu #define SEC_FLAG_MASK		0x0780
41416d8220SZaibo Xu #define SEC_TYPE_MASK		0x0F
42416d8220SZaibo Xu #define SEC_DONE_MASK		0x0001
43416d8220SZaibo Xu 
44416d8220SZaibo Xu #define SEC_TOTAL_IV_SZ		(SEC_IV_SIZE * QM_Q_DEPTH)
45416d8220SZaibo Xu #define SEC_SGL_SGE_NR		128
46416d8220SZaibo Xu #define SEC_CTX_DEV(ctx)	(&(ctx)->sec->qm.pdev->dev)
472f072d75SZaibo Xu #define SEC_CIPHER_AUTH		0xfe
482f072d75SZaibo Xu #define SEC_AUTH_CIPHER		0x1
492f072d75SZaibo Xu #define SEC_MAX_MAC_LEN		64
502514f559SLongfang Liu #define SEC_MAX_AAD_LEN		65535
512f072d75SZaibo Xu #define SEC_TOTAL_MAC_SZ	(SEC_MAX_MAC_LEN * QM_Q_DEPTH)
5274b58db8SLongfang Liu 
5374b58db8SLongfang Liu #define SEC_PBUF_SZ			512
5474b58db8SLongfang Liu #define SEC_PBUF_IV_OFFSET		SEC_PBUF_SZ
5574b58db8SLongfang Liu #define SEC_PBUF_MAC_OFFSET		(SEC_PBUF_SZ + SEC_IV_SIZE)
5674b58db8SLongfang Liu #define SEC_PBUF_PKG		(SEC_PBUF_SZ + SEC_IV_SIZE +	\
5774b58db8SLongfang Liu 			SEC_MAX_MAC_LEN * 2)
5874b58db8SLongfang Liu #define SEC_PBUF_NUM		(PAGE_SIZE / SEC_PBUF_PKG)
5974b58db8SLongfang Liu #define SEC_PBUF_PAGE_NUM	(QM_Q_DEPTH / SEC_PBUF_NUM)
6074b58db8SLongfang Liu #define SEC_PBUF_LEFT_SZ	(SEC_PBUF_PKG * (QM_Q_DEPTH -	\
6174b58db8SLongfang Liu 			SEC_PBUF_PAGE_NUM * SEC_PBUF_NUM))
6274b58db8SLongfang Liu #define SEC_TOTAL_PBUF_SZ	(PAGE_SIZE * SEC_PBUF_PAGE_NUM +	\
6374b58db8SLongfang Liu 			SEC_PBUF_LEFT_SZ)
6474b58db8SLongfang Liu 
652f072d75SZaibo Xu #define SEC_SQE_LEN_RATE	4
66d6de2a59SZaibo Xu #define SEC_SQE_CFLAG		2
672f072d75SZaibo Xu #define SEC_SQE_AEAD_FLAG	3
68d6de2a59SZaibo Xu #define SEC_SQE_DONE		0x1
69416d8220SZaibo Xu 
70416d8220SZaibo Xu /* Get an en/de-cipher queue cyclically to balance load over queues of TFM */
71a181647cSZaibo Xu static inline int sec_alloc_queue_id(struct sec_ctx *ctx, struct sec_req *req)
72416d8220SZaibo Xu {
73416d8220SZaibo Xu 	if (req->c_req.encrypt)
74416d8220SZaibo Xu 		return (u32)atomic_inc_return(&ctx->enc_qcyclic) %
75416d8220SZaibo Xu 				 ctx->hlf_q_num;
76416d8220SZaibo Xu 
77416d8220SZaibo Xu 	return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num +
78416d8220SZaibo Xu 				 ctx->hlf_q_num;
79416d8220SZaibo Xu }
80416d8220SZaibo Xu 
81a181647cSZaibo Xu static inline void sec_free_queue_id(struct sec_ctx *ctx, struct sec_req *req)
82416d8220SZaibo Xu {
83416d8220SZaibo Xu 	if (req->c_req.encrypt)
84416d8220SZaibo Xu 		atomic_dec(&ctx->enc_qcyclic);
85416d8220SZaibo Xu 	else
86416d8220SZaibo Xu 		atomic_dec(&ctx->dec_qcyclic);
87416d8220SZaibo Xu }
88416d8220SZaibo Xu 
89416d8220SZaibo Xu static int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx)
90416d8220SZaibo Xu {
91416d8220SZaibo Xu 	int req_id;
92416d8220SZaibo Xu 
93416d8220SZaibo Xu 	mutex_lock(&qp_ctx->req_lock);
94416d8220SZaibo Xu 
95416d8220SZaibo Xu 	req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL,
96416d8220SZaibo Xu 				  0, QM_Q_DEPTH, GFP_ATOMIC);
97416d8220SZaibo Xu 	mutex_unlock(&qp_ctx->req_lock);
98b9c8d897SZaibo Xu 	if (unlikely(req_id < 0)) {
99416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "alloc req id fail!\n");
100416d8220SZaibo Xu 		return req_id;
101416d8220SZaibo Xu 	}
102416d8220SZaibo Xu 
103416d8220SZaibo Xu 	req->qp_ctx = qp_ctx;
104416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = req;
105633e507fSLongfang Liu 
106416d8220SZaibo Xu 	return req_id;
107416d8220SZaibo Xu }
108416d8220SZaibo Xu 
109416d8220SZaibo Xu static void sec_free_req_id(struct sec_req *req)
110416d8220SZaibo Xu {
111416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
112416d8220SZaibo Xu 	int req_id = req->req_id;
113416d8220SZaibo Xu 
114b9c8d897SZaibo Xu 	if (unlikely(req_id < 0 || req_id >= QM_Q_DEPTH)) {
115416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "free request id invalid!\n");
116416d8220SZaibo Xu 		return;
117416d8220SZaibo Xu 	}
118416d8220SZaibo Xu 
119416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = NULL;
120416d8220SZaibo Xu 	req->qp_ctx = NULL;
121416d8220SZaibo Xu 
122416d8220SZaibo Xu 	mutex_lock(&qp_ctx->req_lock);
123416d8220SZaibo Xu 	idr_remove(&qp_ctx->req_idr, req_id);
124416d8220SZaibo Xu 	mutex_unlock(&qp_ctx->req_lock);
125416d8220SZaibo Xu }
126416d8220SZaibo Xu 
1272514f559SLongfang Liu static int sec_aead_verify(struct sec_req *req)
1282f072d75SZaibo Xu {
1292f072d75SZaibo Xu 	struct aead_request *aead_req = req->aead_req.aead_req;
1302f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
1312f072d75SZaibo Xu 	size_t authsize = crypto_aead_authsize(tfm);
1322514f559SLongfang Liu 	u8 *mac_out = req->aead_req.out_mac;
1332f072d75SZaibo Xu 	u8 *mac = mac_out + SEC_MAX_MAC_LEN;
1342f072d75SZaibo Xu 	struct scatterlist *sgl = aead_req->src;
1352f072d75SZaibo Xu 	size_t sz;
1362f072d75SZaibo Xu 
1372f072d75SZaibo Xu 	sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), mac, authsize,
1382f072d75SZaibo Xu 				aead_req->cryptlen + aead_req->assoclen -
1392f072d75SZaibo Xu 				authsize);
1402f072d75SZaibo Xu 	if (unlikely(sz != authsize || memcmp(mac_out, mac, sz))) {
1412f072d75SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "aead verify failure!\n");
1422f072d75SZaibo Xu 		return -EBADMSG;
1432f072d75SZaibo Xu 	}
1442f072d75SZaibo Xu 
1452f072d75SZaibo Xu 	return 0;
1462f072d75SZaibo Xu }
1472f072d75SZaibo Xu 
148416d8220SZaibo Xu static void sec_req_cb(struct hisi_qp *qp, void *resp)
149416d8220SZaibo Xu {
150416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = qp->qp_ctx;
1518213a1a6SKai Ye 	struct sec_dfx *dfx = &qp_ctx->ctx->sec->debug.dfx;
152416d8220SZaibo Xu 	struct sec_sqe *bd = resp;
153d6de2a59SZaibo Xu 	struct sec_ctx *ctx;
154d6de2a59SZaibo Xu 	struct sec_req *req;
155416d8220SZaibo Xu 	u16 done, flag;
156310ea0acSZaibo Xu 	int err = 0;
157416d8220SZaibo Xu 	u8 type;
158416d8220SZaibo Xu 
159416d8220SZaibo Xu 	type = bd->type_cipher_auth & SEC_TYPE_MASK;
160b9c8d897SZaibo Xu 	if (unlikely(type != SEC_BD_TYPE2)) {
1618213a1a6SKai Ye 		atomic64_inc(&dfx->err_bd_cnt);
162416d8220SZaibo Xu 		pr_err("err bd type [%d]\n", type);
163416d8220SZaibo Xu 		return;
164416d8220SZaibo Xu 	}
165416d8220SZaibo Xu 
166d6de2a59SZaibo Xu 	req = qp_ctx->req_list[le16_to_cpu(bd->type2.tag)];
1678213a1a6SKai Ye 	if (unlikely(!req)) {
1688213a1a6SKai Ye 		atomic64_inc(&dfx->invalid_req_cnt);
1699597efc3SKai Ye 		atomic_inc(&qp->qp_status.used);
1708213a1a6SKai Ye 		return;
1718213a1a6SKai Ye 	}
172d6de2a59SZaibo Xu 	req->err_type = bd->type2.error_type;
173d6de2a59SZaibo Xu 	ctx = req->ctx;
174d6de2a59SZaibo Xu 	done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK;
175d6de2a59SZaibo Xu 	flag = (le16_to_cpu(bd->type2.done_flag) &
176d6de2a59SZaibo Xu 		SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
1772f072d75SZaibo Xu 	if (unlikely(req->err_type || done != SEC_SQE_DONE ||
1782f072d75SZaibo Xu 	    (ctx->alg_type == SEC_SKCIPHER && flag != SEC_SQE_CFLAG) ||
1792f072d75SZaibo Xu 	    (ctx->alg_type == SEC_AEAD && flag != SEC_SQE_AEAD_FLAG))) {
180d6de2a59SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx),
181d6de2a59SZaibo Xu 			"err_type[%d],done[%d],flag[%d]\n",
182d6de2a59SZaibo Xu 			req->err_type, done, flag);
183310ea0acSZaibo Xu 		err = -EIO;
1848213a1a6SKai Ye 		atomic64_inc(&dfx->done_flag_cnt);
185310ea0acSZaibo Xu 	}
1861e9bc276SZaibo Xu 
1872f072d75SZaibo Xu 	if (ctx->alg_type == SEC_AEAD && !req->c_req.encrypt)
1882514f559SLongfang Liu 		err = sec_aead_verify(req);
1892f072d75SZaibo Xu 
1908213a1a6SKai Ye 	atomic64_inc(&dfx->recv_cnt);
191416d8220SZaibo Xu 
192d6de2a59SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
193d6de2a59SZaibo Xu 
194310ea0acSZaibo Xu 	ctx->req_op->callback(ctx, req, err);
195416d8220SZaibo Xu }
196416d8220SZaibo Xu 
197416d8220SZaibo Xu static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req)
198416d8220SZaibo Xu {
199416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
200416d8220SZaibo Xu 	int ret;
201416d8220SZaibo Xu 
2029597efc3SKai Ye 	if (ctx->fake_req_limit <=
2039597efc3SKai Ye 	    atomic_read(&qp_ctx->qp->qp_status.used) &&
2049597efc3SKai Ye 	    !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG))
2059597efc3SKai Ye 		return -EBUSY;
2069597efc3SKai Ye 
207416d8220SZaibo Xu 	mutex_lock(&qp_ctx->req_lock);
208416d8220SZaibo Xu 	ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
2099597efc3SKai Ye 
2109597efc3SKai Ye 	if (ctx->fake_req_limit <=
2119597efc3SKai Ye 	    atomic_read(&qp_ctx->qp->qp_status.used) && !ret) {
2129597efc3SKai Ye 		list_add_tail(&req->backlog_head, &qp_ctx->backlog);
213cb1eeb75SArnd Bergmann 		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
2149597efc3SKai Ye 		atomic64_inc(&ctx->sec->debug.dfx.send_busy_cnt);
2159597efc3SKai Ye 		mutex_unlock(&qp_ctx->req_lock);
2169597efc3SKai Ye 		return -EBUSY;
2179597efc3SKai Ye 	}
2189597efc3SKai Ye 	mutex_unlock(&qp_ctx->req_lock);
219416d8220SZaibo Xu 
220b9c8d897SZaibo Xu 	if (unlikely(ret == -EBUSY))
221416d8220SZaibo Xu 		return -ENOBUFS;
222416d8220SZaibo Xu 
2239597efc3SKai Ye 	if (likely(!ret)) {
224416d8220SZaibo Xu 		ret = -EINPROGRESS;
2259597efc3SKai Ye 		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
2268213a1a6SKai Ye 	}
227416d8220SZaibo Xu 
228416d8220SZaibo Xu 	return ret;
229416d8220SZaibo Xu }
230416d8220SZaibo Xu 
2317c7d902aSZaibo Xu /* Get DMA memory resources */
2327c7d902aSZaibo Xu static int sec_alloc_civ_resource(struct device *dev, struct sec_alg_res *res)
2337c7d902aSZaibo Xu {
2347c7d902aSZaibo Xu 	int i;
2357c7d902aSZaibo Xu 
2367c7d902aSZaibo Xu 	res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ,
2377c7d902aSZaibo Xu 					 &res->c_ivin_dma, GFP_KERNEL);
2387c7d902aSZaibo Xu 	if (!res->c_ivin)
2397c7d902aSZaibo Xu 		return -ENOMEM;
2407c7d902aSZaibo Xu 
2417c7d902aSZaibo Xu 	for (i = 1; i < QM_Q_DEPTH; i++) {
2427c7d902aSZaibo Xu 		res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE;
2437c7d902aSZaibo Xu 		res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE;
2447c7d902aSZaibo Xu 	}
2457c7d902aSZaibo Xu 
2467c7d902aSZaibo Xu 	return 0;
2477c7d902aSZaibo Xu }
2487c7d902aSZaibo Xu 
2497c7d902aSZaibo Xu static void sec_free_civ_resource(struct device *dev, struct sec_alg_res *res)
2507c7d902aSZaibo Xu {
2517c7d902aSZaibo Xu 	if (res->c_ivin)
2527c7d902aSZaibo Xu 		dma_free_coherent(dev, SEC_TOTAL_IV_SZ,
2537c7d902aSZaibo Xu 				  res->c_ivin, res->c_ivin_dma);
2547c7d902aSZaibo Xu }
2557c7d902aSZaibo Xu 
2562f072d75SZaibo Xu static int sec_alloc_mac_resource(struct device *dev, struct sec_alg_res *res)
2572f072d75SZaibo Xu {
2582f072d75SZaibo Xu 	int i;
2592f072d75SZaibo Xu 
2602f072d75SZaibo Xu 	res->out_mac = dma_alloc_coherent(dev, SEC_TOTAL_MAC_SZ << 1,
2612f072d75SZaibo Xu 					  &res->out_mac_dma, GFP_KERNEL);
2622f072d75SZaibo Xu 	if (!res->out_mac)
2632f072d75SZaibo Xu 		return -ENOMEM;
2642f072d75SZaibo Xu 
2652f072d75SZaibo Xu 	for (i = 1; i < QM_Q_DEPTH; i++) {
2662f072d75SZaibo Xu 		res[i].out_mac_dma = res->out_mac_dma +
2672f072d75SZaibo Xu 				     i * (SEC_MAX_MAC_LEN << 1);
2682f072d75SZaibo Xu 		res[i].out_mac = res->out_mac + i * (SEC_MAX_MAC_LEN << 1);
2692f072d75SZaibo Xu 	}
2702f072d75SZaibo Xu 
2712f072d75SZaibo Xu 	return 0;
2722f072d75SZaibo Xu }
2732f072d75SZaibo Xu 
2742f072d75SZaibo Xu static void sec_free_mac_resource(struct device *dev, struct sec_alg_res *res)
2752f072d75SZaibo Xu {
2762f072d75SZaibo Xu 	if (res->out_mac)
2772f072d75SZaibo Xu 		dma_free_coherent(dev, SEC_TOTAL_MAC_SZ << 1,
2782f072d75SZaibo Xu 				  res->out_mac, res->out_mac_dma);
2792f072d75SZaibo Xu }
2802f072d75SZaibo Xu 
28174b58db8SLongfang Liu static void sec_free_pbuf_resource(struct device *dev, struct sec_alg_res *res)
28274b58db8SLongfang Liu {
28374b58db8SLongfang Liu 	if (res->pbuf)
28474b58db8SLongfang Liu 		dma_free_coherent(dev, SEC_TOTAL_PBUF_SZ,
28574b58db8SLongfang Liu 				  res->pbuf, res->pbuf_dma);
28674b58db8SLongfang Liu }
28774b58db8SLongfang Liu 
28874b58db8SLongfang Liu /*
28974b58db8SLongfang Liu  * To improve performance, pbuffer is used for
29074b58db8SLongfang Liu  * small packets (< 512Bytes) as IOMMU translation using.
29174b58db8SLongfang Liu  */
29274b58db8SLongfang Liu static int sec_alloc_pbuf_resource(struct device *dev, struct sec_alg_res *res)
29374b58db8SLongfang Liu {
29474b58db8SLongfang Liu 	int pbuf_page_offset;
29574b58db8SLongfang Liu 	int i, j, k;
29674b58db8SLongfang Liu 
29774b58db8SLongfang Liu 	res->pbuf = dma_alloc_coherent(dev, SEC_TOTAL_PBUF_SZ,
29874b58db8SLongfang Liu 				&res->pbuf_dma, GFP_KERNEL);
29974b58db8SLongfang Liu 	if (!res->pbuf)
30074b58db8SLongfang Liu 		return -ENOMEM;
30174b58db8SLongfang Liu 
30274b58db8SLongfang Liu 	/*
30374b58db8SLongfang Liu 	 * SEC_PBUF_PKG contains data pbuf, iv and
30474b58db8SLongfang Liu 	 * out_mac : <SEC_PBUF|SEC_IV|SEC_MAC>
30574b58db8SLongfang Liu 	 * Every PAGE contains six SEC_PBUF_PKG
30674b58db8SLongfang Liu 	 * The sec_qp_ctx contains QM_Q_DEPTH numbers of SEC_PBUF_PKG
30774b58db8SLongfang Liu 	 * So we need SEC_PBUF_PAGE_NUM numbers of PAGE
30874b58db8SLongfang Liu 	 * for the SEC_TOTAL_PBUF_SZ
30974b58db8SLongfang Liu 	 */
31074b58db8SLongfang Liu 	for (i = 0; i <= SEC_PBUF_PAGE_NUM; i++) {
31174b58db8SLongfang Liu 		pbuf_page_offset = PAGE_SIZE * i;
31274b58db8SLongfang Liu 		for (j = 0; j < SEC_PBUF_NUM; j++) {
31374b58db8SLongfang Liu 			k = i * SEC_PBUF_NUM + j;
31474b58db8SLongfang Liu 			if (k == QM_Q_DEPTH)
31574b58db8SLongfang Liu 				break;
31674b58db8SLongfang Liu 			res[k].pbuf = res->pbuf +
31774b58db8SLongfang Liu 				j * SEC_PBUF_PKG + pbuf_page_offset;
31874b58db8SLongfang Liu 			res[k].pbuf_dma = res->pbuf_dma +
31974b58db8SLongfang Liu 				j * SEC_PBUF_PKG + pbuf_page_offset;
32074b58db8SLongfang Liu 		}
32174b58db8SLongfang Liu 	}
322633e507fSLongfang Liu 
32374b58db8SLongfang Liu 	return 0;
32474b58db8SLongfang Liu }
32574b58db8SLongfang Liu 
3267c7d902aSZaibo Xu static int sec_alg_resource_alloc(struct sec_ctx *ctx,
3277c7d902aSZaibo Xu 				  struct sec_qp_ctx *qp_ctx)
3287c7d902aSZaibo Xu {
3297c7d902aSZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
3302f072d75SZaibo Xu 	struct sec_alg_res *res = qp_ctx->res;
3312f072d75SZaibo Xu 	int ret;
3327c7d902aSZaibo Xu 
3332f072d75SZaibo Xu 	ret = sec_alloc_civ_resource(dev, res);
3342f072d75SZaibo Xu 	if (ret)
3352f072d75SZaibo Xu 		return ret;
3362f072d75SZaibo Xu 
3372f072d75SZaibo Xu 	if (ctx->alg_type == SEC_AEAD) {
3382f072d75SZaibo Xu 		ret = sec_alloc_mac_resource(dev, res);
3392f072d75SZaibo Xu 		if (ret)
3402514f559SLongfang Liu 			goto alloc_fail;
3412f072d75SZaibo Xu 	}
34274b58db8SLongfang Liu 	if (ctx->pbuf_supported) {
34374b58db8SLongfang Liu 		ret = sec_alloc_pbuf_resource(dev, res);
34474b58db8SLongfang Liu 		if (ret) {
34574b58db8SLongfang Liu 			dev_err(dev, "fail to alloc pbuf dma resource!\n");
34624efcec2SLongfang Liu 			goto alloc_pbuf_fail;
34774b58db8SLongfang Liu 		}
34874b58db8SLongfang Liu 	}
3492f072d75SZaibo Xu 
3502f072d75SZaibo Xu 	return 0;
351633e507fSLongfang Liu 
35224efcec2SLongfang Liu alloc_pbuf_fail:
35324efcec2SLongfang Liu 	if (ctx->alg_type == SEC_AEAD)
35424efcec2SLongfang Liu 		sec_free_mac_resource(dev, qp_ctx->res);
3552514f559SLongfang Liu alloc_fail:
3562f072d75SZaibo Xu 	sec_free_civ_resource(dev, res);
3572f072d75SZaibo Xu 	return ret;
3587c7d902aSZaibo Xu }
3597c7d902aSZaibo Xu 
3607c7d902aSZaibo Xu static void sec_alg_resource_free(struct sec_ctx *ctx,
3617c7d902aSZaibo Xu 				  struct sec_qp_ctx *qp_ctx)
3627c7d902aSZaibo Xu {
3637c7d902aSZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
3647c7d902aSZaibo Xu 
3657c7d902aSZaibo Xu 	sec_free_civ_resource(dev, qp_ctx->res);
3662f072d75SZaibo Xu 
36774b58db8SLongfang Liu 	if (ctx->pbuf_supported)
36874b58db8SLongfang Liu 		sec_free_pbuf_resource(dev, qp_ctx->res);
3692f072d75SZaibo Xu 	if (ctx->alg_type == SEC_AEAD)
3702f072d75SZaibo Xu 		sec_free_mac_resource(dev, qp_ctx->res);
3717c7d902aSZaibo Xu }
3727c7d902aSZaibo Xu 
373416d8220SZaibo Xu static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx,
374416d8220SZaibo Xu 			     int qp_ctx_id, int alg_type)
375416d8220SZaibo Xu {
376416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
377416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
378416d8220SZaibo Xu 	struct hisi_qp *qp;
379416d8220SZaibo Xu 	int ret = -ENOMEM;
380416d8220SZaibo Xu 
381416d8220SZaibo Xu 	qp_ctx = &ctx->qp_ctx[qp_ctx_id];
3820b5e43bcSKai Ye 	qp = ctx->qps[qp_ctx_id];
383416d8220SZaibo Xu 	qp->req_type = 0;
384416d8220SZaibo Xu 	qp->qp_ctx = qp_ctx;
385416d8220SZaibo Xu 	qp->req_cb = sec_req_cb;
386416d8220SZaibo Xu 	qp_ctx->qp = qp;
387416d8220SZaibo Xu 	qp_ctx->ctx = ctx;
388416d8220SZaibo Xu 
389416d8220SZaibo Xu 	mutex_init(&qp_ctx->req_lock);
390416d8220SZaibo Xu 	idr_init(&qp_ctx->req_idr);
3919597efc3SKai Ye 	INIT_LIST_HEAD(&qp_ctx->backlog);
392416d8220SZaibo Xu 
393416d8220SZaibo Xu 	qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
394416d8220SZaibo Xu 						     SEC_SGL_SGE_NR);
3958a6b8f4dSDan Carpenter 	if (IS_ERR(qp_ctx->c_in_pool)) {
396416d8220SZaibo Xu 		dev_err(dev, "fail to create sgl pool for input!\n");
3977c7d902aSZaibo Xu 		goto err_destroy_idr;
398416d8220SZaibo Xu 	}
399416d8220SZaibo Xu 
400416d8220SZaibo Xu 	qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
401416d8220SZaibo Xu 						      SEC_SGL_SGE_NR);
4028a6b8f4dSDan Carpenter 	if (IS_ERR(qp_ctx->c_out_pool)) {
403416d8220SZaibo Xu 		dev_err(dev, "fail to create sgl pool for output!\n");
404416d8220SZaibo Xu 		goto err_free_c_in_pool;
405416d8220SZaibo Xu 	}
406416d8220SZaibo Xu 
4077c7d902aSZaibo Xu 	ret = sec_alg_resource_alloc(ctx, qp_ctx);
408416d8220SZaibo Xu 	if (ret)
409416d8220SZaibo Xu 		goto err_free_c_out_pool;
410416d8220SZaibo Xu 
411416d8220SZaibo Xu 	ret = hisi_qm_start_qp(qp, 0);
412416d8220SZaibo Xu 	if (ret < 0)
413416d8220SZaibo Xu 		goto err_queue_free;
414416d8220SZaibo Xu 
415416d8220SZaibo Xu 	return 0;
416416d8220SZaibo Xu 
417416d8220SZaibo Xu err_queue_free:
4187c7d902aSZaibo Xu 	sec_alg_resource_free(ctx, qp_ctx);
419416d8220SZaibo Xu err_free_c_out_pool:
420416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
421416d8220SZaibo Xu err_free_c_in_pool:
422416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
423416d8220SZaibo Xu err_destroy_idr:
424416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
425416d8220SZaibo Xu 	return ret;
426416d8220SZaibo Xu }
427416d8220SZaibo Xu 
428416d8220SZaibo Xu static void sec_release_qp_ctx(struct sec_ctx *ctx,
429416d8220SZaibo Xu 			       struct sec_qp_ctx *qp_ctx)
430416d8220SZaibo Xu {
431416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
432416d8220SZaibo Xu 
433416d8220SZaibo Xu 	hisi_qm_stop_qp(qp_ctx->qp);
4347c7d902aSZaibo Xu 	sec_alg_resource_free(ctx, qp_ctx);
435416d8220SZaibo Xu 
436416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
437416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
438416d8220SZaibo Xu 
439416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
440416d8220SZaibo Xu }
441416d8220SZaibo Xu 
442473a0f96SZaibo Xu static int sec_ctx_base_init(struct sec_ctx *ctx)
443416d8220SZaibo Xu {
444416d8220SZaibo Xu 	struct sec_dev *sec;
445416d8220SZaibo Xu 	int i, ret;
446416d8220SZaibo Xu 
4470b5e43bcSKai Ye 	ctx->qps = sec_create_qps();
4480b5e43bcSKai Ye 	if (!ctx->qps) {
4490b5e43bcSKai Ye 		pr_err("Can not create sec qps!\n");
450416d8220SZaibo Xu 		return -ENODEV;
451416d8220SZaibo Xu 	}
4520b5e43bcSKai Ye 
4530b5e43bcSKai Ye 	sec = container_of(ctx->qps[0]->qm, struct sec_dev, qm);
454416d8220SZaibo Xu 	ctx->sec = sec;
455a718cfceSZaibo Xu 	ctx->hlf_q_num = sec->ctx_q_num >> 1;
456416d8220SZaibo Xu 
45774b58db8SLongfang Liu 	ctx->pbuf_supported = ctx->sec->iommu_used;
45874b58db8SLongfang Liu 
459416d8220SZaibo Xu 	/* Half of queue depth is taken as fake requests limit in the queue. */
460a718cfceSZaibo Xu 	ctx->fake_req_limit = QM_Q_DEPTH >> 1;
461416d8220SZaibo Xu 	ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx),
462416d8220SZaibo Xu 			      GFP_KERNEL);
46324efcec2SLongfang Liu 	if (!ctx->qp_ctx) {
46424efcec2SLongfang Liu 		ret = -ENOMEM;
46524efcec2SLongfang Liu 		goto err_destroy_qps;
46624efcec2SLongfang Liu 	}
467416d8220SZaibo Xu 
468416d8220SZaibo Xu 	for (i = 0; i < sec->ctx_q_num; i++) {
469473a0f96SZaibo Xu 		ret = sec_create_qp_ctx(&sec->qm, ctx, i, 0);
470416d8220SZaibo Xu 		if (ret)
471416d8220SZaibo Xu 			goto err_sec_release_qp_ctx;
472416d8220SZaibo Xu 	}
473416d8220SZaibo Xu 
474416d8220SZaibo Xu 	return 0;
47524efcec2SLongfang Liu 
476416d8220SZaibo Xu err_sec_release_qp_ctx:
477416d8220SZaibo Xu 	for (i = i - 1; i >= 0; i--)
478416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
479416d8220SZaibo Xu 
480416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
48124efcec2SLongfang Liu err_destroy_qps:
48224efcec2SLongfang Liu 	sec_destroy_qps(ctx->qps, sec->ctx_q_num);
48324efcec2SLongfang Liu 
484416d8220SZaibo Xu 	return ret;
485416d8220SZaibo Xu }
486416d8220SZaibo Xu 
487473a0f96SZaibo Xu static void sec_ctx_base_uninit(struct sec_ctx *ctx)
488416d8220SZaibo Xu {
489473a0f96SZaibo Xu 	int i;
490416d8220SZaibo Xu 
491416d8220SZaibo Xu 	for (i = 0; i < ctx->sec->ctx_q_num; i++)
492416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
493416d8220SZaibo Xu 
4940b5e43bcSKai Ye 	sec_destroy_qps(ctx->qps, ctx->sec->ctx_q_num);
495416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
496416d8220SZaibo Xu }
497416d8220SZaibo Xu 
498473a0f96SZaibo Xu static int sec_cipher_init(struct sec_ctx *ctx)
499473a0f96SZaibo Xu {
500473a0f96SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
501473a0f96SZaibo Xu 
502473a0f96SZaibo Xu 	c_ctx->c_key = dma_alloc_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
503473a0f96SZaibo Xu 					  &c_ctx->c_key_dma, GFP_KERNEL);
504473a0f96SZaibo Xu 	if (!c_ctx->c_key)
505473a0f96SZaibo Xu 		return -ENOMEM;
506473a0f96SZaibo Xu 
507473a0f96SZaibo Xu 	return 0;
508473a0f96SZaibo Xu }
509473a0f96SZaibo Xu 
510473a0f96SZaibo Xu static void sec_cipher_uninit(struct sec_ctx *ctx)
511473a0f96SZaibo Xu {
512473a0f96SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
513473a0f96SZaibo Xu 
514473a0f96SZaibo Xu 	memzero_explicit(c_ctx->c_key, SEC_MAX_KEY_SIZE);
515473a0f96SZaibo Xu 	dma_free_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
516473a0f96SZaibo Xu 			  c_ctx->c_key, c_ctx->c_key_dma);
517473a0f96SZaibo Xu }
518473a0f96SZaibo Xu 
5192f072d75SZaibo Xu static int sec_auth_init(struct sec_ctx *ctx)
5202f072d75SZaibo Xu {
5212f072d75SZaibo Xu 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
5222f072d75SZaibo Xu 
5232f072d75SZaibo Xu 	a_ctx->a_key = dma_alloc_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
5242f072d75SZaibo Xu 					  &a_ctx->a_key_dma, GFP_KERNEL);
5252f072d75SZaibo Xu 	if (!a_ctx->a_key)
5262f072d75SZaibo Xu 		return -ENOMEM;
5272f072d75SZaibo Xu 
5282f072d75SZaibo Xu 	return 0;
5292f072d75SZaibo Xu }
5302f072d75SZaibo Xu 
5312f072d75SZaibo Xu static void sec_auth_uninit(struct sec_ctx *ctx)
5322f072d75SZaibo Xu {
5332f072d75SZaibo Xu 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
5342f072d75SZaibo Xu 
5352f072d75SZaibo Xu 	memzero_explicit(a_ctx->a_key, SEC_MAX_KEY_SIZE);
5362f072d75SZaibo Xu 	dma_free_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
5372f072d75SZaibo Xu 			  a_ctx->a_key, a_ctx->a_key_dma);
5382f072d75SZaibo Xu }
5392f072d75SZaibo Xu 
540473a0f96SZaibo Xu static int sec_skcipher_init(struct crypto_skcipher *tfm)
541473a0f96SZaibo Xu {
542473a0f96SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
543473a0f96SZaibo Xu 	int ret;
544473a0f96SZaibo Xu 
5452f072d75SZaibo Xu 	ctx->alg_type = SEC_SKCIPHER;
546473a0f96SZaibo Xu 	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req));
547473a0f96SZaibo Xu 	ctx->c_ctx.ivsize = crypto_skcipher_ivsize(tfm);
548473a0f96SZaibo Xu 	if (ctx->c_ctx.ivsize > SEC_IV_SIZE) {
549473a0f96SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "get error skcipher iv size!\n");
550473a0f96SZaibo Xu 		return -EINVAL;
551473a0f96SZaibo Xu 	}
552473a0f96SZaibo Xu 
553473a0f96SZaibo Xu 	ret = sec_ctx_base_init(ctx);
554473a0f96SZaibo Xu 	if (ret)
555473a0f96SZaibo Xu 		return ret;
556473a0f96SZaibo Xu 
557473a0f96SZaibo Xu 	ret = sec_cipher_init(ctx);
558473a0f96SZaibo Xu 	if (ret)
559473a0f96SZaibo Xu 		goto err_cipher_init;
560473a0f96SZaibo Xu 
561473a0f96SZaibo Xu 	return 0;
562633e507fSLongfang Liu 
563473a0f96SZaibo Xu err_cipher_init:
564473a0f96SZaibo Xu 	sec_ctx_base_uninit(ctx);
565473a0f96SZaibo Xu 	return ret;
566473a0f96SZaibo Xu }
567473a0f96SZaibo Xu 
568473a0f96SZaibo Xu static void sec_skcipher_uninit(struct crypto_skcipher *tfm)
569473a0f96SZaibo Xu {
570473a0f96SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
571473a0f96SZaibo Xu 
572473a0f96SZaibo Xu 	sec_cipher_uninit(ctx);
573473a0f96SZaibo Xu 	sec_ctx_base_uninit(ctx);
574473a0f96SZaibo Xu }
575473a0f96SZaibo Xu 
576416d8220SZaibo Xu static int sec_skcipher_3des_setkey(struct sec_cipher_ctx *c_ctx,
577416d8220SZaibo Xu 				    const u32 keylen,
578416d8220SZaibo Xu 				    const enum sec_cmode c_mode)
579416d8220SZaibo Xu {
580416d8220SZaibo Xu 	switch (keylen) {
581416d8220SZaibo Xu 	case SEC_DES3_2KEY_SIZE:
582416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_2KEY;
583416d8220SZaibo Xu 		break;
584416d8220SZaibo Xu 	case SEC_DES3_3KEY_SIZE:
585416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_3KEY;
586416d8220SZaibo Xu 		break;
587416d8220SZaibo Xu 	default:
588416d8220SZaibo Xu 		return -EINVAL;
589416d8220SZaibo Xu 	}
590416d8220SZaibo Xu 
591416d8220SZaibo Xu 	return 0;
592416d8220SZaibo Xu }
593416d8220SZaibo Xu 
594416d8220SZaibo Xu static int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx,
595416d8220SZaibo Xu 				       const u32 keylen,
596416d8220SZaibo Xu 				       const enum sec_cmode c_mode)
597416d8220SZaibo Xu {
598416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
599416d8220SZaibo Xu 		switch (keylen) {
600416d8220SZaibo Xu 		case SEC_XTS_MIN_KEY_SIZE:
601416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_128BIT;
602416d8220SZaibo Xu 			break;
603416d8220SZaibo Xu 		case SEC_XTS_MAX_KEY_SIZE:
604416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_256BIT;
605416d8220SZaibo Xu 			break;
606416d8220SZaibo Xu 		default:
607416d8220SZaibo Xu 			pr_err("hisi_sec2: xts mode key error!\n");
608416d8220SZaibo Xu 			return -EINVAL;
609416d8220SZaibo Xu 		}
610416d8220SZaibo Xu 	} else {
611416d8220SZaibo Xu 		switch (keylen) {
612416d8220SZaibo Xu 		case AES_KEYSIZE_128:
613416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_128BIT;
614416d8220SZaibo Xu 			break;
615416d8220SZaibo Xu 		case AES_KEYSIZE_192:
616416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_192BIT;
617416d8220SZaibo Xu 			break;
618416d8220SZaibo Xu 		case AES_KEYSIZE_256:
619416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_256BIT;
620416d8220SZaibo Xu 			break;
621416d8220SZaibo Xu 		default:
622416d8220SZaibo Xu 			pr_err("hisi_sec2: aes key error!\n");
623416d8220SZaibo Xu 			return -EINVAL;
624416d8220SZaibo Xu 		}
625416d8220SZaibo Xu 	}
626416d8220SZaibo Xu 
627416d8220SZaibo Xu 	return 0;
628416d8220SZaibo Xu }
629416d8220SZaibo Xu 
630416d8220SZaibo Xu static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
631416d8220SZaibo Xu 			       const u32 keylen, const enum sec_calg c_alg,
632416d8220SZaibo Xu 			       const enum sec_cmode c_mode)
633416d8220SZaibo Xu {
634416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
635416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
636416d8220SZaibo Xu 	int ret;
637416d8220SZaibo Xu 
638416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
639416d8220SZaibo Xu 		ret = xts_verify_key(tfm, key, keylen);
640416d8220SZaibo Xu 		if (ret) {
641416d8220SZaibo Xu 			dev_err(SEC_CTX_DEV(ctx), "xts mode key err!\n");
642416d8220SZaibo Xu 			return ret;
643416d8220SZaibo Xu 		}
644416d8220SZaibo Xu 	}
645416d8220SZaibo Xu 
646416d8220SZaibo Xu 	c_ctx->c_alg  = c_alg;
647416d8220SZaibo Xu 	c_ctx->c_mode = c_mode;
648416d8220SZaibo Xu 
649416d8220SZaibo Xu 	switch (c_alg) {
650416d8220SZaibo Xu 	case SEC_CALG_3DES:
651416d8220SZaibo Xu 		ret = sec_skcipher_3des_setkey(c_ctx, keylen, c_mode);
652416d8220SZaibo Xu 		break;
653416d8220SZaibo Xu 	case SEC_CALG_AES:
654416d8220SZaibo Xu 	case SEC_CALG_SM4:
655416d8220SZaibo Xu 		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
656416d8220SZaibo Xu 		break;
657416d8220SZaibo Xu 	default:
658416d8220SZaibo Xu 		return -EINVAL;
659416d8220SZaibo Xu 	}
660416d8220SZaibo Xu 
661416d8220SZaibo Xu 	if (ret) {
662416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "set sec key err!\n");
663416d8220SZaibo Xu 		return ret;
664416d8220SZaibo Xu 	}
665416d8220SZaibo Xu 
666416d8220SZaibo Xu 	memcpy(c_ctx->c_key, key, keylen);
667416d8220SZaibo Xu 
668416d8220SZaibo Xu 	return 0;
669416d8220SZaibo Xu }
670416d8220SZaibo Xu 
671416d8220SZaibo Xu #define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode)			\
672416d8220SZaibo Xu static int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\
673416d8220SZaibo Xu 	u32 keylen)							\
674416d8220SZaibo Xu {									\
675416d8220SZaibo Xu 	return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode);	\
676416d8220SZaibo Xu }
677416d8220SZaibo Xu 
678416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB)
679416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC)
680416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS)
681416d8220SZaibo Xu 
682416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB)
683416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC)
684416d8220SZaibo Xu 
685416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS)
686416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC)
687416d8220SZaibo Xu 
68874b58db8SLongfang Liu static int sec_cipher_pbuf_map(struct sec_ctx *ctx, struct sec_req *req,
68974b58db8SLongfang Liu 			struct scatterlist *src)
69074b58db8SLongfang Liu {
69174b58db8SLongfang Liu 	struct aead_request *aead_req = req->aead_req.aead_req;
69274b58db8SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
69374b58db8SLongfang Liu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
69474b58db8SLongfang Liu 	struct device *dev = SEC_CTX_DEV(ctx);
69574b58db8SLongfang Liu 	int copy_size, pbuf_length;
69674b58db8SLongfang Liu 	int req_id = req->req_id;
69774b58db8SLongfang Liu 
69874b58db8SLongfang Liu 	if (ctx->alg_type == SEC_AEAD)
69974b58db8SLongfang Liu 		copy_size = aead_req->cryptlen + aead_req->assoclen;
70074b58db8SLongfang Liu 	else
70174b58db8SLongfang Liu 		copy_size = c_req->c_len;
70274b58db8SLongfang Liu 
70374b58db8SLongfang Liu 	pbuf_length = sg_copy_to_buffer(src, sg_nents(src),
70474b58db8SLongfang Liu 				qp_ctx->res[req_id].pbuf,
70574b58db8SLongfang Liu 				copy_size);
70674b58db8SLongfang Liu 
70774b58db8SLongfang Liu 	if (unlikely(pbuf_length != copy_size)) {
70874b58db8SLongfang Liu 		dev_err(dev, "copy src data to pbuf error!\n");
70974b58db8SLongfang Liu 		return -EINVAL;
71074b58db8SLongfang Liu 	}
71174b58db8SLongfang Liu 
71274b58db8SLongfang Liu 	c_req->c_in_dma = qp_ctx->res[req_id].pbuf_dma;
71374b58db8SLongfang Liu 
71474b58db8SLongfang Liu 	if (!c_req->c_in_dma) {
71574b58db8SLongfang Liu 		dev_err(dev, "fail to set pbuffer address!\n");
71674b58db8SLongfang Liu 		return -ENOMEM;
71774b58db8SLongfang Liu 	}
71874b58db8SLongfang Liu 
71974b58db8SLongfang Liu 	c_req->c_out_dma = c_req->c_in_dma;
72074b58db8SLongfang Liu 
72174b58db8SLongfang Liu 	return 0;
72274b58db8SLongfang Liu }
72374b58db8SLongfang Liu 
72474b58db8SLongfang Liu static void sec_cipher_pbuf_unmap(struct sec_ctx *ctx, struct sec_req *req,
72574b58db8SLongfang Liu 			struct scatterlist *dst)
72674b58db8SLongfang Liu {
72774b58db8SLongfang Liu 	struct aead_request *aead_req = req->aead_req.aead_req;
72874b58db8SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
72974b58db8SLongfang Liu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
73074b58db8SLongfang Liu 	struct device *dev = SEC_CTX_DEV(ctx);
73174b58db8SLongfang Liu 	int copy_size, pbuf_length;
73274b58db8SLongfang Liu 	int req_id = req->req_id;
73374b58db8SLongfang Liu 
73474b58db8SLongfang Liu 	if (ctx->alg_type == SEC_AEAD)
73574b58db8SLongfang Liu 		copy_size = c_req->c_len + aead_req->assoclen;
73674b58db8SLongfang Liu 	else
73774b58db8SLongfang Liu 		copy_size = c_req->c_len;
73874b58db8SLongfang Liu 
73974b58db8SLongfang Liu 	pbuf_length = sg_copy_from_buffer(dst, sg_nents(dst),
74074b58db8SLongfang Liu 				qp_ctx->res[req_id].pbuf,
74174b58db8SLongfang Liu 				copy_size);
74274b58db8SLongfang Liu 
74374b58db8SLongfang Liu 	if (unlikely(pbuf_length != copy_size))
74474b58db8SLongfang Liu 		dev_err(dev, "copy pbuf data to dst error!\n");
74574b58db8SLongfang Liu }
74674b58db8SLongfang Liu 
7472514f559SLongfang Liu static int sec_cipher_map(struct sec_ctx *ctx, struct sec_req *req,
748416d8220SZaibo Xu 			  struct scatterlist *src, struct scatterlist *dst)
749416d8220SZaibo Xu {
750416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
7512514f559SLongfang Liu 	struct sec_aead_req *a_req = &req->aead_req;
752416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
7532514f559SLongfang Liu 	struct sec_alg_res *res = &qp_ctx->res[req->req_id];
7542514f559SLongfang Liu 	struct device *dev = SEC_CTX_DEV(ctx);
75574b58db8SLongfang Liu 	int ret;
7562514f559SLongfang Liu 
75774b58db8SLongfang Liu 	if (req->use_pbuf) {
75874b58db8SLongfang Liu 		ret = sec_cipher_pbuf_map(ctx, req, src);
75974b58db8SLongfang Liu 		c_req->c_ivin = res->pbuf + SEC_PBUF_IV_OFFSET;
76074b58db8SLongfang Liu 		c_req->c_ivin_dma = res->pbuf_dma + SEC_PBUF_IV_OFFSET;
76174b58db8SLongfang Liu 		if (ctx->alg_type == SEC_AEAD) {
76274b58db8SLongfang Liu 			a_req->out_mac = res->pbuf + SEC_PBUF_MAC_OFFSET;
76374b58db8SLongfang Liu 			a_req->out_mac_dma = res->pbuf_dma +
76474b58db8SLongfang Liu 					SEC_PBUF_MAC_OFFSET;
76574b58db8SLongfang Liu 		}
76674b58db8SLongfang Liu 
76774b58db8SLongfang Liu 		return ret;
76874b58db8SLongfang Liu 	}
7692514f559SLongfang Liu 	c_req->c_ivin = res->c_ivin;
7702514f559SLongfang Liu 	c_req->c_ivin_dma = res->c_ivin_dma;
7712514f559SLongfang Liu 	if (ctx->alg_type == SEC_AEAD) {
7722514f559SLongfang Liu 		a_req->out_mac = res->out_mac;
7732514f559SLongfang Liu 		a_req->out_mac_dma = res->out_mac_dma;
7742514f559SLongfang Liu 	}
775416d8220SZaibo Xu 
776416d8220SZaibo Xu 	c_req->c_in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src,
777416d8220SZaibo Xu 						    qp_ctx->c_in_pool,
778416d8220SZaibo Xu 						    req->req_id,
779416d8220SZaibo Xu 						    &c_req->c_in_dma);
780416d8220SZaibo Xu 
781416d8220SZaibo Xu 	if (IS_ERR(c_req->c_in)) {
782416d8220SZaibo Xu 		dev_err(dev, "fail to dma map input sgl buffers!\n");
783416d8220SZaibo Xu 		return PTR_ERR(c_req->c_in);
784416d8220SZaibo Xu 	}
785416d8220SZaibo Xu 
786416d8220SZaibo Xu 	if (dst == src) {
787416d8220SZaibo Xu 		c_req->c_out = c_req->c_in;
788416d8220SZaibo Xu 		c_req->c_out_dma = c_req->c_in_dma;
789416d8220SZaibo Xu 	} else {
790416d8220SZaibo Xu 		c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst,
791416d8220SZaibo Xu 							     qp_ctx->c_out_pool,
792416d8220SZaibo Xu 							     req->req_id,
793416d8220SZaibo Xu 							     &c_req->c_out_dma);
794416d8220SZaibo Xu 
795416d8220SZaibo Xu 		if (IS_ERR(c_req->c_out)) {
796416d8220SZaibo Xu 			dev_err(dev, "fail to dma map output sgl buffers!\n");
797416d8220SZaibo Xu 			hisi_acc_sg_buf_unmap(dev, src, c_req->c_in);
798416d8220SZaibo Xu 			return PTR_ERR(c_req->c_out);
799416d8220SZaibo Xu 		}
800416d8220SZaibo Xu 	}
801416d8220SZaibo Xu 
802416d8220SZaibo Xu 	return 0;
803416d8220SZaibo Xu }
804416d8220SZaibo Xu 
8052514f559SLongfang Liu static void sec_cipher_unmap(struct sec_ctx *ctx, struct sec_req *req,
806a181647cSZaibo Xu 			     struct scatterlist *src, struct scatterlist *dst)
807a181647cSZaibo Xu {
8082514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
8092514f559SLongfang Liu 	struct device *dev = SEC_CTX_DEV(ctx);
810a181647cSZaibo Xu 
81174b58db8SLongfang Liu 	if (req->use_pbuf) {
81274b58db8SLongfang Liu 		sec_cipher_pbuf_unmap(ctx, req, dst);
81374b58db8SLongfang Liu 	} else {
8142514f559SLongfang Liu 		if (dst != src)
8152514f559SLongfang Liu 			hisi_acc_sg_buf_unmap(dev, src, c_req->c_in);
8162514f559SLongfang Liu 
8172514f559SLongfang Liu 		hisi_acc_sg_buf_unmap(dev, dst, c_req->c_out);
818a181647cSZaibo Xu 	}
81974b58db8SLongfang Liu }
820a181647cSZaibo Xu 
821416d8220SZaibo Xu static int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
822416d8220SZaibo Xu {
823a181647cSZaibo Xu 	struct skcipher_request *sq = req->c_req.sk_req;
824416d8220SZaibo Xu 
8252514f559SLongfang Liu 	return sec_cipher_map(ctx, req, sq->src, sq->dst);
826416d8220SZaibo Xu }
827416d8220SZaibo Xu 
828416d8220SZaibo Xu static void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
829416d8220SZaibo Xu {
8302514f559SLongfang Liu 	struct skcipher_request *sq = req->c_req.sk_req;
831416d8220SZaibo Xu 
8322514f559SLongfang Liu 	sec_cipher_unmap(ctx, req, sq->src, sq->dst);
833416d8220SZaibo Xu }
834416d8220SZaibo Xu 
8352f072d75SZaibo Xu static int sec_aead_aes_set_key(struct sec_cipher_ctx *c_ctx,
8362f072d75SZaibo Xu 				struct crypto_authenc_keys *keys)
8372f072d75SZaibo Xu {
8382f072d75SZaibo Xu 	switch (keys->enckeylen) {
8392f072d75SZaibo Xu 	case AES_KEYSIZE_128:
8402f072d75SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_128BIT;
8412f072d75SZaibo Xu 		break;
8422f072d75SZaibo Xu 	case AES_KEYSIZE_192:
8432f072d75SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_192BIT;
8442f072d75SZaibo Xu 		break;
8452f072d75SZaibo Xu 	case AES_KEYSIZE_256:
8462f072d75SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_256BIT;
8472f072d75SZaibo Xu 		break;
8482f072d75SZaibo Xu 	default:
8492f072d75SZaibo Xu 		pr_err("hisi_sec2: aead aes key error!\n");
8502f072d75SZaibo Xu 		return -EINVAL;
8512f072d75SZaibo Xu 	}
8522f072d75SZaibo Xu 	memcpy(c_ctx->c_key, keys->enckey, keys->enckeylen);
8532f072d75SZaibo Xu 
8542f072d75SZaibo Xu 	return 0;
8552f072d75SZaibo Xu }
8562f072d75SZaibo Xu 
8572f072d75SZaibo Xu static int sec_aead_auth_set_key(struct sec_auth_ctx *ctx,
8582f072d75SZaibo Xu 				 struct crypto_authenc_keys *keys)
8592f072d75SZaibo Xu {
8602f072d75SZaibo Xu 	struct crypto_shash *hash_tfm = ctx->hash_tfm;
8615761498cSKai Ye 	int blocksize, digestsize, ret;
8622f072d75SZaibo Xu 
8632f072d75SZaibo Xu 	if (!keys->authkeylen) {
8642f072d75SZaibo Xu 		pr_err("hisi_sec2: aead auth key error!\n");
8652f072d75SZaibo Xu 		return -EINVAL;
8662f072d75SZaibo Xu 	}
8672f072d75SZaibo Xu 
8682f072d75SZaibo Xu 	blocksize = crypto_shash_blocksize(hash_tfm);
8695761498cSKai Ye 	digestsize = crypto_shash_digestsize(hash_tfm);
8702f072d75SZaibo Xu 	if (keys->authkeylen > blocksize) {
87161c38e3aSEric Biggers 		ret = crypto_shash_tfm_digest(hash_tfm, keys->authkey,
8722f072d75SZaibo Xu 					      keys->authkeylen, ctx->a_key);
8732f072d75SZaibo Xu 		if (ret) {
8742203d3f7SColin Ian King 			pr_err("hisi_sec2: aead auth digest error!\n");
8752f072d75SZaibo Xu 			return -EINVAL;
8762f072d75SZaibo Xu 		}
8775761498cSKai Ye 		ctx->a_key_len = digestsize;
8782f072d75SZaibo Xu 	} else {
8792f072d75SZaibo Xu 		memcpy(ctx->a_key, keys->authkey, keys->authkeylen);
8802f072d75SZaibo Xu 		ctx->a_key_len = keys->authkeylen;
8812f072d75SZaibo Xu 	}
8822f072d75SZaibo Xu 
8832f072d75SZaibo Xu 	return 0;
8842f072d75SZaibo Xu }
8852f072d75SZaibo Xu 
8862f072d75SZaibo Xu static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
8872f072d75SZaibo Xu 			   const u32 keylen, const enum sec_hash_alg a_alg,
8882f072d75SZaibo Xu 			   const enum sec_calg c_alg,
8892f072d75SZaibo Xu 			   const enum sec_mac_len mac_len,
8902f072d75SZaibo Xu 			   const enum sec_cmode c_mode)
8912f072d75SZaibo Xu {
8922f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
8932f072d75SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
8942f072d75SZaibo Xu 	struct crypto_authenc_keys keys;
8952f072d75SZaibo Xu 	int ret;
8962f072d75SZaibo Xu 
8972f072d75SZaibo Xu 	ctx->a_ctx.a_alg = a_alg;
8982f072d75SZaibo Xu 	ctx->c_ctx.c_alg = c_alg;
8992f072d75SZaibo Xu 	ctx->a_ctx.mac_len = mac_len;
9002f072d75SZaibo Xu 	c_ctx->c_mode = c_mode;
9012f072d75SZaibo Xu 
9022f072d75SZaibo Xu 	if (crypto_authenc_extractkeys(&keys, key, keylen))
9032f072d75SZaibo Xu 		goto bad_key;
9042f072d75SZaibo Xu 
9052f072d75SZaibo Xu 	ret = sec_aead_aes_set_key(c_ctx, &keys);
9062f072d75SZaibo Xu 	if (ret) {
9072f072d75SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "set sec cipher key err!\n");
9082f072d75SZaibo Xu 		goto bad_key;
9092f072d75SZaibo Xu 	}
9102f072d75SZaibo Xu 
9112f072d75SZaibo Xu 	ret = sec_aead_auth_set_key(&ctx->a_ctx, &keys);
9122f072d75SZaibo Xu 	if (ret) {
9132f072d75SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "set sec auth key err!\n");
9142f072d75SZaibo Xu 		goto bad_key;
9152f072d75SZaibo Xu 	}
9162f072d75SZaibo Xu 
9172f072d75SZaibo Xu 	return 0;
918633e507fSLongfang Liu 
9192f072d75SZaibo Xu bad_key:
9202f072d75SZaibo Xu 	memzero_explicit(&keys, sizeof(struct crypto_authenc_keys));
9212f072d75SZaibo Xu 	return -EINVAL;
9222f072d75SZaibo Xu }
9232f072d75SZaibo Xu 
9242f072d75SZaibo Xu 
9252f072d75SZaibo Xu #define GEN_SEC_AEAD_SETKEY_FUNC(name, aalg, calg, maclen, cmode)	\
9262f072d75SZaibo Xu static int sec_setkey_##name(struct crypto_aead *tfm, const u8 *key,	\
9272f072d75SZaibo Xu 	u32 keylen)							\
9282f072d75SZaibo Xu {									\
9292f072d75SZaibo Xu 	return sec_aead_setkey(tfm, key, keylen, aalg, calg, maclen, cmode);\
9302f072d75SZaibo Xu }
9312f072d75SZaibo Xu 
9322f072d75SZaibo Xu GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha1, SEC_A_HMAC_SHA1,
9332f072d75SZaibo Xu 			 SEC_CALG_AES, SEC_HMAC_SHA1_MAC, SEC_CMODE_CBC)
9342f072d75SZaibo Xu GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha256, SEC_A_HMAC_SHA256,
9352f072d75SZaibo Xu 			 SEC_CALG_AES, SEC_HMAC_SHA256_MAC, SEC_CMODE_CBC)
9362f072d75SZaibo Xu GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha512, SEC_A_HMAC_SHA512,
9372f072d75SZaibo Xu 			 SEC_CALG_AES, SEC_HMAC_SHA512_MAC, SEC_CMODE_CBC)
9382f072d75SZaibo Xu 
9392f072d75SZaibo Xu static int sec_aead_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
9402f072d75SZaibo Xu {
9412f072d75SZaibo Xu 	struct aead_request *aq = req->aead_req.aead_req;
9422f072d75SZaibo Xu 
9432514f559SLongfang Liu 	return sec_cipher_map(ctx, req, aq->src, aq->dst);
9442f072d75SZaibo Xu }
9452f072d75SZaibo Xu 
9462f072d75SZaibo Xu static void sec_aead_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
9472f072d75SZaibo Xu {
9482f072d75SZaibo Xu 	struct aead_request *aq = req->aead_req.aead_req;
9492f072d75SZaibo Xu 
9502514f559SLongfang Liu 	sec_cipher_unmap(ctx, req, aq->src, aq->dst);
9512f072d75SZaibo Xu }
9522f072d75SZaibo Xu 
953416d8220SZaibo Xu static int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req)
954416d8220SZaibo Xu {
955416d8220SZaibo Xu 	int ret;
956416d8220SZaibo Xu 
957416d8220SZaibo Xu 	ret = ctx->req_op->buf_map(ctx, req);
958b9c8d897SZaibo Xu 	if (unlikely(ret))
959416d8220SZaibo Xu 		return ret;
960416d8220SZaibo Xu 
961416d8220SZaibo Xu 	ctx->req_op->do_transfer(ctx, req);
962416d8220SZaibo Xu 
963416d8220SZaibo Xu 	ret = ctx->req_op->bd_fill(ctx, req);
964b9c8d897SZaibo Xu 	if (unlikely(ret))
965416d8220SZaibo Xu 		goto unmap_req_buf;
966416d8220SZaibo Xu 
967416d8220SZaibo Xu 	return ret;
968416d8220SZaibo Xu 
969416d8220SZaibo Xu unmap_req_buf:
970416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
971416d8220SZaibo Xu 	return ret;
972416d8220SZaibo Xu }
973416d8220SZaibo Xu 
974416d8220SZaibo Xu static void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req)
975416d8220SZaibo Xu {
976416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
977416d8220SZaibo Xu }
978416d8220SZaibo Xu 
979416d8220SZaibo Xu static void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
980416d8220SZaibo Xu {
981416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
9822514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
983416d8220SZaibo Xu 
9842514f559SLongfang Liu 	memcpy(c_req->c_ivin, sk_req->iv, ctx->c_ctx.ivsize);
985416d8220SZaibo Xu }
986416d8220SZaibo Xu 
987416d8220SZaibo Xu static int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
988416d8220SZaibo Xu {
989416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
990416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
991416d8220SZaibo Xu 	struct sec_sqe *sec_sqe = &req->sec_sqe;
992416d8220SZaibo Xu 	u8 scene, sa_type, da_type;
993416d8220SZaibo Xu 	u8 bd_type, cipher;
9947c7d902aSZaibo Xu 	u8 de = 0;
995416d8220SZaibo Xu 
996416d8220SZaibo Xu 	memset(sec_sqe, 0, sizeof(struct sec_sqe));
997416d8220SZaibo Xu 
998416d8220SZaibo Xu 	sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
9992514f559SLongfang Liu 	sec_sqe->type2.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
1000416d8220SZaibo Xu 	sec_sqe->type2.data_src_addr = cpu_to_le64(c_req->c_in_dma);
1001416d8220SZaibo Xu 	sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma);
1002416d8220SZaibo Xu 
1003416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) <<
1004416d8220SZaibo Xu 						SEC_CMODE_OFFSET);
1005416d8220SZaibo Xu 	sec_sqe->type2.c_alg = c_ctx->c_alg;
1006416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
1007416d8220SZaibo Xu 						SEC_CKEY_OFFSET);
1008416d8220SZaibo Xu 
1009416d8220SZaibo Xu 	bd_type = SEC_BD_TYPE2;
1010416d8220SZaibo Xu 	if (c_req->encrypt)
1011416d8220SZaibo Xu 		cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET;
1012416d8220SZaibo Xu 	else
1013416d8220SZaibo Xu 		cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET;
1014416d8220SZaibo Xu 	sec_sqe->type_cipher_auth = bd_type | cipher;
1015416d8220SZaibo Xu 
101674b58db8SLongfang Liu 	if (req->use_pbuf)
101774b58db8SLongfang Liu 		sa_type = SEC_PBUF << SEC_SRC_SGL_OFFSET;
101874b58db8SLongfang Liu 	else
1019416d8220SZaibo Xu 		sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET;
1020416d8220SZaibo Xu 	scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET;
1021416d8220SZaibo Xu 	if (c_req->c_in_dma != c_req->c_out_dma)
1022416d8220SZaibo Xu 		de = 0x1 << SEC_DE_OFFSET;
1023416d8220SZaibo Xu 
1024416d8220SZaibo Xu 	sec_sqe->sds_sa_type = (de | scene | sa_type);
1025416d8220SZaibo Xu 
1026416d8220SZaibo Xu 	/* Just set DST address type */
102774b58db8SLongfang Liu 	if (req->use_pbuf)
102874b58db8SLongfang Liu 		da_type = SEC_PBUF << SEC_DST_SGL_OFFSET;
102974b58db8SLongfang Liu 	else
1030416d8220SZaibo Xu 		da_type = SEC_SGL << SEC_DST_SGL_OFFSET;
1031416d8220SZaibo Xu 	sec_sqe->sdm_addr_type |= da_type;
1032416d8220SZaibo Xu 
1033416d8220SZaibo Xu 	sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len);
1034416d8220SZaibo Xu 	sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id);
1035416d8220SZaibo Xu 
1036416d8220SZaibo Xu 	return 0;
1037416d8220SZaibo Xu }
1038416d8220SZaibo Xu 
10392f072d75SZaibo Xu static void sec_update_iv(struct sec_req *req, enum sec_alg_type alg_type)
1040416d8220SZaibo Xu {
10412f072d75SZaibo Xu 	struct aead_request *aead_req = req->aead_req.aead_req;
1042416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
1043416d8220SZaibo Xu 	u32 iv_size = req->ctx->c_ctx.ivsize;
1044416d8220SZaibo Xu 	struct scatterlist *sgl;
10452f072d75SZaibo Xu 	unsigned int cryptlen;
1046416d8220SZaibo Xu 	size_t sz;
10472f072d75SZaibo Xu 	u8 *iv;
1048416d8220SZaibo Xu 
1049416d8220SZaibo Xu 	if (req->c_req.encrypt)
10502f072d75SZaibo Xu 		sgl = alg_type == SEC_SKCIPHER ? sk_req->dst : aead_req->dst;
1051416d8220SZaibo Xu 	else
10522f072d75SZaibo Xu 		sgl = alg_type == SEC_SKCIPHER ? sk_req->src : aead_req->src;
1053416d8220SZaibo Xu 
10542f072d75SZaibo Xu 	if (alg_type == SEC_SKCIPHER) {
10552f072d75SZaibo Xu 		iv = sk_req->iv;
10562f072d75SZaibo Xu 		cryptlen = sk_req->cryptlen;
10572f072d75SZaibo Xu 	} else {
10582f072d75SZaibo Xu 		iv = aead_req->iv;
10592f072d75SZaibo Xu 		cryptlen = aead_req->cryptlen;
10602f072d75SZaibo Xu 	}
10612f072d75SZaibo Xu 
10622f072d75SZaibo Xu 	sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), iv, iv_size,
10632f072d75SZaibo Xu 				cryptlen - iv_size);
1064b9c8d897SZaibo Xu 	if (unlikely(sz != iv_size))
1065416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "copy output iv error!\n");
1066416d8220SZaibo Xu }
1067416d8220SZaibo Xu 
10689597efc3SKai Ye static struct sec_req *sec_back_req_clear(struct sec_ctx *ctx,
10699597efc3SKai Ye 				struct sec_qp_ctx *qp_ctx)
10709597efc3SKai Ye {
10719597efc3SKai Ye 	struct sec_req *backlog_req = NULL;
10729597efc3SKai Ye 
10739597efc3SKai Ye 	mutex_lock(&qp_ctx->req_lock);
10749597efc3SKai Ye 	if (ctx->fake_req_limit >=
10759597efc3SKai Ye 	    atomic_read(&qp_ctx->qp->qp_status.used) &&
10769597efc3SKai Ye 	    !list_empty(&qp_ctx->backlog)) {
10779597efc3SKai Ye 		backlog_req = list_first_entry(&qp_ctx->backlog,
10789597efc3SKai Ye 				typeof(*backlog_req), backlog_head);
10799597efc3SKai Ye 		list_del(&backlog_req->backlog_head);
10809597efc3SKai Ye 	}
10819597efc3SKai Ye 	mutex_unlock(&qp_ctx->req_lock);
10829597efc3SKai Ye 
10839597efc3SKai Ye 	return backlog_req;
10849597efc3SKai Ye }
10859597efc3SKai Ye 
1086310ea0acSZaibo Xu static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req,
1087310ea0acSZaibo Xu 				  int err)
1088416d8220SZaibo Xu {
1089416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
1090416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
10919597efc3SKai Ye 	struct skcipher_request *backlog_sk_req;
10929597efc3SKai Ye 	struct sec_req *backlog_req;
1093416d8220SZaibo Xu 
1094416d8220SZaibo Xu 	sec_free_req_id(req);
1095416d8220SZaibo Xu 
1096416d8220SZaibo Xu 	/* IV output at encrypto of CBC mode */
1097310ea0acSZaibo Xu 	if (!err && ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt)
10982f072d75SZaibo Xu 		sec_update_iv(req, SEC_SKCIPHER);
1099416d8220SZaibo Xu 
11009597efc3SKai Ye 	while (1) {
11019597efc3SKai Ye 		backlog_req = sec_back_req_clear(ctx, qp_ctx);
11029597efc3SKai Ye 		if (!backlog_req)
11039597efc3SKai Ye 			break;
11049597efc3SKai Ye 
11059597efc3SKai Ye 		backlog_sk_req = backlog_req->c_req.sk_req;
11069597efc3SKai Ye 		backlog_sk_req->base.complete(&backlog_sk_req->base,
11079597efc3SKai Ye 						-EINPROGRESS);
11089597efc3SKai Ye 		atomic64_inc(&ctx->sec->debug.dfx.recv_busy_cnt);
11099597efc3SKai Ye 	}
11109597efc3SKai Ye 
1111310ea0acSZaibo Xu 	sk_req->base.complete(&sk_req->base, err);
1112416d8220SZaibo Xu }
1113416d8220SZaibo Xu 
11142f072d75SZaibo Xu static void sec_aead_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
11152f072d75SZaibo Xu {
11162f072d75SZaibo Xu 	struct aead_request *aead_req = req->aead_req.aead_req;
11172514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
11182f072d75SZaibo Xu 
11192514f559SLongfang Liu 	memcpy(c_req->c_ivin, aead_req->iv, ctx->c_ctx.ivsize);
11202f072d75SZaibo Xu }
11212f072d75SZaibo Xu 
11222f072d75SZaibo Xu static void sec_auth_bd_fill_ex(struct sec_auth_ctx *ctx, int dir,
11232f072d75SZaibo Xu 			       struct sec_req *req, struct sec_sqe *sec_sqe)
11242f072d75SZaibo Xu {
11252f072d75SZaibo Xu 	struct sec_aead_req *a_req = &req->aead_req;
11262f072d75SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
11272f072d75SZaibo Xu 	struct aead_request *aq = a_req->aead_req;
11282f072d75SZaibo Xu 
11292f072d75SZaibo Xu 	sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma);
11302f072d75SZaibo Xu 
11312f072d75SZaibo Xu 	sec_sqe->type2.mac_key_alg =
11322f072d75SZaibo Xu 			cpu_to_le32(ctx->mac_len / SEC_SQE_LEN_RATE);
11332f072d75SZaibo Xu 
11342f072d75SZaibo Xu 	sec_sqe->type2.mac_key_alg |=
11352f072d75SZaibo Xu 			cpu_to_le32((u32)((ctx->a_key_len) /
11362f072d75SZaibo Xu 			SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET);
11372f072d75SZaibo Xu 
11382f072d75SZaibo Xu 	sec_sqe->type2.mac_key_alg |=
11392f072d75SZaibo Xu 			cpu_to_le32((u32)(ctx->a_alg) << SEC_AEAD_ALG_OFFSET);
11402f072d75SZaibo Xu 
11412f072d75SZaibo Xu 	sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE1 << SEC_AUTH_OFFSET;
11422f072d75SZaibo Xu 
11432f072d75SZaibo Xu 	if (dir)
11442f072d75SZaibo Xu 		sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH;
11452f072d75SZaibo Xu 	else
11462f072d75SZaibo Xu 		sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER;
11472f072d75SZaibo Xu 
11482f072d75SZaibo Xu 	sec_sqe->type2.alen_ivllen = cpu_to_le32(c_req->c_len + aq->assoclen);
11492f072d75SZaibo Xu 
11502f072d75SZaibo Xu 	sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
11512f072d75SZaibo Xu 
11522514f559SLongfang Liu 	sec_sqe->type2.mac_addr = cpu_to_le64(a_req->out_mac_dma);
11532f072d75SZaibo Xu }
11542f072d75SZaibo Xu 
11552f072d75SZaibo Xu static int sec_aead_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
11562f072d75SZaibo Xu {
11572f072d75SZaibo Xu 	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
11582f072d75SZaibo Xu 	struct sec_sqe *sec_sqe = &req->sec_sqe;
11592f072d75SZaibo Xu 	int ret;
11602f072d75SZaibo Xu 
11612f072d75SZaibo Xu 	ret = sec_skcipher_bd_fill(ctx, req);
11622f072d75SZaibo Xu 	if (unlikely(ret)) {
11632f072d75SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "skcipher bd fill is error!\n");
11642f072d75SZaibo Xu 		return ret;
11652f072d75SZaibo Xu 	}
11662f072d75SZaibo Xu 
11672f072d75SZaibo Xu 	sec_auth_bd_fill_ex(auth_ctx, req->c_req.encrypt, req, sec_sqe);
11682f072d75SZaibo Xu 
11692f072d75SZaibo Xu 	return 0;
11702f072d75SZaibo Xu }
11712f072d75SZaibo Xu 
11722f072d75SZaibo Xu static void sec_aead_callback(struct sec_ctx *c, struct sec_req *req, int err)
11732f072d75SZaibo Xu {
11742f072d75SZaibo Xu 	struct aead_request *a_req = req->aead_req.aead_req;
11752f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
11762514f559SLongfang Liu 	struct sec_aead_req *aead_req = &req->aead_req;
11772f072d75SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
11782f072d75SZaibo Xu 	size_t authsize = crypto_aead_authsize(tfm);
11792f072d75SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
11809597efc3SKai Ye 	struct aead_request *backlog_aead_req;
11819597efc3SKai Ye 	struct sec_req *backlog_req;
11822f072d75SZaibo Xu 	size_t sz;
11832f072d75SZaibo Xu 
11842f072d75SZaibo Xu 	if (!err && c->c_ctx.c_mode == SEC_CMODE_CBC && c_req->encrypt)
11852f072d75SZaibo Xu 		sec_update_iv(req, SEC_AEAD);
11862f072d75SZaibo Xu 
11872f072d75SZaibo Xu 	/* Copy output mac */
11882f072d75SZaibo Xu 	if (!err && c_req->encrypt) {
11892f072d75SZaibo Xu 		struct scatterlist *sgl = a_req->dst;
11902f072d75SZaibo Xu 
11912f072d75SZaibo Xu 		sz = sg_pcopy_from_buffer(sgl, sg_nents(sgl),
11922514f559SLongfang Liu 					  aead_req->out_mac,
11932f072d75SZaibo Xu 					  authsize, a_req->cryptlen +
11942f072d75SZaibo Xu 					  a_req->assoclen);
11952f072d75SZaibo Xu 
11962f072d75SZaibo Xu 		if (unlikely(sz != authsize)) {
11972f072d75SZaibo Xu 			dev_err(SEC_CTX_DEV(req->ctx), "copy out mac err!\n");
11982f072d75SZaibo Xu 			err = -EINVAL;
11992f072d75SZaibo Xu 		}
12002f072d75SZaibo Xu 	}
12012f072d75SZaibo Xu 
12022f072d75SZaibo Xu 	sec_free_req_id(req);
12032f072d75SZaibo Xu 
12049597efc3SKai Ye 	while (1) {
12059597efc3SKai Ye 		backlog_req = sec_back_req_clear(c, qp_ctx);
12069597efc3SKai Ye 		if (!backlog_req)
12079597efc3SKai Ye 			break;
12089597efc3SKai Ye 
12099597efc3SKai Ye 		backlog_aead_req = backlog_req->aead_req.aead_req;
12109597efc3SKai Ye 		backlog_aead_req->base.complete(&backlog_aead_req->base,
12119597efc3SKai Ye 						-EINPROGRESS);
12129597efc3SKai Ye 		atomic64_inc(&c->sec->debug.dfx.recv_busy_cnt);
12139597efc3SKai Ye 	}
12142f072d75SZaibo Xu 
12152f072d75SZaibo Xu 	a_req->base.complete(&a_req->base, err);
12162f072d75SZaibo Xu }
12172f072d75SZaibo Xu 
1218416d8220SZaibo Xu static void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req)
1219416d8220SZaibo Xu {
1220416d8220SZaibo Xu 	sec_free_req_id(req);
1221a181647cSZaibo Xu 	sec_free_queue_id(ctx, req);
1222416d8220SZaibo Xu }
1223416d8220SZaibo Xu 
1224416d8220SZaibo Xu static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
1225416d8220SZaibo Xu {
1226416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
12277c7d902aSZaibo Xu 	int queue_id;
1228416d8220SZaibo Xu 
1229416d8220SZaibo Xu 	/* To load balance */
1230a181647cSZaibo Xu 	queue_id = sec_alloc_queue_id(ctx, req);
1231a181647cSZaibo Xu 	qp_ctx = &ctx->qp_ctx[queue_id];
1232416d8220SZaibo Xu 
1233416d8220SZaibo Xu 	req->req_id = sec_alloc_req_id(req, qp_ctx);
1234b9c8d897SZaibo Xu 	if (unlikely(req->req_id < 0)) {
1235a181647cSZaibo Xu 		sec_free_queue_id(ctx, req);
1236416d8220SZaibo Xu 		return req->req_id;
1237416d8220SZaibo Xu 	}
1238416d8220SZaibo Xu 
12397c7d902aSZaibo Xu 	return 0;
1240416d8220SZaibo Xu }
1241416d8220SZaibo Xu 
1242416d8220SZaibo Xu static int sec_process(struct sec_ctx *ctx, struct sec_req *req)
1243416d8220SZaibo Xu {
12442514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
1245416d8220SZaibo Xu 	int ret;
1246416d8220SZaibo Xu 
1247416d8220SZaibo Xu 	ret = sec_request_init(ctx, req);
1248b9c8d897SZaibo Xu 	if (unlikely(ret))
1249416d8220SZaibo Xu 		return ret;
1250416d8220SZaibo Xu 
1251416d8220SZaibo Xu 	ret = sec_request_transfer(ctx, req);
1252b9c8d897SZaibo Xu 	if (unlikely(ret))
1253416d8220SZaibo Xu 		goto err_uninit_req;
1254416d8220SZaibo Xu 
1255416d8220SZaibo Xu 	/* Output IV as decrypto */
1256416d8220SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt)
12572f072d75SZaibo Xu 		sec_update_iv(req, ctx->alg_type);
1258416d8220SZaibo Xu 
1259416d8220SZaibo Xu 	ret = ctx->req_op->bd_send(ctx, req);
12609597efc3SKai Ye 	if (unlikely((ret != -EBUSY && ret != -EINPROGRESS) ||
12619597efc3SKai Ye 		(ret == -EBUSY && !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
1262a718cfceSZaibo Xu 		dev_err_ratelimited(SEC_CTX_DEV(ctx), "send sec request failed!\n");
1263416d8220SZaibo Xu 		goto err_send_req;
1264416d8220SZaibo Xu 	}
1265416d8220SZaibo Xu 
1266416d8220SZaibo Xu 	return ret;
1267416d8220SZaibo Xu 
1268416d8220SZaibo Xu err_send_req:
1269416d8220SZaibo Xu 	/* As failing, restore the IV from user */
12702f072d75SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) {
12712f072d75SZaibo Xu 		if (ctx->alg_type == SEC_SKCIPHER)
12722514f559SLongfang Liu 			memcpy(req->c_req.sk_req->iv, c_req->c_ivin,
1273416d8220SZaibo Xu 			       ctx->c_ctx.ivsize);
12742f072d75SZaibo Xu 		else
12752514f559SLongfang Liu 			memcpy(req->aead_req.aead_req->iv, c_req->c_ivin,
12762f072d75SZaibo Xu 			       ctx->c_ctx.ivsize);
12772f072d75SZaibo Xu 	}
1278416d8220SZaibo Xu 
1279416d8220SZaibo Xu 	sec_request_untransfer(ctx, req);
1280416d8220SZaibo Xu err_uninit_req:
1281416d8220SZaibo Xu 	sec_request_uninit(ctx, req);
1282416d8220SZaibo Xu 	return ret;
1283416d8220SZaibo Xu }
1284416d8220SZaibo Xu 
1285a181647cSZaibo Xu static const struct sec_req_op sec_skcipher_req_ops = {
1286416d8220SZaibo Xu 	.buf_map	= sec_skcipher_sgl_map,
1287416d8220SZaibo Xu 	.buf_unmap	= sec_skcipher_sgl_unmap,
1288416d8220SZaibo Xu 	.do_transfer	= sec_skcipher_copy_iv,
1289416d8220SZaibo Xu 	.bd_fill	= sec_skcipher_bd_fill,
1290416d8220SZaibo Xu 	.bd_send	= sec_bd_send,
1291416d8220SZaibo Xu 	.callback	= sec_skcipher_callback,
1292416d8220SZaibo Xu 	.process	= sec_process,
1293416d8220SZaibo Xu };
1294416d8220SZaibo Xu 
12952f072d75SZaibo Xu static const struct sec_req_op sec_aead_req_ops = {
12962f072d75SZaibo Xu 	.buf_map	= sec_aead_sgl_map,
12972f072d75SZaibo Xu 	.buf_unmap	= sec_aead_sgl_unmap,
12982f072d75SZaibo Xu 	.do_transfer	= sec_aead_copy_iv,
12992f072d75SZaibo Xu 	.bd_fill	= sec_aead_bd_fill,
13002f072d75SZaibo Xu 	.bd_send	= sec_bd_send,
13012f072d75SZaibo Xu 	.callback	= sec_aead_callback,
13022f072d75SZaibo Xu 	.process	= sec_process,
13032f072d75SZaibo Xu };
13042f072d75SZaibo Xu 
1305416d8220SZaibo Xu static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
1306416d8220SZaibo Xu {
1307416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
1308416d8220SZaibo Xu 
1309a181647cSZaibo Xu 	ctx->req_op = &sec_skcipher_req_ops;
1310416d8220SZaibo Xu 
1311416d8220SZaibo Xu 	return sec_skcipher_init(tfm);
1312416d8220SZaibo Xu }
1313416d8220SZaibo Xu 
1314416d8220SZaibo Xu static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm)
1315416d8220SZaibo Xu {
1316a181647cSZaibo Xu 	sec_skcipher_uninit(tfm);
1317416d8220SZaibo Xu }
1318416d8220SZaibo Xu 
13192f072d75SZaibo Xu static int sec_aead_init(struct crypto_aead *tfm)
13202f072d75SZaibo Xu {
13212f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
13222f072d75SZaibo Xu 	int ret;
13232f072d75SZaibo Xu 
13242f072d75SZaibo Xu 	crypto_aead_set_reqsize(tfm, sizeof(struct sec_req));
13252f072d75SZaibo Xu 	ctx->alg_type = SEC_AEAD;
13262f072d75SZaibo Xu 	ctx->c_ctx.ivsize = crypto_aead_ivsize(tfm);
13272f072d75SZaibo Xu 	if (ctx->c_ctx.ivsize > SEC_IV_SIZE) {
13282f072d75SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "get error aead iv size!\n");
13292f072d75SZaibo Xu 		return -EINVAL;
13302f072d75SZaibo Xu 	}
13312f072d75SZaibo Xu 
13322f072d75SZaibo Xu 	ctx->req_op = &sec_aead_req_ops;
13332f072d75SZaibo Xu 	ret = sec_ctx_base_init(ctx);
13342f072d75SZaibo Xu 	if (ret)
13352f072d75SZaibo Xu 		return ret;
13362f072d75SZaibo Xu 
13372f072d75SZaibo Xu 	ret = sec_auth_init(ctx);
13382f072d75SZaibo Xu 	if (ret)
13392f072d75SZaibo Xu 		goto err_auth_init;
13402f072d75SZaibo Xu 
13412f072d75SZaibo Xu 	ret = sec_cipher_init(ctx);
13422f072d75SZaibo Xu 	if (ret)
13432f072d75SZaibo Xu 		goto err_cipher_init;
13442f072d75SZaibo Xu 
13452f072d75SZaibo Xu 	return ret;
13462f072d75SZaibo Xu 
13472f072d75SZaibo Xu err_cipher_init:
13482f072d75SZaibo Xu 	sec_auth_uninit(ctx);
13492f072d75SZaibo Xu err_auth_init:
13502f072d75SZaibo Xu 	sec_ctx_base_uninit(ctx);
13512f072d75SZaibo Xu 	return ret;
13522f072d75SZaibo Xu }
13532f072d75SZaibo Xu 
13542f072d75SZaibo Xu static void sec_aead_exit(struct crypto_aead *tfm)
13552f072d75SZaibo Xu {
13562f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
13572f072d75SZaibo Xu 
13582f072d75SZaibo Xu 	sec_cipher_uninit(ctx);
13592f072d75SZaibo Xu 	sec_auth_uninit(ctx);
13602f072d75SZaibo Xu 	sec_ctx_base_uninit(ctx);
13612f072d75SZaibo Xu }
13622f072d75SZaibo Xu 
13632f072d75SZaibo Xu static int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name)
13642f072d75SZaibo Xu {
13652f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
13662f072d75SZaibo Xu 	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
13672f072d75SZaibo Xu 	int ret;
13682f072d75SZaibo Xu 
13692f072d75SZaibo Xu 	ret = sec_aead_init(tfm);
13702f072d75SZaibo Xu 	if (ret) {
13712f072d75SZaibo Xu 		pr_err("hisi_sec2: aead init error!\n");
13722f072d75SZaibo Xu 		return ret;
13732f072d75SZaibo Xu 	}
13742f072d75SZaibo Xu 
13752f072d75SZaibo Xu 	auth_ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
13762f072d75SZaibo Xu 	if (IS_ERR(auth_ctx->hash_tfm)) {
13772f072d75SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "aead alloc shash error!\n");
13782f072d75SZaibo Xu 		sec_aead_exit(tfm);
13792f072d75SZaibo Xu 		return PTR_ERR(auth_ctx->hash_tfm);
13802f072d75SZaibo Xu 	}
13812f072d75SZaibo Xu 
13822f072d75SZaibo Xu 	return 0;
13832f072d75SZaibo Xu }
13842f072d75SZaibo Xu 
13852f072d75SZaibo Xu static void sec_aead_ctx_exit(struct crypto_aead *tfm)
13862f072d75SZaibo Xu {
13872f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
13882f072d75SZaibo Xu 
13892f072d75SZaibo Xu 	crypto_free_shash(ctx->a_ctx.hash_tfm);
13902f072d75SZaibo Xu 	sec_aead_exit(tfm);
13912f072d75SZaibo Xu }
13922f072d75SZaibo Xu 
13932f072d75SZaibo Xu static int sec_aead_sha1_ctx_init(struct crypto_aead *tfm)
13942f072d75SZaibo Xu {
13952f072d75SZaibo Xu 	return sec_aead_ctx_init(tfm, "sha1");
13962f072d75SZaibo Xu }
13972f072d75SZaibo Xu 
13982f072d75SZaibo Xu static int sec_aead_sha256_ctx_init(struct crypto_aead *tfm)
13992f072d75SZaibo Xu {
14002f072d75SZaibo Xu 	return sec_aead_ctx_init(tfm, "sha256");
14012f072d75SZaibo Xu }
14022f072d75SZaibo Xu 
14032f072d75SZaibo Xu static int sec_aead_sha512_ctx_init(struct crypto_aead *tfm)
14042f072d75SZaibo Xu {
14052f072d75SZaibo Xu 	return sec_aead_ctx_init(tfm, "sha512");
14062f072d75SZaibo Xu }
14072f072d75SZaibo Xu 
1408d6de2a59SZaibo Xu static int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
1409416d8220SZaibo Xu {
1410d6de2a59SZaibo Xu 	struct skcipher_request *sk_req = sreq->c_req.sk_req;
1411416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
1412d6de2a59SZaibo Xu 	u8 c_alg = ctx->c_ctx.c_alg;
1413416d8220SZaibo Xu 
1414b9c8d897SZaibo Xu 	if (unlikely(!sk_req->src || !sk_req->dst)) {
1415416d8220SZaibo Xu 		dev_err(dev, "skcipher input param error!\n");
1416416d8220SZaibo Xu 		return -EINVAL;
1417416d8220SZaibo Xu 	}
1418d6de2a59SZaibo Xu 	sreq->c_req.c_len = sk_req->cryptlen;
141974b58db8SLongfang Liu 
142074b58db8SLongfang Liu 	if (ctx->pbuf_supported && sk_req->cryptlen <= SEC_PBUF_SZ)
142174b58db8SLongfang Liu 		sreq->use_pbuf = true;
142274b58db8SLongfang Liu 	else
142374b58db8SLongfang Liu 		sreq->use_pbuf = false;
142474b58db8SLongfang Liu 
1425416d8220SZaibo Xu 	if (c_alg == SEC_CALG_3DES) {
1426b9c8d897SZaibo Xu 		if (unlikely(sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1))) {
1427416d8220SZaibo Xu 			dev_err(dev, "skcipher 3des input length error!\n");
1428416d8220SZaibo Xu 			return -EINVAL;
1429416d8220SZaibo Xu 		}
1430416d8220SZaibo Xu 		return 0;
1431416d8220SZaibo Xu 	} else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) {
1432b9c8d897SZaibo Xu 		if (unlikely(sk_req->cryptlen & (AES_BLOCK_SIZE - 1))) {
1433416d8220SZaibo Xu 			dev_err(dev, "skcipher aes input length error!\n");
1434416d8220SZaibo Xu 			return -EINVAL;
1435416d8220SZaibo Xu 		}
1436416d8220SZaibo Xu 		return 0;
1437416d8220SZaibo Xu 	}
1438416d8220SZaibo Xu 	dev_err(dev, "skcipher algorithm error!\n");
1439633e507fSLongfang Liu 
1440416d8220SZaibo Xu 	return -EINVAL;
1441416d8220SZaibo Xu }
1442416d8220SZaibo Xu 
1443416d8220SZaibo Xu static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt)
1444416d8220SZaibo Xu {
1445416d8220SZaibo Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req);
1446416d8220SZaibo Xu 	struct sec_req *req = skcipher_request_ctx(sk_req);
1447416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
1448416d8220SZaibo Xu 	int ret;
1449416d8220SZaibo Xu 
1450416d8220SZaibo Xu 	if (!sk_req->cryptlen)
1451416d8220SZaibo Xu 		return 0;
1452416d8220SZaibo Xu 
14539597efc3SKai Ye 	req->flag = sk_req->base.flags;
1454416d8220SZaibo Xu 	req->c_req.sk_req = sk_req;
1455416d8220SZaibo Xu 	req->c_req.encrypt = encrypt;
1456416d8220SZaibo Xu 	req->ctx = ctx;
1457416d8220SZaibo Xu 
1458d6de2a59SZaibo Xu 	ret = sec_skcipher_param_check(ctx, req);
1459d6de2a59SZaibo Xu 	if (unlikely(ret))
1460d6de2a59SZaibo Xu 		return -EINVAL;
1461d6de2a59SZaibo Xu 
1462416d8220SZaibo Xu 	return ctx->req_op->process(ctx, req);
1463416d8220SZaibo Xu }
1464416d8220SZaibo Xu 
1465416d8220SZaibo Xu static int sec_skcipher_encrypt(struct skcipher_request *sk_req)
1466416d8220SZaibo Xu {
1467416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, true);
1468416d8220SZaibo Xu }
1469416d8220SZaibo Xu 
1470416d8220SZaibo Xu static int sec_skcipher_decrypt(struct skcipher_request *sk_req)
1471416d8220SZaibo Xu {
1472416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, false);
1473416d8220SZaibo Xu }
1474416d8220SZaibo Xu 
1475416d8220SZaibo Xu #define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \
1476416d8220SZaibo Xu 	sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\
1477416d8220SZaibo Xu {\
1478416d8220SZaibo Xu 	.base = {\
1479416d8220SZaibo Xu 		.cra_name = sec_cra_name,\
1480416d8220SZaibo Xu 		.cra_driver_name = "hisi_sec_"sec_cra_name,\
1481416d8220SZaibo Xu 		.cra_priority = SEC_PRIORITY,\
1482b8aa7dc5SMikulas Patocka 		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,\
1483416d8220SZaibo Xu 		.cra_blocksize = blk_size,\
1484416d8220SZaibo Xu 		.cra_ctxsize = sizeof(struct sec_ctx),\
1485416d8220SZaibo Xu 		.cra_module = THIS_MODULE,\
1486416d8220SZaibo Xu 	},\
1487416d8220SZaibo Xu 	.init = ctx_init,\
1488416d8220SZaibo Xu 	.exit = ctx_exit,\
1489416d8220SZaibo Xu 	.setkey = sec_set_key,\
1490416d8220SZaibo Xu 	.decrypt = sec_skcipher_decrypt,\
1491416d8220SZaibo Xu 	.encrypt = sec_skcipher_encrypt,\
1492416d8220SZaibo Xu 	.min_keysize = sec_min_key_size,\
1493416d8220SZaibo Xu 	.max_keysize = sec_max_key_size,\
1494416d8220SZaibo Xu 	.ivsize = iv_size,\
1495416d8220SZaibo Xu },
1496416d8220SZaibo Xu 
1497416d8220SZaibo Xu #define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \
1498416d8220SZaibo Xu 	max_key_size, blk_size, iv_size) \
1499416d8220SZaibo Xu 	SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \
1500416d8220SZaibo Xu 	sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size)
1501416d8220SZaibo Xu 
1502a181647cSZaibo Xu static struct skcipher_alg sec_skciphers[] = {
1503416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb,
1504416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
1505416d8220SZaibo Xu 			 AES_BLOCK_SIZE, 0)
1506416d8220SZaibo Xu 
1507416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc,
1508416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
1509416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
1510416d8220SZaibo Xu 
1511416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts,
1512416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE,
1513416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
1514416d8220SZaibo Xu 
1515416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb,
1516416d8220SZaibo Xu 			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
1517416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, 0)
1518416d8220SZaibo Xu 
1519416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc,
1520416d8220SZaibo Xu 			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
1521416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE)
1522416d8220SZaibo Xu 
1523416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,
1524416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE,
1525416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
1526416d8220SZaibo Xu 
1527416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc,
1528416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
1529416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
1530416d8220SZaibo Xu };
1531416d8220SZaibo Xu 
15322f072d75SZaibo Xu static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
15332f072d75SZaibo Xu {
15342f072d75SZaibo Xu 	u8 c_alg = ctx->c_ctx.c_alg;
15352f072d75SZaibo Xu 	struct aead_request *req = sreq->aead_req.aead_req;
15362f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
15372f072d75SZaibo Xu 	size_t authsize = crypto_aead_authsize(tfm);
15382f072d75SZaibo Xu 
15392514f559SLongfang Liu 	if (unlikely(!req->src || !req->dst || !req->cryptlen ||
15402514f559SLongfang Liu 		req->assoclen > SEC_MAX_AAD_LEN)) {
15412f072d75SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "aead input param error!\n");
15422f072d75SZaibo Xu 		return -EINVAL;
15432f072d75SZaibo Xu 	}
15442f072d75SZaibo Xu 
154574b58db8SLongfang Liu 	if (ctx->pbuf_supported && (req->cryptlen + req->assoclen) <=
154674b58db8SLongfang Liu 		SEC_PBUF_SZ)
154774b58db8SLongfang Liu 		sreq->use_pbuf = true;
154874b58db8SLongfang Liu 	else
154974b58db8SLongfang Liu 		sreq->use_pbuf = false;
155074b58db8SLongfang Liu 
15512f072d75SZaibo Xu 	/* Support AES only */
15522f072d75SZaibo Xu 	if (unlikely(c_alg != SEC_CALG_AES)) {
15532f072d75SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "aead crypto alg error!\n");
15542f072d75SZaibo Xu 		return -EINVAL;
15552f072d75SZaibo Xu 	}
15562f072d75SZaibo Xu 	if (sreq->c_req.encrypt)
15572f072d75SZaibo Xu 		sreq->c_req.c_len = req->cryptlen;
15582f072d75SZaibo Xu 	else
15592f072d75SZaibo Xu 		sreq->c_req.c_len = req->cryptlen - authsize;
15602f072d75SZaibo Xu 
15612f072d75SZaibo Xu 	if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) {
15622f072d75SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "aead crypto length error!\n");
15632f072d75SZaibo Xu 		return -EINVAL;
15642f072d75SZaibo Xu 	}
15652f072d75SZaibo Xu 
15662f072d75SZaibo Xu 	return 0;
15672f072d75SZaibo Xu }
15682f072d75SZaibo Xu 
15692f072d75SZaibo Xu static int sec_aead_crypto(struct aead_request *a_req, bool encrypt)
15702f072d75SZaibo Xu {
15712f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
15722f072d75SZaibo Xu 	struct sec_req *req = aead_request_ctx(a_req);
15732f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
15742f072d75SZaibo Xu 	int ret;
15752f072d75SZaibo Xu 
15769597efc3SKai Ye 	req->flag = a_req->base.flags;
15772f072d75SZaibo Xu 	req->aead_req.aead_req = a_req;
15782f072d75SZaibo Xu 	req->c_req.encrypt = encrypt;
15792f072d75SZaibo Xu 	req->ctx = ctx;
15802f072d75SZaibo Xu 
15812f072d75SZaibo Xu 	ret = sec_aead_param_check(ctx, req);
15822f072d75SZaibo Xu 	if (unlikely(ret))
15832f072d75SZaibo Xu 		return -EINVAL;
15842f072d75SZaibo Xu 
15852f072d75SZaibo Xu 	return ctx->req_op->process(ctx, req);
15862f072d75SZaibo Xu }
15872f072d75SZaibo Xu 
15882f072d75SZaibo Xu static int sec_aead_encrypt(struct aead_request *a_req)
15892f072d75SZaibo Xu {
15902f072d75SZaibo Xu 	return sec_aead_crypto(a_req, true);
15912f072d75SZaibo Xu }
15922f072d75SZaibo Xu 
15932f072d75SZaibo Xu static int sec_aead_decrypt(struct aead_request *a_req)
15942f072d75SZaibo Xu {
15952f072d75SZaibo Xu 	return sec_aead_crypto(a_req, false);
15962f072d75SZaibo Xu }
15972f072d75SZaibo Xu 
15982f072d75SZaibo Xu #define SEC_AEAD_GEN_ALG(sec_cra_name, sec_set_key, ctx_init,\
15992f072d75SZaibo Xu 			 ctx_exit, blk_size, iv_size, max_authsize)\
16002f072d75SZaibo Xu {\
16012f072d75SZaibo Xu 	.base = {\
16022f072d75SZaibo Xu 		.cra_name = sec_cra_name,\
16032f072d75SZaibo Xu 		.cra_driver_name = "hisi_sec_"sec_cra_name,\
16042f072d75SZaibo Xu 		.cra_priority = SEC_PRIORITY,\
1605b8aa7dc5SMikulas Patocka 		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,\
16062f072d75SZaibo Xu 		.cra_blocksize = blk_size,\
16072f072d75SZaibo Xu 		.cra_ctxsize = sizeof(struct sec_ctx),\
16082f072d75SZaibo Xu 		.cra_module = THIS_MODULE,\
16092f072d75SZaibo Xu 	},\
16102f072d75SZaibo Xu 	.init = ctx_init,\
16112f072d75SZaibo Xu 	.exit = ctx_exit,\
16122f072d75SZaibo Xu 	.setkey = sec_set_key,\
16132f072d75SZaibo Xu 	.decrypt = sec_aead_decrypt,\
16142f072d75SZaibo Xu 	.encrypt = sec_aead_encrypt,\
16152f072d75SZaibo Xu 	.ivsize = iv_size,\
16162f072d75SZaibo Xu 	.maxauthsize = max_authsize,\
16172f072d75SZaibo Xu }
16182f072d75SZaibo Xu 
16192f072d75SZaibo Xu #define SEC_AEAD_ALG(algname, keyfunc, aead_init, blksize, ivsize, authsize)\
16202f072d75SZaibo Xu 	SEC_AEAD_GEN_ALG(algname, keyfunc, aead_init,\
16212f072d75SZaibo Xu 			sec_aead_ctx_exit, blksize, ivsize, authsize)
16222f072d75SZaibo Xu 
16232f072d75SZaibo Xu static struct aead_alg sec_aeads[] = {
16242f072d75SZaibo Xu 	SEC_AEAD_ALG("authenc(hmac(sha1),cbc(aes))",
16252f072d75SZaibo Xu 		     sec_setkey_aes_cbc_sha1, sec_aead_sha1_ctx_init,
16262f072d75SZaibo Xu 		     AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA1_DIGEST_SIZE),
16272f072d75SZaibo Xu 
16282f072d75SZaibo Xu 	SEC_AEAD_ALG("authenc(hmac(sha256),cbc(aes))",
16292f072d75SZaibo Xu 		     sec_setkey_aes_cbc_sha256, sec_aead_sha256_ctx_init,
16302f072d75SZaibo Xu 		     AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA256_DIGEST_SIZE),
16312f072d75SZaibo Xu 
16322f072d75SZaibo Xu 	SEC_AEAD_ALG("authenc(hmac(sha512),cbc(aes))",
16332f072d75SZaibo Xu 		     sec_setkey_aes_cbc_sha512, sec_aead_sha512_ctx_init,
16342f072d75SZaibo Xu 		     AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA512_DIGEST_SIZE),
16352f072d75SZaibo Xu };
16362f072d75SZaibo Xu 
1637416d8220SZaibo Xu int sec_register_to_crypto(void)
1638416d8220SZaibo Xu {
16393d29e98dSYang Shen 	int ret;
1640416d8220SZaibo Xu 
1641416d8220SZaibo Xu 	/* To avoid repeat register */
1642a181647cSZaibo Xu 	ret = crypto_register_skciphers(sec_skciphers,
1643a181647cSZaibo Xu 					ARRAY_SIZE(sec_skciphers));
16442f072d75SZaibo Xu 	if (ret)
16452f072d75SZaibo Xu 		return ret;
16462f072d75SZaibo Xu 
16472f072d75SZaibo Xu 	ret = crypto_register_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
16482f072d75SZaibo Xu 	if (ret)
16493d29e98dSYang Shen 		crypto_unregister_skciphers(sec_skciphers,
16503d29e98dSYang Shen 					    ARRAY_SIZE(sec_skciphers));
1651416d8220SZaibo Xu 	return ret;
1652416d8220SZaibo Xu }
1653416d8220SZaibo Xu 
1654416d8220SZaibo Xu void sec_unregister_from_crypto(void)
1655416d8220SZaibo Xu {
1656a181647cSZaibo Xu 	crypto_unregister_skciphers(sec_skciphers,
1657a181647cSZaibo Xu 				    ARRAY_SIZE(sec_skciphers));
16582f072d75SZaibo Xu 	crypto_unregister_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
16592f072d75SZaibo Xu }
1660