xref: /linux/drivers/crypto/hisilicon/sec2/sec_crypto.c (revision 129a9f340172b4f3857260a7a7bb9d7b3496ba50)
1416d8220SZaibo Xu // SPDX-License-Identifier: GPL-2.0
2416d8220SZaibo Xu /* Copyright (c) 2019 HiSilicon Limited. */
3416d8220SZaibo Xu 
4416d8220SZaibo Xu #include <crypto/aes.h>
56c46a329SKai Ye #include <crypto/aead.h>
6416d8220SZaibo Xu #include <crypto/algapi.h>
72f072d75SZaibo Xu #include <crypto/authenc.h>
8416d8220SZaibo Xu #include <crypto/des.h>
92f072d75SZaibo Xu #include <crypto/hash.h>
102f072d75SZaibo Xu #include <crypto/internal/aead.h>
11ae6ce7b1SKai Ye #include <crypto/internal/des.h>
12a24d22b2SEric Biggers #include <crypto/sha1.h>
13a24d22b2SEric Biggers #include <crypto/sha2.h>
14416d8220SZaibo Xu #include <crypto/skcipher.h>
15416d8220SZaibo Xu #include <crypto/xts.h>
16416d8220SZaibo Xu #include <linux/crypto.h>
17416d8220SZaibo Xu #include <linux/dma-mapping.h>
18416d8220SZaibo Xu #include <linux/idr.h>
19416d8220SZaibo Xu 
20416d8220SZaibo Xu #include "sec.h"
21416d8220SZaibo Xu #include "sec_crypto.h"
22416d8220SZaibo Xu 
23416d8220SZaibo Xu #define SEC_PRIORITY		4001
24416d8220SZaibo Xu #define SEC_XTS_MIN_KEY_SIZE	(2 * AES_MIN_KEY_SIZE)
255652d55aSKai Ye #define SEC_XTS_MID_KEY_SIZE	(3 * AES_MIN_KEY_SIZE)
26416d8220SZaibo Xu #define SEC_XTS_MAX_KEY_SIZE	(2 * AES_MAX_KEY_SIZE)
27416d8220SZaibo Xu #define SEC_DES3_2KEY_SIZE	(2 * DES_KEY_SIZE)
28416d8220SZaibo Xu #define SEC_DES3_3KEY_SIZE	(3 * DES_KEY_SIZE)
29416d8220SZaibo Xu 
30416d8220SZaibo Xu /* SEC sqe(bd) bit operational relative MACRO */
31416d8220SZaibo Xu #define SEC_DE_OFFSET		1
32416d8220SZaibo Xu #define SEC_CIPHER_OFFSET	4
33416d8220SZaibo Xu #define SEC_SCENE_OFFSET	3
34416d8220SZaibo Xu #define SEC_DST_SGL_OFFSET	2
35416d8220SZaibo Xu #define SEC_SRC_SGL_OFFSET	7
36416d8220SZaibo Xu #define SEC_CKEY_OFFSET		9
37416d8220SZaibo Xu #define SEC_CMODE_OFFSET	12
382f072d75SZaibo Xu #define SEC_AKEY_OFFSET         5
392f072d75SZaibo Xu #define SEC_AEAD_ALG_OFFSET     11
402f072d75SZaibo Xu #define SEC_AUTH_OFFSET		6
412f072d75SZaibo Xu 
42adc3f65aSKai Ye #define SEC_DE_OFFSET_V3		9
43adc3f65aSKai Ye #define SEC_SCENE_OFFSET_V3	5
44adc3f65aSKai Ye #define SEC_CKEY_OFFSET_V3	13
45566f060fSKai Ye #define SEC_CTR_CNT_OFFSET	25
46566f060fSKai Ye #define SEC_CTR_CNT_ROLLOVER	2
47adc3f65aSKai Ye #define SEC_SRC_SGL_OFFSET_V3	11
48adc3f65aSKai Ye #define SEC_DST_SGL_OFFSET_V3	14
49adc3f65aSKai Ye #define SEC_CALG_OFFSET_V3	4
50adc3f65aSKai Ye #define SEC_AKEY_OFFSET_V3	9
51adc3f65aSKai Ye #define SEC_MAC_OFFSET_V3	4
52adc3f65aSKai Ye #define SEC_AUTH_ALG_OFFSET_V3	15
53adc3f65aSKai Ye #define SEC_CIPHER_AUTH_V3	0xbf
54adc3f65aSKai Ye #define SEC_AUTH_CIPHER_V3	0x40
55416d8220SZaibo Xu #define SEC_FLAG_OFFSET		7
56416d8220SZaibo Xu #define SEC_FLAG_MASK		0x0780
57416d8220SZaibo Xu #define SEC_TYPE_MASK		0x0F
58416d8220SZaibo Xu #define SEC_DONE_MASK		0x0001
59668f1ab7SKai Ye #define SEC_ICV_MASK		0x000E
60adc3f65aSKai Ye #define SEC_SQE_LEN_RATE_MASK	0x3
61416d8220SZaibo Xu 
62*129a9f34SWeili Qian #define SEC_TOTAL_IV_SZ(depth)	(SEC_IV_SIZE * (depth))
63416d8220SZaibo Xu #define SEC_SGL_SGE_NR		128
642f072d75SZaibo Xu #define SEC_CIPHER_AUTH		0xfe
652f072d75SZaibo Xu #define SEC_AUTH_CIPHER		0x1
662f072d75SZaibo Xu #define SEC_MAX_MAC_LEN		64
672514f559SLongfang Liu #define SEC_MAX_AAD_LEN		65535
685e340558SKai Ye #define SEC_MAX_CCM_AAD_LEN	65279
69*129a9f34SWeili Qian #define SEC_TOTAL_MAC_SZ(depth) (SEC_MAX_MAC_LEN * (depth))
7074b58db8SLongfang Liu 
7174b58db8SLongfang Liu #define SEC_PBUF_SZ			512
7274b58db8SLongfang Liu #define SEC_PBUF_IV_OFFSET		SEC_PBUF_SZ
7374b58db8SLongfang Liu #define SEC_PBUF_MAC_OFFSET		(SEC_PBUF_SZ + SEC_IV_SIZE)
7474b58db8SLongfang Liu #define SEC_PBUF_PKG		(SEC_PBUF_SZ + SEC_IV_SIZE +	\
7574b58db8SLongfang Liu 			SEC_MAX_MAC_LEN * 2)
7674b58db8SLongfang Liu #define SEC_PBUF_NUM		(PAGE_SIZE / SEC_PBUF_PKG)
77*129a9f34SWeili Qian #define SEC_PBUF_PAGE_NUM(depth)	((depth) / SEC_PBUF_NUM)
78*129a9f34SWeili Qian #define SEC_PBUF_LEFT_SZ(depth)		(SEC_PBUF_PKG * ((depth) -	\
79*129a9f34SWeili Qian 				SEC_PBUF_PAGE_NUM(depth) * SEC_PBUF_NUM))
80*129a9f34SWeili Qian #define SEC_TOTAL_PBUF_SZ(depth)	(PAGE_SIZE * SEC_PBUF_PAGE_NUM(depth) +	\
81*129a9f34SWeili Qian 				SEC_PBUF_LEFT_SZ(depth))
8274b58db8SLongfang Liu 
832f072d75SZaibo Xu #define SEC_SQE_LEN_RATE	4
84d6de2a59SZaibo Xu #define SEC_SQE_CFLAG		2
852f072d75SZaibo Xu #define SEC_SQE_AEAD_FLAG	3
86d6de2a59SZaibo Xu #define SEC_SQE_DONE		0x1
87668f1ab7SKai Ye #define SEC_ICV_ERR		0x2
88c16a70c1SKai Ye #define MIN_MAC_LEN		4
89c16a70c1SKai Ye #define MAC_LEN_MASK		0x1U
907b44c0eeSKai Ye #define MAX_INPUT_DATA_LEN	0xFFFE00
917b44c0eeSKai Ye #define BITS_MASK		0xFF
927b44c0eeSKai Ye #define BYTE_BITS		0x8
935652d55aSKai Ye #define SEC_XTS_NAME_SZ		0x3
94c16a70c1SKai Ye #define IV_CM_CAL_NUM		2
95c16a70c1SKai Ye #define IV_CL_MASK		0x7
96c16a70c1SKai Ye #define IV_CL_MIN		2
97c16a70c1SKai Ye #define IV_CL_MID		4
98c16a70c1SKai Ye #define IV_CL_MAX		8
99c16a70c1SKai Ye #define IV_FLAGS_OFFSET	0x6
100c16a70c1SKai Ye #define IV_CM_OFFSET		0x3
101c16a70c1SKai Ye #define IV_LAST_BYTE1		1
102c16a70c1SKai Ye #define IV_LAST_BYTE2		2
103c16a70c1SKai Ye #define IV_LAST_BYTE_MASK	0xFF
104c16a70c1SKai Ye #define IV_CTR_INIT		0x1
105c16a70c1SKai Ye #define IV_BYTE_OFFSET		0x8
106416d8220SZaibo Xu 
107416d8220SZaibo Xu /* Get an en/de-cipher queue cyclically to balance load over queues of TFM */
108a181647cSZaibo Xu static inline int sec_alloc_queue_id(struct sec_ctx *ctx, struct sec_req *req)
109416d8220SZaibo Xu {
110416d8220SZaibo Xu 	if (req->c_req.encrypt)
111416d8220SZaibo Xu 		return (u32)atomic_inc_return(&ctx->enc_qcyclic) %
112416d8220SZaibo Xu 				 ctx->hlf_q_num;
113416d8220SZaibo Xu 
114416d8220SZaibo Xu 	return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num +
115416d8220SZaibo Xu 				 ctx->hlf_q_num;
116416d8220SZaibo Xu }
117416d8220SZaibo Xu 
118a181647cSZaibo Xu static inline void sec_free_queue_id(struct sec_ctx *ctx, struct sec_req *req)
119416d8220SZaibo Xu {
120416d8220SZaibo Xu 	if (req->c_req.encrypt)
121416d8220SZaibo Xu 		atomic_dec(&ctx->enc_qcyclic);
122416d8220SZaibo Xu 	else
123416d8220SZaibo Xu 		atomic_dec(&ctx->dec_qcyclic);
124416d8220SZaibo Xu }
125416d8220SZaibo Xu 
126416d8220SZaibo Xu static int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx)
127416d8220SZaibo Xu {
128416d8220SZaibo Xu 	int req_id;
129416d8220SZaibo Xu 
13002884a4fSZhengchao Shao 	spin_lock_bh(&qp_ctx->req_lock);
131*129a9f34SWeili Qian 	req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL, 0, qp_ctx->qp->sq_depth, GFP_ATOMIC);
13202884a4fSZhengchao Shao 	spin_unlock_bh(&qp_ctx->req_lock);
133b9c8d897SZaibo Xu 	if (unlikely(req_id < 0)) {
134a44dce50SLongfang Liu 		dev_err(req->ctx->dev, "alloc req id fail!\n");
135416d8220SZaibo Xu 		return req_id;
136416d8220SZaibo Xu 	}
137416d8220SZaibo Xu 
138416d8220SZaibo Xu 	req->qp_ctx = qp_ctx;
139416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = req;
140633e507fSLongfang Liu 
141416d8220SZaibo Xu 	return req_id;
142416d8220SZaibo Xu }
143416d8220SZaibo Xu 
144416d8220SZaibo Xu static void sec_free_req_id(struct sec_req *req)
145416d8220SZaibo Xu {
146416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
147416d8220SZaibo Xu 	int req_id = req->req_id;
148416d8220SZaibo Xu 
149*129a9f34SWeili Qian 	if (unlikely(req_id < 0 || req_id >= qp_ctx->qp->sq_depth)) {
150a44dce50SLongfang Liu 		dev_err(req->ctx->dev, "free request id invalid!\n");
151416d8220SZaibo Xu 		return;
152416d8220SZaibo Xu 	}
153416d8220SZaibo Xu 
154416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = NULL;
155416d8220SZaibo Xu 	req->qp_ctx = NULL;
156416d8220SZaibo Xu 
15702884a4fSZhengchao Shao 	spin_lock_bh(&qp_ctx->req_lock);
158416d8220SZaibo Xu 	idr_remove(&qp_ctx->req_idr, req_id);
15902884a4fSZhengchao Shao 	spin_unlock_bh(&qp_ctx->req_lock);
160416d8220SZaibo Xu }
161416d8220SZaibo Xu 
162adc3f65aSKai Ye static u8 pre_parse_finished_bd(struct bd_status *status, void *resp)
163adc3f65aSKai Ye {
164adc3f65aSKai Ye 	struct sec_sqe *bd = resp;
165adc3f65aSKai Ye 
166adc3f65aSKai Ye 	status->done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK;
167668f1ab7SKai Ye 	status->icv = (le16_to_cpu(bd->type2.done_flag) & SEC_ICV_MASK) >> 1;
168adc3f65aSKai Ye 	status->flag = (le16_to_cpu(bd->type2.done_flag) &
169adc3f65aSKai Ye 					SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
170adc3f65aSKai Ye 	status->tag = le16_to_cpu(bd->type2.tag);
171adc3f65aSKai Ye 	status->err_type = bd->type2.error_type;
172adc3f65aSKai Ye 
173adc3f65aSKai Ye 	return bd->type_cipher_auth & SEC_TYPE_MASK;
174adc3f65aSKai Ye }
175adc3f65aSKai Ye 
176adc3f65aSKai Ye static u8 pre_parse_finished_bd3(struct bd_status *status, void *resp)
177adc3f65aSKai Ye {
178adc3f65aSKai Ye 	struct sec_sqe3 *bd3 = resp;
179adc3f65aSKai Ye 
180adc3f65aSKai Ye 	status->done = le16_to_cpu(bd3->done_flag) & SEC_DONE_MASK;
181668f1ab7SKai Ye 	status->icv = (le16_to_cpu(bd3->done_flag) & SEC_ICV_MASK) >> 1;
182adc3f65aSKai Ye 	status->flag = (le16_to_cpu(bd3->done_flag) &
183adc3f65aSKai Ye 					SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
184adc3f65aSKai Ye 	status->tag = le64_to_cpu(bd3->tag);
185adc3f65aSKai Ye 	status->err_type = bd3->error_type;
186adc3f65aSKai Ye 
187adc3f65aSKai Ye 	return le32_to_cpu(bd3->bd_param) & SEC_TYPE_MASK;
188adc3f65aSKai Ye }
189adc3f65aSKai Ye 
190adc3f65aSKai Ye static int sec_cb_status_check(struct sec_req *req,
191adc3f65aSKai Ye 			       struct bd_status *status)
192adc3f65aSKai Ye {
193adc3f65aSKai Ye 	struct sec_ctx *ctx = req->ctx;
194adc3f65aSKai Ye 
195adc3f65aSKai Ye 	if (unlikely(req->err_type || status->done != SEC_SQE_DONE)) {
196adc3f65aSKai Ye 		dev_err_ratelimited(ctx->dev, "err_type[%d], done[%u]\n",
197adc3f65aSKai Ye 				    req->err_type, status->done);
198adc3f65aSKai Ye 		return -EIO;
199adc3f65aSKai Ye 	}
200adc3f65aSKai Ye 
201adc3f65aSKai Ye 	if (unlikely(ctx->alg_type == SEC_SKCIPHER)) {
202adc3f65aSKai Ye 		if (unlikely(status->flag != SEC_SQE_CFLAG)) {
203adc3f65aSKai Ye 			dev_err_ratelimited(ctx->dev, "flag[%u]\n",
204adc3f65aSKai Ye 					    status->flag);
205adc3f65aSKai Ye 			return -EIO;
206adc3f65aSKai Ye 		}
207668f1ab7SKai Ye 	} else if (unlikely(ctx->alg_type == SEC_AEAD)) {
208668f1ab7SKai Ye 		if (unlikely(status->flag != SEC_SQE_AEAD_FLAG ||
209668f1ab7SKai Ye 			     status->icv == SEC_ICV_ERR)) {
210668f1ab7SKai Ye 			dev_err_ratelimited(ctx->dev,
211668f1ab7SKai Ye 					    "flag[%u], icv[%u]\n",
212668f1ab7SKai Ye 					    status->flag, status->icv);
213668f1ab7SKai Ye 			return -EBADMSG;
214668f1ab7SKai Ye 		}
215adc3f65aSKai Ye 	}
216adc3f65aSKai Ye 
217adc3f65aSKai Ye 	return 0;
218adc3f65aSKai Ye }
219adc3f65aSKai Ye 
220416d8220SZaibo Xu static void sec_req_cb(struct hisi_qp *qp, void *resp)
221416d8220SZaibo Xu {
222416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = qp->qp_ctx;
2238213a1a6SKai Ye 	struct sec_dfx *dfx = &qp_ctx->ctx->sec->debug.dfx;
224adc3f65aSKai Ye 	u8 type_supported = qp_ctx->ctx->type_supported;
225adc3f65aSKai Ye 	struct bd_status status;
226d6de2a59SZaibo Xu 	struct sec_ctx *ctx;
227d6de2a59SZaibo Xu 	struct sec_req *req;
228adc3f65aSKai Ye 	int err;
229416d8220SZaibo Xu 	u8 type;
230416d8220SZaibo Xu 
231adc3f65aSKai Ye 	if (type_supported == SEC_BD_TYPE2) {
232adc3f65aSKai Ye 		type = pre_parse_finished_bd(&status, resp);
233adc3f65aSKai Ye 		req = qp_ctx->req_list[status.tag];
234adc3f65aSKai Ye 	} else {
235adc3f65aSKai Ye 		type = pre_parse_finished_bd3(&status, resp);
236adc3f65aSKai Ye 		req = (void *)(uintptr_t)status.tag;
237adc3f65aSKai Ye 	}
238adc3f65aSKai Ye 
239adc3f65aSKai Ye 	if (unlikely(type != type_supported)) {
2408213a1a6SKai Ye 		atomic64_inc(&dfx->err_bd_cnt);
24149838259SKai Ye 		pr_err("err bd type [%u]\n", type);
242416d8220SZaibo Xu 		return;
243416d8220SZaibo Xu 	}
244416d8220SZaibo Xu 
2458213a1a6SKai Ye 	if (unlikely(!req)) {
2468213a1a6SKai Ye 		atomic64_inc(&dfx->invalid_req_cnt);
2479597efc3SKai Ye 		atomic_inc(&qp->qp_status.used);
2488213a1a6SKai Ye 		return;
2498213a1a6SKai Ye 	}
250adc3f65aSKai Ye 
251adc3f65aSKai Ye 	req->err_type = status.err_type;
252d6de2a59SZaibo Xu 	ctx = req->ctx;
253adc3f65aSKai Ye 	err = sec_cb_status_check(req, &status);
254adc3f65aSKai Ye 	if (err)
2558213a1a6SKai Ye 		atomic64_inc(&dfx->done_flag_cnt);
2561e9bc276SZaibo Xu 
2578213a1a6SKai Ye 	atomic64_inc(&dfx->recv_cnt);
258416d8220SZaibo Xu 
259d6de2a59SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
260d6de2a59SZaibo Xu 
261310ea0acSZaibo Xu 	ctx->req_op->callback(ctx, req, err);
262416d8220SZaibo Xu }
263416d8220SZaibo Xu 
264416d8220SZaibo Xu static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req)
265416d8220SZaibo Xu {
266416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
267416d8220SZaibo Xu 	int ret;
268416d8220SZaibo Xu 
2699597efc3SKai Ye 	if (ctx->fake_req_limit <=
2709597efc3SKai Ye 	    atomic_read(&qp_ctx->qp->qp_status.used) &&
2719597efc3SKai Ye 	    !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG))
2729597efc3SKai Ye 		return -EBUSY;
2739597efc3SKai Ye 
27402884a4fSZhengchao Shao 	spin_lock_bh(&qp_ctx->req_lock);
275416d8220SZaibo Xu 	ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
2769597efc3SKai Ye 
2779597efc3SKai Ye 	if (ctx->fake_req_limit <=
2789597efc3SKai Ye 	    atomic_read(&qp_ctx->qp->qp_status.used) && !ret) {
2799597efc3SKai Ye 		list_add_tail(&req->backlog_head, &qp_ctx->backlog);
280cb1eeb75SArnd Bergmann 		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
2819597efc3SKai Ye 		atomic64_inc(&ctx->sec->debug.dfx.send_busy_cnt);
28202884a4fSZhengchao Shao 		spin_unlock_bh(&qp_ctx->req_lock);
2839597efc3SKai Ye 		return -EBUSY;
2849597efc3SKai Ye 	}
28502884a4fSZhengchao Shao 	spin_unlock_bh(&qp_ctx->req_lock);
286416d8220SZaibo Xu 
287b9c8d897SZaibo Xu 	if (unlikely(ret == -EBUSY))
288416d8220SZaibo Xu 		return -ENOBUFS;
289416d8220SZaibo Xu 
2909597efc3SKai Ye 	if (likely(!ret)) {
291416d8220SZaibo Xu 		ret = -EINPROGRESS;
2929597efc3SKai Ye 		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
2938213a1a6SKai Ye 	}
294416d8220SZaibo Xu 
295416d8220SZaibo Xu 	return ret;
296416d8220SZaibo Xu }
297416d8220SZaibo Xu 
2987c7d902aSZaibo Xu /* Get DMA memory resources */
2997c7d902aSZaibo Xu static int sec_alloc_civ_resource(struct device *dev, struct sec_alg_res *res)
3007c7d902aSZaibo Xu {
301*129a9f34SWeili Qian 	u16 q_depth = res->depth;
3027c7d902aSZaibo Xu 	int i;
3037c7d902aSZaibo Xu 
304*129a9f34SWeili Qian 	res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ(q_depth),
3057c7d902aSZaibo Xu 					 &res->c_ivin_dma, GFP_KERNEL);
3067c7d902aSZaibo Xu 	if (!res->c_ivin)
3077c7d902aSZaibo Xu 		return -ENOMEM;
3087c7d902aSZaibo Xu 
309*129a9f34SWeili Qian 	for (i = 1; i < q_depth; i++) {
3107c7d902aSZaibo Xu 		res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE;
3117c7d902aSZaibo Xu 		res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE;
3127c7d902aSZaibo Xu 	}
3137c7d902aSZaibo Xu 
3147c7d902aSZaibo Xu 	return 0;
3157c7d902aSZaibo Xu }
3167c7d902aSZaibo Xu 
3177c7d902aSZaibo Xu static void sec_free_civ_resource(struct device *dev, struct sec_alg_res *res)
3187c7d902aSZaibo Xu {
3197c7d902aSZaibo Xu 	if (res->c_ivin)
320*129a9f34SWeili Qian 		dma_free_coherent(dev, SEC_TOTAL_IV_SZ(res->depth),
3217c7d902aSZaibo Xu 				  res->c_ivin, res->c_ivin_dma);
3227c7d902aSZaibo Xu }
3237c7d902aSZaibo Xu 
324c16a70c1SKai Ye static int sec_alloc_aiv_resource(struct device *dev, struct sec_alg_res *res)
325c16a70c1SKai Ye {
326*129a9f34SWeili Qian 	u16 q_depth = res->depth;
327c16a70c1SKai Ye 	int i;
328c16a70c1SKai Ye 
329*129a9f34SWeili Qian 	res->a_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ(q_depth),
330c16a70c1SKai Ye 					 &res->a_ivin_dma, GFP_KERNEL);
331c16a70c1SKai Ye 	if (!res->a_ivin)
332c16a70c1SKai Ye 		return -ENOMEM;
333c16a70c1SKai Ye 
334*129a9f34SWeili Qian 	for (i = 1; i < q_depth; i++) {
335c16a70c1SKai Ye 		res[i].a_ivin_dma = res->a_ivin_dma + i * SEC_IV_SIZE;
336c16a70c1SKai Ye 		res[i].a_ivin = res->a_ivin + i * SEC_IV_SIZE;
337c16a70c1SKai Ye 	}
338c16a70c1SKai Ye 
339c16a70c1SKai Ye 	return 0;
340c16a70c1SKai Ye }
341c16a70c1SKai Ye 
342c16a70c1SKai Ye static void sec_free_aiv_resource(struct device *dev, struct sec_alg_res *res)
343c16a70c1SKai Ye {
344c16a70c1SKai Ye 	if (res->a_ivin)
345*129a9f34SWeili Qian 		dma_free_coherent(dev, SEC_TOTAL_IV_SZ(res->depth),
346c16a70c1SKai Ye 				  res->a_ivin, res->a_ivin_dma);
347c16a70c1SKai Ye }
348c16a70c1SKai Ye 
3492f072d75SZaibo Xu static int sec_alloc_mac_resource(struct device *dev, struct sec_alg_res *res)
3502f072d75SZaibo Xu {
351*129a9f34SWeili Qian 	u16 q_depth = res->depth;
3522f072d75SZaibo Xu 	int i;
3532f072d75SZaibo Xu 
354*129a9f34SWeili Qian 	res->out_mac = dma_alloc_coherent(dev, SEC_TOTAL_MAC_SZ(q_depth) << 1,
3552f072d75SZaibo Xu 					  &res->out_mac_dma, GFP_KERNEL);
3562f072d75SZaibo Xu 	if (!res->out_mac)
3572f072d75SZaibo Xu 		return -ENOMEM;
3582f072d75SZaibo Xu 
359*129a9f34SWeili Qian 	for (i = 1; i < q_depth; i++) {
3602f072d75SZaibo Xu 		res[i].out_mac_dma = res->out_mac_dma +
3612f072d75SZaibo Xu 				     i * (SEC_MAX_MAC_LEN << 1);
3622f072d75SZaibo Xu 		res[i].out_mac = res->out_mac + i * (SEC_MAX_MAC_LEN << 1);
3632f072d75SZaibo Xu 	}
3642f072d75SZaibo Xu 
3652f072d75SZaibo Xu 	return 0;
3662f072d75SZaibo Xu }
3672f072d75SZaibo Xu 
3682f072d75SZaibo Xu static void sec_free_mac_resource(struct device *dev, struct sec_alg_res *res)
3692f072d75SZaibo Xu {
3702f072d75SZaibo Xu 	if (res->out_mac)
371*129a9f34SWeili Qian 		dma_free_coherent(dev, SEC_TOTAL_MAC_SZ(res->depth) << 1,
3722f072d75SZaibo Xu 				  res->out_mac, res->out_mac_dma);
3732f072d75SZaibo Xu }
3742f072d75SZaibo Xu 
37574b58db8SLongfang Liu static void sec_free_pbuf_resource(struct device *dev, struct sec_alg_res *res)
37674b58db8SLongfang Liu {
37774b58db8SLongfang Liu 	if (res->pbuf)
378*129a9f34SWeili Qian 		dma_free_coherent(dev, SEC_TOTAL_PBUF_SZ(res->depth),
37974b58db8SLongfang Liu 				  res->pbuf, res->pbuf_dma);
38074b58db8SLongfang Liu }
38174b58db8SLongfang Liu 
38274b58db8SLongfang Liu /*
38374b58db8SLongfang Liu  * To improve performance, pbuffer is used for
38474b58db8SLongfang Liu  * small packets (< 512Bytes) as IOMMU translation using.
38574b58db8SLongfang Liu  */
38674b58db8SLongfang Liu static int sec_alloc_pbuf_resource(struct device *dev, struct sec_alg_res *res)
38774b58db8SLongfang Liu {
388*129a9f34SWeili Qian 	u16 q_depth = res->depth;
389*129a9f34SWeili Qian 	int size = SEC_PBUF_PAGE_NUM(q_depth);
39074b58db8SLongfang Liu 	int pbuf_page_offset;
39174b58db8SLongfang Liu 	int i, j, k;
39274b58db8SLongfang Liu 
393*129a9f34SWeili Qian 	res->pbuf = dma_alloc_coherent(dev, SEC_TOTAL_PBUF_SZ(q_depth),
39474b58db8SLongfang Liu 				&res->pbuf_dma, GFP_KERNEL);
39574b58db8SLongfang Liu 	if (!res->pbuf)
39674b58db8SLongfang Liu 		return -ENOMEM;
39774b58db8SLongfang Liu 
39874b58db8SLongfang Liu 	/*
39974b58db8SLongfang Liu 	 * SEC_PBUF_PKG contains data pbuf, iv and
40074b58db8SLongfang Liu 	 * out_mac : <SEC_PBUF|SEC_IV|SEC_MAC>
40174b58db8SLongfang Liu 	 * Every PAGE contains six SEC_PBUF_PKG
40274b58db8SLongfang Liu 	 * The sec_qp_ctx contains QM_Q_DEPTH numbers of SEC_PBUF_PKG
40374b58db8SLongfang Liu 	 * So we need SEC_PBUF_PAGE_NUM numbers of PAGE
40474b58db8SLongfang Liu 	 * for the SEC_TOTAL_PBUF_SZ
40574b58db8SLongfang Liu 	 */
406*129a9f34SWeili Qian 	for (i = 0; i <= size; i++) {
40774b58db8SLongfang Liu 		pbuf_page_offset = PAGE_SIZE * i;
40874b58db8SLongfang Liu 		for (j = 0; j < SEC_PBUF_NUM; j++) {
40974b58db8SLongfang Liu 			k = i * SEC_PBUF_NUM + j;
410*129a9f34SWeili Qian 			if (k == q_depth)
41174b58db8SLongfang Liu 				break;
41274b58db8SLongfang Liu 			res[k].pbuf = res->pbuf +
41374b58db8SLongfang Liu 				j * SEC_PBUF_PKG + pbuf_page_offset;
41474b58db8SLongfang Liu 			res[k].pbuf_dma = res->pbuf_dma +
41574b58db8SLongfang Liu 				j * SEC_PBUF_PKG + pbuf_page_offset;
41674b58db8SLongfang Liu 		}
41774b58db8SLongfang Liu 	}
418633e507fSLongfang Liu 
41974b58db8SLongfang Liu 	return 0;
42074b58db8SLongfang Liu }
42174b58db8SLongfang Liu 
4227c7d902aSZaibo Xu static int sec_alg_resource_alloc(struct sec_ctx *ctx,
4237c7d902aSZaibo Xu 				  struct sec_qp_ctx *qp_ctx)
4247c7d902aSZaibo Xu {
4252f072d75SZaibo Xu 	struct sec_alg_res *res = qp_ctx->res;
426a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
4272f072d75SZaibo Xu 	int ret;
4287c7d902aSZaibo Xu 
4292f072d75SZaibo Xu 	ret = sec_alloc_civ_resource(dev, res);
4302f072d75SZaibo Xu 	if (ret)
4312f072d75SZaibo Xu 		return ret;
4322f072d75SZaibo Xu 
4332f072d75SZaibo Xu 	if (ctx->alg_type == SEC_AEAD) {
434c16a70c1SKai Ye 		ret = sec_alloc_aiv_resource(dev, res);
435c16a70c1SKai Ye 		if (ret)
436c16a70c1SKai Ye 			goto alloc_aiv_fail;
437c16a70c1SKai Ye 
4382f072d75SZaibo Xu 		ret = sec_alloc_mac_resource(dev, res);
4392f072d75SZaibo Xu 		if (ret)
440c16a70c1SKai Ye 			goto alloc_mac_fail;
4412f072d75SZaibo Xu 	}
44274b58db8SLongfang Liu 	if (ctx->pbuf_supported) {
44374b58db8SLongfang Liu 		ret = sec_alloc_pbuf_resource(dev, res);
44474b58db8SLongfang Liu 		if (ret) {
44574b58db8SLongfang Liu 			dev_err(dev, "fail to alloc pbuf dma resource!\n");
44624efcec2SLongfang Liu 			goto alloc_pbuf_fail;
44774b58db8SLongfang Liu 		}
44874b58db8SLongfang Liu 	}
4492f072d75SZaibo Xu 
4502f072d75SZaibo Xu 	return 0;
451633e507fSLongfang Liu 
45224efcec2SLongfang Liu alloc_pbuf_fail:
45324efcec2SLongfang Liu 	if (ctx->alg_type == SEC_AEAD)
45424efcec2SLongfang Liu 		sec_free_mac_resource(dev, qp_ctx->res);
455c16a70c1SKai Ye alloc_mac_fail:
456c16a70c1SKai Ye 	if (ctx->alg_type == SEC_AEAD)
457c16a70c1SKai Ye 		sec_free_aiv_resource(dev, res);
458c16a70c1SKai Ye alloc_aiv_fail:
4592f072d75SZaibo Xu 	sec_free_civ_resource(dev, res);
4602f072d75SZaibo Xu 	return ret;
4617c7d902aSZaibo Xu }
4627c7d902aSZaibo Xu 
4637c7d902aSZaibo Xu static void sec_alg_resource_free(struct sec_ctx *ctx,
4647c7d902aSZaibo Xu 				  struct sec_qp_ctx *qp_ctx)
4657c7d902aSZaibo Xu {
466a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
4677c7d902aSZaibo Xu 
4687c7d902aSZaibo Xu 	sec_free_civ_resource(dev, qp_ctx->res);
4692f072d75SZaibo Xu 
47074b58db8SLongfang Liu 	if (ctx->pbuf_supported)
47174b58db8SLongfang Liu 		sec_free_pbuf_resource(dev, qp_ctx->res);
4722f072d75SZaibo Xu 	if (ctx->alg_type == SEC_AEAD)
4732f072d75SZaibo Xu 		sec_free_mac_resource(dev, qp_ctx->res);
4747c7d902aSZaibo Xu }
4757c7d902aSZaibo Xu 
476*129a9f34SWeili Qian static int sec_alloc_qp_ctx_resource(struct hisi_qm *qm, struct sec_ctx *ctx,
477*129a9f34SWeili Qian 				     struct sec_qp_ctx *qp_ctx)
478*129a9f34SWeili Qian {
479*129a9f34SWeili Qian 	u16 q_depth = qp_ctx->qp->sq_depth;
480*129a9f34SWeili Qian 	struct device *dev = ctx->dev;
481*129a9f34SWeili Qian 	int ret = -ENOMEM;
482*129a9f34SWeili Qian 
483*129a9f34SWeili Qian 	qp_ctx->req_list = kcalloc(q_depth, sizeof(struct sec_req *), GFP_KERNEL);
484*129a9f34SWeili Qian 	if (!qp_ctx->req_list)
485*129a9f34SWeili Qian 		return ret;
486*129a9f34SWeili Qian 
487*129a9f34SWeili Qian 	qp_ctx->res = kcalloc(q_depth, sizeof(struct sec_alg_res), GFP_KERNEL);
488*129a9f34SWeili Qian 	if (!qp_ctx->res)
489*129a9f34SWeili Qian 		goto err_free_req_list;
490*129a9f34SWeili Qian 	qp_ctx->res->depth = q_depth;
491*129a9f34SWeili Qian 
492*129a9f34SWeili Qian 	qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, q_depth, SEC_SGL_SGE_NR);
493*129a9f34SWeili Qian 	if (IS_ERR(qp_ctx->c_in_pool)) {
494*129a9f34SWeili Qian 		dev_err(dev, "fail to create sgl pool for input!\n");
495*129a9f34SWeili Qian 		goto err_free_res;
496*129a9f34SWeili Qian 	}
497*129a9f34SWeili Qian 
498*129a9f34SWeili Qian 	qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, q_depth, SEC_SGL_SGE_NR);
499*129a9f34SWeili Qian 	if (IS_ERR(qp_ctx->c_out_pool)) {
500*129a9f34SWeili Qian 		dev_err(dev, "fail to create sgl pool for output!\n");
501*129a9f34SWeili Qian 		goto err_free_c_in_pool;
502*129a9f34SWeili Qian 	}
503*129a9f34SWeili Qian 
504*129a9f34SWeili Qian 	ret = sec_alg_resource_alloc(ctx, qp_ctx);
505*129a9f34SWeili Qian 	if (ret)
506*129a9f34SWeili Qian 		goto err_free_c_out_pool;
507*129a9f34SWeili Qian 
508*129a9f34SWeili Qian 	return 0;
509*129a9f34SWeili Qian 
510*129a9f34SWeili Qian err_free_c_out_pool:
511*129a9f34SWeili Qian 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
512*129a9f34SWeili Qian err_free_c_in_pool:
513*129a9f34SWeili Qian 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
514*129a9f34SWeili Qian err_free_res:
515*129a9f34SWeili Qian 	kfree(qp_ctx->res);
516*129a9f34SWeili Qian err_free_req_list:
517*129a9f34SWeili Qian 	kfree(qp_ctx->req_list);
518*129a9f34SWeili Qian 	return ret;
519*129a9f34SWeili Qian }
520*129a9f34SWeili Qian 
521*129a9f34SWeili Qian static void sec_free_qp_ctx_resource(struct sec_ctx *ctx, struct sec_qp_ctx *qp_ctx)
522*129a9f34SWeili Qian {
523*129a9f34SWeili Qian 	struct device *dev = ctx->dev;
524*129a9f34SWeili Qian 
525*129a9f34SWeili Qian 	sec_alg_resource_free(ctx, qp_ctx);
526*129a9f34SWeili Qian 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
527*129a9f34SWeili Qian 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
528*129a9f34SWeili Qian 	kfree(qp_ctx->res);
529*129a9f34SWeili Qian 	kfree(qp_ctx->req_list);
530*129a9f34SWeili Qian }
531*129a9f34SWeili Qian 
532416d8220SZaibo Xu static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx,
533416d8220SZaibo Xu 			     int qp_ctx_id, int alg_type)
534416d8220SZaibo Xu {
535416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
536416d8220SZaibo Xu 	struct hisi_qp *qp;
537*129a9f34SWeili Qian 	int ret;
538416d8220SZaibo Xu 
539416d8220SZaibo Xu 	qp_ctx = &ctx->qp_ctx[qp_ctx_id];
5400b5e43bcSKai Ye 	qp = ctx->qps[qp_ctx_id];
541416d8220SZaibo Xu 	qp->req_type = 0;
542416d8220SZaibo Xu 	qp->qp_ctx = qp_ctx;
543416d8220SZaibo Xu 	qp_ctx->qp = qp;
544416d8220SZaibo Xu 	qp_ctx->ctx = ctx;
545416d8220SZaibo Xu 
546adc3f65aSKai Ye 	qp->req_cb = sec_req_cb;
547adc3f65aSKai Ye 
54802884a4fSZhengchao Shao 	spin_lock_init(&qp_ctx->req_lock);
549416d8220SZaibo Xu 	idr_init(&qp_ctx->req_idr);
5509597efc3SKai Ye 	INIT_LIST_HEAD(&qp_ctx->backlog);
551416d8220SZaibo Xu 
552*129a9f34SWeili Qian 	ret = sec_alloc_qp_ctx_resource(qm, ctx, qp_ctx);
553416d8220SZaibo Xu 	if (ret)
554*129a9f34SWeili Qian 		goto err_destroy_idr;
555416d8220SZaibo Xu 
556416d8220SZaibo Xu 	ret = hisi_qm_start_qp(qp, 0);
557416d8220SZaibo Xu 	if (ret < 0)
558*129a9f34SWeili Qian 		goto err_resource_free;
559416d8220SZaibo Xu 
560416d8220SZaibo Xu 	return 0;
561416d8220SZaibo Xu 
562*129a9f34SWeili Qian err_resource_free:
563*129a9f34SWeili Qian 	sec_free_qp_ctx_resource(ctx, qp_ctx);
564416d8220SZaibo Xu err_destroy_idr:
565416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
566416d8220SZaibo Xu 	return ret;
567416d8220SZaibo Xu }
568416d8220SZaibo Xu 
569416d8220SZaibo Xu static void sec_release_qp_ctx(struct sec_ctx *ctx,
570416d8220SZaibo Xu 			       struct sec_qp_ctx *qp_ctx)
571416d8220SZaibo Xu {
572416d8220SZaibo Xu 	hisi_qm_stop_qp(qp_ctx->qp);
573*129a9f34SWeili Qian 	sec_free_qp_ctx_resource(ctx, qp_ctx);
574416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
575416d8220SZaibo Xu }
576416d8220SZaibo Xu 
577473a0f96SZaibo Xu static int sec_ctx_base_init(struct sec_ctx *ctx)
578416d8220SZaibo Xu {
579416d8220SZaibo Xu 	struct sec_dev *sec;
580416d8220SZaibo Xu 	int i, ret;
581416d8220SZaibo Xu 
5820b5e43bcSKai Ye 	ctx->qps = sec_create_qps();
5830b5e43bcSKai Ye 	if (!ctx->qps) {
5840b5e43bcSKai Ye 		pr_err("Can not create sec qps!\n");
585416d8220SZaibo Xu 		return -ENODEV;
586416d8220SZaibo Xu 	}
5870b5e43bcSKai Ye 
5880b5e43bcSKai Ye 	sec = container_of(ctx->qps[0]->qm, struct sec_dev, qm);
589416d8220SZaibo Xu 	ctx->sec = sec;
590a44dce50SLongfang Liu 	ctx->dev = &sec->qm.pdev->dev;
591a718cfceSZaibo Xu 	ctx->hlf_q_num = sec->ctx_q_num >> 1;
592416d8220SZaibo Xu 
59374b58db8SLongfang Liu 	ctx->pbuf_supported = ctx->sec->iommu_used;
59474b58db8SLongfang Liu 
595416d8220SZaibo Xu 	/* Half of queue depth is taken as fake requests limit in the queue. */
596*129a9f34SWeili Qian 	ctx->fake_req_limit = ctx->qps[0]->sq_depth >> 1;
597416d8220SZaibo Xu 	ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx),
598416d8220SZaibo Xu 			      GFP_KERNEL);
59924efcec2SLongfang Liu 	if (!ctx->qp_ctx) {
60024efcec2SLongfang Liu 		ret = -ENOMEM;
60124efcec2SLongfang Liu 		goto err_destroy_qps;
60224efcec2SLongfang Liu 	}
603416d8220SZaibo Xu 
604416d8220SZaibo Xu 	for (i = 0; i < sec->ctx_q_num; i++) {
605473a0f96SZaibo Xu 		ret = sec_create_qp_ctx(&sec->qm, ctx, i, 0);
606416d8220SZaibo Xu 		if (ret)
607416d8220SZaibo Xu 			goto err_sec_release_qp_ctx;
608416d8220SZaibo Xu 	}
609416d8220SZaibo Xu 
610416d8220SZaibo Xu 	return 0;
61124efcec2SLongfang Liu 
612416d8220SZaibo Xu err_sec_release_qp_ctx:
613416d8220SZaibo Xu 	for (i = i - 1; i >= 0; i--)
614416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
615416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
61624efcec2SLongfang Liu err_destroy_qps:
61724efcec2SLongfang Liu 	sec_destroy_qps(ctx->qps, sec->ctx_q_num);
618416d8220SZaibo Xu 	return ret;
619416d8220SZaibo Xu }
620416d8220SZaibo Xu 
621473a0f96SZaibo Xu static void sec_ctx_base_uninit(struct sec_ctx *ctx)
622416d8220SZaibo Xu {
623473a0f96SZaibo Xu 	int i;
624416d8220SZaibo Xu 
625416d8220SZaibo Xu 	for (i = 0; i < ctx->sec->ctx_q_num; i++)
626416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
627416d8220SZaibo Xu 
6280b5e43bcSKai Ye 	sec_destroy_qps(ctx->qps, ctx->sec->ctx_q_num);
629416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
630416d8220SZaibo Xu }
631416d8220SZaibo Xu 
632473a0f96SZaibo Xu static int sec_cipher_init(struct sec_ctx *ctx)
633473a0f96SZaibo Xu {
634473a0f96SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
635473a0f96SZaibo Xu 
636a44dce50SLongfang Liu 	c_ctx->c_key = dma_alloc_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
637473a0f96SZaibo Xu 					  &c_ctx->c_key_dma, GFP_KERNEL);
638473a0f96SZaibo Xu 	if (!c_ctx->c_key)
639473a0f96SZaibo Xu 		return -ENOMEM;
640473a0f96SZaibo Xu 
641473a0f96SZaibo Xu 	return 0;
642473a0f96SZaibo Xu }
643473a0f96SZaibo Xu 
644473a0f96SZaibo Xu static void sec_cipher_uninit(struct sec_ctx *ctx)
645473a0f96SZaibo Xu {
646473a0f96SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
647473a0f96SZaibo Xu 
648473a0f96SZaibo Xu 	memzero_explicit(c_ctx->c_key, SEC_MAX_KEY_SIZE);
649a44dce50SLongfang Liu 	dma_free_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
650473a0f96SZaibo Xu 			  c_ctx->c_key, c_ctx->c_key_dma);
651473a0f96SZaibo Xu }
652473a0f96SZaibo Xu 
6532f072d75SZaibo Xu static int sec_auth_init(struct sec_ctx *ctx)
6542f072d75SZaibo Xu {
6552f072d75SZaibo Xu 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
6562f072d75SZaibo Xu 
65745f5d017SKai Ye 	a_ctx->a_key = dma_alloc_coherent(ctx->dev, SEC_MAX_AKEY_SIZE,
6582f072d75SZaibo Xu 					  &a_ctx->a_key_dma, GFP_KERNEL);
6592f072d75SZaibo Xu 	if (!a_ctx->a_key)
6602f072d75SZaibo Xu 		return -ENOMEM;
6612f072d75SZaibo Xu 
6622f072d75SZaibo Xu 	return 0;
6632f072d75SZaibo Xu }
6642f072d75SZaibo Xu 
6652f072d75SZaibo Xu static void sec_auth_uninit(struct sec_ctx *ctx)
6662f072d75SZaibo Xu {
6672f072d75SZaibo Xu 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
6682f072d75SZaibo Xu 
66945f5d017SKai Ye 	memzero_explicit(a_ctx->a_key, SEC_MAX_AKEY_SIZE);
67045f5d017SKai Ye 	dma_free_coherent(ctx->dev, SEC_MAX_AKEY_SIZE,
6712f072d75SZaibo Xu 			  a_ctx->a_key, a_ctx->a_key_dma);
6722f072d75SZaibo Xu }
6732f072d75SZaibo Xu 
6745652d55aSKai Ye static int sec_skcipher_fbtfm_init(struct crypto_skcipher *tfm)
6755652d55aSKai Ye {
6765652d55aSKai Ye 	const char *alg = crypto_tfm_alg_name(&tfm->base);
6775652d55aSKai Ye 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
6785652d55aSKai Ye 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
6795652d55aSKai Ye 
6805652d55aSKai Ye 	c_ctx->fallback = false;
681e764d81dSKai Ye 
682e764d81dSKai Ye 	/* Currently, only XTS mode need fallback tfm when using 192bit key */
6835652d55aSKai Ye 	if (likely(strncmp(alg, "xts", SEC_XTS_NAME_SZ)))
6845652d55aSKai Ye 		return 0;
6855652d55aSKai Ye 
6865652d55aSKai Ye 	c_ctx->fbtfm = crypto_alloc_sync_skcipher(alg, 0,
6875652d55aSKai Ye 						  CRYPTO_ALG_NEED_FALLBACK);
6885652d55aSKai Ye 	if (IS_ERR(c_ctx->fbtfm)) {
689e764d81dSKai Ye 		pr_err("failed to alloc xts mode fallback tfm!\n");
6905652d55aSKai Ye 		return PTR_ERR(c_ctx->fbtfm);
6915652d55aSKai Ye 	}
6925652d55aSKai Ye 
6935652d55aSKai Ye 	return 0;
6945652d55aSKai Ye }
6955652d55aSKai Ye 
696473a0f96SZaibo Xu static int sec_skcipher_init(struct crypto_skcipher *tfm)
697473a0f96SZaibo Xu {
698473a0f96SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
699473a0f96SZaibo Xu 	int ret;
700473a0f96SZaibo Xu 
7012f072d75SZaibo Xu 	ctx->alg_type = SEC_SKCIPHER;
702473a0f96SZaibo Xu 	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req));
703473a0f96SZaibo Xu 	ctx->c_ctx.ivsize = crypto_skcipher_ivsize(tfm);
704473a0f96SZaibo Xu 	if (ctx->c_ctx.ivsize > SEC_IV_SIZE) {
7054b7aef02SLongfang Liu 		pr_err("get error skcipher iv size!\n");
706473a0f96SZaibo Xu 		return -EINVAL;
707473a0f96SZaibo Xu 	}
708473a0f96SZaibo Xu 
709473a0f96SZaibo Xu 	ret = sec_ctx_base_init(ctx);
710473a0f96SZaibo Xu 	if (ret)
711473a0f96SZaibo Xu 		return ret;
712473a0f96SZaibo Xu 
713473a0f96SZaibo Xu 	ret = sec_cipher_init(ctx);
714473a0f96SZaibo Xu 	if (ret)
715473a0f96SZaibo Xu 		goto err_cipher_init;
716473a0f96SZaibo Xu 
7175652d55aSKai Ye 	ret = sec_skcipher_fbtfm_init(tfm);
7185652d55aSKai Ye 	if (ret)
7195652d55aSKai Ye 		goto err_fbtfm_init;
7205652d55aSKai Ye 
721473a0f96SZaibo Xu 	return 0;
722633e507fSLongfang Liu 
7235652d55aSKai Ye err_fbtfm_init:
7245652d55aSKai Ye 	sec_cipher_uninit(ctx);
725473a0f96SZaibo Xu err_cipher_init:
726473a0f96SZaibo Xu 	sec_ctx_base_uninit(ctx);
727473a0f96SZaibo Xu 	return ret;
728473a0f96SZaibo Xu }
729473a0f96SZaibo Xu 
730473a0f96SZaibo Xu static void sec_skcipher_uninit(struct crypto_skcipher *tfm)
731473a0f96SZaibo Xu {
732473a0f96SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
733473a0f96SZaibo Xu 
7345652d55aSKai Ye 	if (ctx->c_ctx.fbtfm)
7355652d55aSKai Ye 		crypto_free_sync_skcipher(ctx->c_ctx.fbtfm);
7365652d55aSKai Ye 
737473a0f96SZaibo Xu 	sec_cipher_uninit(ctx);
738473a0f96SZaibo Xu 	sec_ctx_base_uninit(ctx);
739473a0f96SZaibo Xu }
740473a0f96SZaibo Xu 
741ae6ce7b1SKai Ye static int sec_skcipher_3des_setkey(struct crypto_skcipher *tfm, const u8 *key,
742416d8220SZaibo Xu 				    const u32 keylen,
743416d8220SZaibo Xu 				    const enum sec_cmode c_mode)
744416d8220SZaibo Xu {
745ae6ce7b1SKai Ye 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
746ae6ce7b1SKai Ye 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
747ae6ce7b1SKai Ye 	int ret;
748ae6ce7b1SKai Ye 
749ae6ce7b1SKai Ye 	ret = verify_skcipher_des3_key(tfm, key);
750ae6ce7b1SKai Ye 	if (ret)
751ae6ce7b1SKai Ye 		return ret;
752ae6ce7b1SKai Ye 
753416d8220SZaibo Xu 	switch (keylen) {
754416d8220SZaibo Xu 	case SEC_DES3_2KEY_SIZE:
755416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_2KEY;
756416d8220SZaibo Xu 		break;
757416d8220SZaibo Xu 	case SEC_DES3_3KEY_SIZE:
758416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_3KEY;
759416d8220SZaibo Xu 		break;
760416d8220SZaibo Xu 	default:
761416d8220SZaibo Xu 		return -EINVAL;
762416d8220SZaibo Xu 	}
763416d8220SZaibo Xu 
764416d8220SZaibo Xu 	return 0;
765416d8220SZaibo Xu }
766416d8220SZaibo Xu 
767416d8220SZaibo Xu static int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx,
768416d8220SZaibo Xu 				       const u32 keylen,
769416d8220SZaibo Xu 				       const enum sec_cmode c_mode)
770416d8220SZaibo Xu {
771416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
772416d8220SZaibo Xu 		switch (keylen) {
773416d8220SZaibo Xu 		case SEC_XTS_MIN_KEY_SIZE:
774416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_128BIT;
775416d8220SZaibo Xu 			break;
7765652d55aSKai Ye 		case SEC_XTS_MID_KEY_SIZE:
7775652d55aSKai Ye 			c_ctx->fallback = true;
7785652d55aSKai Ye 			break;
779416d8220SZaibo Xu 		case SEC_XTS_MAX_KEY_SIZE:
780416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_256BIT;
781416d8220SZaibo Xu 			break;
782416d8220SZaibo Xu 		default:
783416d8220SZaibo Xu 			pr_err("hisi_sec2: xts mode key error!\n");
784416d8220SZaibo Xu 			return -EINVAL;
785416d8220SZaibo Xu 		}
786416d8220SZaibo Xu 	} else {
787adc3f65aSKai Ye 		if (c_ctx->c_alg == SEC_CALG_SM4 &&
788adc3f65aSKai Ye 		    keylen != AES_KEYSIZE_128) {
789adc3f65aSKai Ye 			pr_err("hisi_sec2: sm4 key error!\n");
790adc3f65aSKai Ye 			return -EINVAL;
791adc3f65aSKai Ye 		} else {
792416d8220SZaibo Xu 			switch (keylen) {
793416d8220SZaibo Xu 			case AES_KEYSIZE_128:
794416d8220SZaibo Xu 				c_ctx->c_key_len = SEC_CKEY_128BIT;
795416d8220SZaibo Xu 				break;
796416d8220SZaibo Xu 			case AES_KEYSIZE_192:
797416d8220SZaibo Xu 				c_ctx->c_key_len = SEC_CKEY_192BIT;
798416d8220SZaibo Xu 				break;
799416d8220SZaibo Xu 			case AES_KEYSIZE_256:
800416d8220SZaibo Xu 				c_ctx->c_key_len = SEC_CKEY_256BIT;
801416d8220SZaibo Xu 				break;
802416d8220SZaibo Xu 			default:
803416d8220SZaibo Xu 				pr_err("hisi_sec2: aes key error!\n");
804416d8220SZaibo Xu 				return -EINVAL;
805416d8220SZaibo Xu 			}
806416d8220SZaibo Xu 		}
807adc3f65aSKai Ye 	}
808416d8220SZaibo Xu 
809416d8220SZaibo Xu 	return 0;
810416d8220SZaibo Xu }
811416d8220SZaibo Xu 
812416d8220SZaibo Xu static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
813416d8220SZaibo Xu 			       const u32 keylen, const enum sec_calg c_alg,
814416d8220SZaibo Xu 			       const enum sec_cmode c_mode)
815416d8220SZaibo Xu {
816416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
817416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
818a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
819416d8220SZaibo Xu 	int ret;
820416d8220SZaibo Xu 
821416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
822416d8220SZaibo Xu 		ret = xts_verify_key(tfm, key, keylen);
823416d8220SZaibo Xu 		if (ret) {
824a44dce50SLongfang Liu 			dev_err(dev, "xts mode key err!\n");
825416d8220SZaibo Xu 			return ret;
826416d8220SZaibo Xu 		}
827416d8220SZaibo Xu 	}
828416d8220SZaibo Xu 
829416d8220SZaibo Xu 	c_ctx->c_alg  = c_alg;
830416d8220SZaibo Xu 	c_ctx->c_mode = c_mode;
831416d8220SZaibo Xu 
832416d8220SZaibo Xu 	switch (c_alg) {
833416d8220SZaibo Xu 	case SEC_CALG_3DES:
834ae6ce7b1SKai Ye 		ret = sec_skcipher_3des_setkey(tfm, key, keylen, c_mode);
835416d8220SZaibo Xu 		break;
836416d8220SZaibo Xu 	case SEC_CALG_AES:
837416d8220SZaibo Xu 	case SEC_CALG_SM4:
838416d8220SZaibo Xu 		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
839416d8220SZaibo Xu 		break;
840416d8220SZaibo Xu 	default:
841416d8220SZaibo Xu 		return -EINVAL;
842416d8220SZaibo Xu 	}
843416d8220SZaibo Xu 
844416d8220SZaibo Xu 	if (ret) {
845a44dce50SLongfang Liu 		dev_err(dev, "set sec key err!\n");
846416d8220SZaibo Xu 		return ret;
847416d8220SZaibo Xu 	}
848416d8220SZaibo Xu 
849416d8220SZaibo Xu 	memcpy(c_ctx->c_key, key, keylen);
850e764d81dSKai Ye 	if (c_ctx->fallback && c_ctx->fbtfm) {
8515652d55aSKai Ye 		ret = crypto_sync_skcipher_setkey(c_ctx->fbtfm, key, keylen);
8525652d55aSKai Ye 		if (ret) {
8535652d55aSKai Ye 			dev_err(dev, "failed to set fallback skcipher key!\n");
8545652d55aSKai Ye 			return ret;
8555652d55aSKai Ye 		}
8565652d55aSKai Ye 	}
857416d8220SZaibo Xu 	return 0;
858416d8220SZaibo Xu }
859416d8220SZaibo Xu 
860416d8220SZaibo Xu #define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode)			\
861416d8220SZaibo Xu static int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\
862416d8220SZaibo Xu 	u32 keylen)							\
863416d8220SZaibo Xu {									\
864416d8220SZaibo Xu 	return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode);	\
865416d8220SZaibo Xu }
866416d8220SZaibo Xu 
867416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB)
868416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC)
869416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS)
8707b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(aes_ofb, SEC_CALG_AES, SEC_CMODE_OFB)
8717b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(aes_cfb, SEC_CALG_AES, SEC_CMODE_CFB)
8727b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(aes_ctr, SEC_CALG_AES, SEC_CMODE_CTR)
873416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB)
874416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC)
875416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS)
876416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC)
8777b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(sm4_ofb, SEC_CALG_SM4, SEC_CMODE_OFB)
8787b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(sm4_cfb, SEC_CALG_SM4, SEC_CMODE_CFB)
8797b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(sm4_ctr, SEC_CALG_SM4, SEC_CMODE_CTR)
880416d8220SZaibo Xu 
88174b58db8SLongfang Liu static int sec_cipher_pbuf_map(struct sec_ctx *ctx, struct sec_req *req,
88274b58db8SLongfang Liu 			struct scatterlist *src)
88374b58db8SLongfang Liu {
8846c46a329SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
8856c46a329SKai Ye 	struct aead_request *aead_req = a_req->aead_req;
88674b58db8SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
88774b58db8SLongfang Liu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
888a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
88974b58db8SLongfang Liu 	int copy_size, pbuf_length;
89074b58db8SLongfang Liu 	int req_id = req->req_id;
8916c46a329SKai Ye 	struct crypto_aead *tfm;
8926c46a329SKai Ye 	size_t authsize;
8936c46a329SKai Ye 	u8 *mac_offset;
89474b58db8SLongfang Liu 
89574b58db8SLongfang Liu 	if (ctx->alg_type == SEC_AEAD)
89674b58db8SLongfang Liu 		copy_size = aead_req->cryptlen + aead_req->assoclen;
89774b58db8SLongfang Liu 	else
89874b58db8SLongfang Liu 		copy_size = c_req->c_len;
89974b58db8SLongfang Liu 
90074b58db8SLongfang Liu 	pbuf_length = sg_copy_to_buffer(src, sg_nents(src),
9016c46a329SKai Ye 			qp_ctx->res[req_id].pbuf, copy_size);
90274b58db8SLongfang Liu 	if (unlikely(pbuf_length != copy_size)) {
90374b58db8SLongfang Liu 		dev_err(dev, "copy src data to pbuf error!\n");
90474b58db8SLongfang Liu 		return -EINVAL;
90574b58db8SLongfang Liu 	}
9066c46a329SKai Ye 	if (!c_req->encrypt && ctx->alg_type == SEC_AEAD) {
9076c46a329SKai Ye 		tfm = crypto_aead_reqtfm(aead_req);
9086c46a329SKai Ye 		authsize = crypto_aead_authsize(tfm);
9096c46a329SKai Ye 		mac_offset = qp_ctx->res[req_id].pbuf + copy_size - authsize;
9106c46a329SKai Ye 		memcpy(a_req->out_mac, mac_offset, authsize);
9116c46a329SKai Ye 	}
91274b58db8SLongfang Liu 
9139039878aSKai Ye 	req->in_dma = qp_ctx->res[req_id].pbuf_dma;
9149039878aSKai Ye 	c_req->c_out_dma = req->in_dma;
91574b58db8SLongfang Liu 
91674b58db8SLongfang Liu 	return 0;
91774b58db8SLongfang Liu }
91874b58db8SLongfang Liu 
91974b58db8SLongfang Liu static void sec_cipher_pbuf_unmap(struct sec_ctx *ctx, struct sec_req *req,
92074b58db8SLongfang Liu 			struct scatterlist *dst)
92174b58db8SLongfang Liu {
92274b58db8SLongfang Liu 	struct aead_request *aead_req = req->aead_req.aead_req;
92374b58db8SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
92474b58db8SLongfang Liu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
92574b58db8SLongfang Liu 	int copy_size, pbuf_length;
92674b58db8SLongfang Liu 	int req_id = req->req_id;
92774b58db8SLongfang Liu 
92874b58db8SLongfang Liu 	if (ctx->alg_type == SEC_AEAD)
92974b58db8SLongfang Liu 		copy_size = c_req->c_len + aead_req->assoclen;
93074b58db8SLongfang Liu 	else
93174b58db8SLongfang Liu 		copy_size = c_req->c_len;
93274b58db8SLongfang Liu 
93374b58db8SLongfang Liu 	pbuf_length = sg_copy_from_buffer(dst, sg_nents(dst),
934668f1ab7SKai Ye 			qp_ctx->res[req_id].pbuf, copy_size);
93574b58db8SLongfang Liu 	if (unlikely(pbuf_length != copy_size))
936668f1ab7SKai Ye 		dev_err(ctx->dev, "copy pbuf data to dst error!\n");
937668f1ab7SKai Ye }
938668f1ab7SKai Ye 
939668f1ab7SKai Ye static int sec_aead_mac_init(struct sec_aead_req *req)
940668f1ab7SKai Ye {
941668f1ab7SKai Ye 	struct aead_request *aead_req = req->aead_req;
942668f1ab7SKai Ye 	struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
943668f1ab7SKai Ye 	size_t authsize = crypto_aead_authsize(tfm);
944668f1ab7SKai Ye 	u8 *mac_out = req->out_mac;
945668f1ab7SKai Ye 	struct scatterlist *sgl = aead_req->src;
946668f1ab7SKai Ye 	size_t copy_size;
947668f1ab7SKai Ye 	off_t skip_size;
948668f1ab7SKai Ye 
949668f1ab7SKai Ye 	/* Copy input mac */
950668f1ab7SKai Ye 	skip_size = aead_req->assoclen + aead_req->cryptlen - authsize;
951668f1ab7SKai Ye 	copy_size = sg_pcopy_to_buffer(sgl, sg_nents(sgl), mac_out,
952668f1ab7SKai Ye 				       authsize, skip_size);
953668f1ab7SKai Ye 	if (unlikely(copy_size != authsize))
954668f1ab7SKai Ye 		return -EINVAL;
955668f1ab7SKai Ye 
956668f1ab7SKai Ye 	return 0;
95774b58db8SLongfang Liu }
95874b58db8SLongfang Liu 
9592514f559SLongfang Liu static int sec_cipher_map(struct sec_ctx *ctx, struct sec_req *req,
960416d8220SZaibo Xu 			  struct scatterlist *src, struct scatterlist *dst)
961416d8220SZaibo Xu {
962416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
9632514f559SLongfang Liu 	struct sec_aead_req *a_req = &req->aead_req;
964416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
9652514f559SLongfang Liu 	struct sec_alg_res *res = &qp_ctx->res[req->req_id];
966a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
96774b58db8SLongfang Liu 	int ret;
9682514f559SLongfang Liu 
96974b58db8SLongfang Liu 	if (req->use_pbuf) {
97074b58db8SLongfang Liu 		c_req->c_ivin = res->pbuf + SEC_PBUF_IV_OFFSET;
97174b58db8SLongfang Liu 		c_req->c_ivin_dma = res->pbuf_dma + SEC_PBUF_IV_OFFSET;
97274b58db8SLongfang Liu 		if (ctx->alg_type == SEC_AEAD) {
973c16a70c1SKai Ye 			a_req->a_ivin = res->a_ivin;
974c16a70c1SKai Ye 			a_req->a_ivin_dma = res->a_ivin_dma;
97574b58db8SLongfang Liu 			a_req->out_mac = res->pbuf + SEC_PBUF_MAC_OFFSET;
97674b58db8SLongfang Liu 			a_req->out_mac_dma = res->pbuf_dma +
97774b58db8SLongfang Liu 					SEC_PBUF_MAC_OFFSET;
97874b58db8SLongfang Liu 		}
979668f1ab7SKai Ye 		ret = sec_cipher_pbuf_map(ctx, req, src);
98074b58db8SLongfang Liu 
98174b58db8SLongfang Liu 		return ret;
98274b58db8SLongfang Liu 	}
9832514f559SLongfang Liu 	c_req->c_ivin = res->c_ivin;
9842514f559SLongfang Liu 	c_req->c_ivin_dma = res->c_ivin_dma;
9852514f559SLongfang Liu 	if (ctx->alg_type == SEC_AEAD) {
986c16a70c1SKai Ye 		a_req->a_ivin = res->a_ivin;
987c16a70c1SKai Ye 		a_req->a_ivin_dma = res->a_ivin_dma;
9882514f559SLongfang Liu 		a_req->out_mac = res->out_mac;
9892514f559SLongfang Liu 		a_req->out_mac_dma = res->out_mac_dma;
9902514f559SLongfang Liu 	}
991416d8220SZaibo Xu 
9929039878aSKai Ye 	req->in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src,
993416d8220SZaibo Xu 						qp_ctx->c_in_pool,
994416d8220SZaibo Xu 						req->req_id,
9959039878aSKai Ye 						&req->in_dma);
9969039878aSKai Ye 	if (IS_ERR(req->in)) {
997416d8220SZaibo Xu 		dev_err(dev, "fail to dma map input sgl buffers!\n");
9989039878aSKai Ye 		return PTR_ERR(req->in);
999416d8220SZaibo Xu 	}
1000416d8220SZaibo Xu 
1001668f1ab7SKai Ye 	if (!c_req->encrypt && ctx->alg_type == SEC_AEAD) {
1002668f1ab7SKai Ye 		ret = sec_aead_mac_init(a_req);
1003668f1ab7SKai Ye 		if (unlikely(ret)) {
1004668f1ab7SKai Ye 			dev_err(dev, "fail to init mac data for ICV!\n");
1005668f1ab7SKai Ye 			return ret;
1006668f1ab7SKai Ye 		}
1007668f1ab7SKai Ye 	}
10089039878aSKai Ye 
1009416d8220SZaibo Xu 	if (dst == src) {
10109039878aSKai Ye 		c_req->c_out = req->in;
10119039878aSKai Ye 		c_req->c_out_dma = req->in_dma;
1012416d8220SZaibo Xu 	} else {
1013416d8220SZaibo Xu 		c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst,
1014416d8220SZaibo Xu 							     qp_ctx->c_out_pool,
1015416d8220SZaibo Xu 							     req->req_id,
1016416d8220SZaibo Xu 							     &c_req->c_out_dma);
1017416d8220SZaibo Xu 
1018416d8220SZaibo Xu 		if (IS_ERR(c_req->c_out)) {
1019416d8220SZaibo Xu 			dev_err(dev, "fail to dma map output sgl buffers!\n");
10209039878aSKai Ye 			hisi_acc_sg_buf_unmap(dev, src, req->in);
1021416d8220SZaibo Xu 			return PTR_ERR(c_req->c_out);
1022416d8220SZaibo Xu 		}
1023416d8220SZaibo Xu 	}
1024416d8220SZaibo Xu 
1025416d8220SZaibo Xu 	return 0;
1026416d8220SZaibo Xu }
1027416d8220SZaibo Xu 
10282514f559SLongfang Liu static void sec_cipher_unmap(struct sec_ctx *ctx, struct sec_req *req,
1029a181647cSZaibo Xu 			     struct scatterlist *src, struct scatterlist *dst)
1030a181647cSZaibo Xu {
10312514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
1032a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
1033a181647cSZaibo Xu 
103474b58db8SLongfang Liu 	if (req->use_pbuf) {
103574b58db8SLongfang Liu 		sec_cipher_pbuf_unmap(ctx, req, dst);
103674b58db8SLongfang Liu 	} else {
10372514f559SLongfang Liu 		if (dst != src)
10389039878aSKai Ye 			hisi_acc_sg_buf_unmap(dev, src, req->in);
10392514f559SLongfang Liu 
10402514f559SLongfang Liu 		hisi_acc_sg_buf_unmap(dev, dst, c_req->c_out);
1041a181647cSZaibo Xu 	}
104274b58db8SLongfang Liu }
1043a181647cSZaibo Xu 
1044416d8220SZaibo Xu static int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
1045416d8220SZaibo Xu {
1046a181647cSZaibo Xu 	struct skcipher_request *sq = req->c_req.sk_req;
1047416d8220SZaibo Xu 
10482514f559SLongfang Liu 	return sec_cipher_map(ctx, req, sq->src, sq->dst);
1049416d8220SZaibo Xu }
1050416d8220SZaibo Xu 
1051416d8220SZaibo Xu static void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
1052416d8220SZaibo Xu {
10532514f559SLongfang Liu 	struct skcipher_request *sq = req->c_req.sk_req;
1054416d8220SZaibo Xu 
10552514f559SLongfang Liu 	sec_cipher_unmap(ctx, req, sq->src, sq->dst);
1056416d8220SZaibo Xu }
1057416d8220SZaibo Xu 
10582f072d75SZaibo Xu static int sec_aead_aes_set_key(struct sec_cipher_ctx *c_ctx,
10592f072d75SZaibo Xu 				struct crypto_authenc_keys *keys)
10602f072d75SZaibo Xu {
10612f072d75SZaibo Xu 	switch (keys->enckeylen) {
10622f072d75SZaibo Xu 	case AES_KEYSIZE_128:
10632f072d75SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_128BIT;
10642f072d75SZaibo Xu 		break;
10652f072d75SZaibo Xu 	case AES_KEYSIZE_192:
10662f072d75SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_192BIT;
10672f072d75SZaibo Xu 		break;
10682f072d75SZaibo Xu 	case AES_KEYSIZE_256:
10692f072d75SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_256BIT;
10702f072d75SZaibo Xu 		break;
10712f072d75SZaibo Xu 	default:
10722f072d75SZaibo Xu 		pr_err("hisi_sec2: aead aes key error!\n");
10732f072d75SZaibo Xu 		return -EINVAL;
10742f072d75SZaibo Xu 	}
10752f072d75SZaibo Xu 	memcpy(c_ctx->c_key, keys->enckey, keys->enckeylen);
10762f072d75SZaibo Xu 
10772f072d75SZaibo Xu 	return 0;
10782f072d75SZaibo Xu }
10792f072d75SZaibo Xu 
10802f072d75SZaibo Xu static int sec_aead_auth_set_key(struct sec_auth_ctx *ctx,
10812f072d75SZaibo Xu 				 struct crypto_authenc_keys *keys)
10822f072d75SZaibo Xu {
10832f072d75SZaibo Xu 	struct crypto_shash *hash_tfm = ctx->hash_tfm;
10845761498cSKai Ye 	int blocksize, digestsize, ret;
10852f072d75SZaibo Xu 
10862f072d75SZaibo Xu 	if (!keys->authkeylen) {
10872f072d75SZaibo Xu 		pr_err("hisi_sec2: aead auth key error!\n");
10882f072d75SZaibo Xu 		return -EINVAL;
10892f072d75SZaibo Xu 	}
10902f072d75SZaibo Xu 
10912f072d75SZaibo Xu 	blocksize = crypto_shash_blocksize(hash_tfm);
10925761498cSKai Ye 	digestsize = crypto_shash_digestsize(hash_tfm);
10932f072d75SZaibo Xu 	if (keys->authkeylen > blocksize) {
109461c38e3aSEric Biggers 		ret = crypto_shash_tfm_digest(hash_tfm, keys->authkey,
10952f072d75SZaibo Xu 					      keys->authkeylen, ctx->a_key);
10962f072d75SZaibo Xu 		if (ret) {
10972203d3f7SColin Ian King 			pr_err("hisi_sec2: aead auth digest error!\n");
10982f072d75SZaibo Xu 			return -EINVAL;
10992f072d75SZaibo Xu 		}
11005761498cSKai Ye 		ctx->a_key_len = digestsize;
11012f072d75SZaibo Xu 	} else {
11022f072d75SZaibo Xu 		memcpy(ctx->a_key, keys->authkey, keys->authkeylen);
11032f072d75SZaibo Xu 		ctx->a_key_len = keys->authkeylen;
11042f072d75SZaibo Xu 	}
11052f072d75SZaibo Xu 
11062f072d75SZaibo Xu 	return 0;
11072f072d75SZaibo Xu }
11082f072d75SZaibo Xu 
11096c46a329SKai Ye static int sec_aead_setauthsize(struct crypto_aead *aead, unsigned int authsize)
11106c46a329SKai Ye {
11116c46a329SKai Ye 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
11126c46a329SKai Ye 	struct sec_ctx *ctx = crypto_tfm_ctx(tfm);
11136c46a329SKai Ye 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
11146c46a329SKai Ye 
11156c46a329SKai Ye 	if (unlikely(a_ctx->fallback_aead_tfm))
11166c46a329SKai Ye 		return crypto_aead_setauthsize(a_ctx->fallback_aead_tfm, authsize);
11176c46a329SKai Ye 
11186c46a329SKai Ye 	return 0;
11196c46a329SKai Ye }
11206c46a329SKai Ye 
11216c46a329SKai Ye static int sec_aead_fallback_setkey(struct sec_auth_ctx *a_ctx,
11226c46a329SKai Ye 				    struct crypto_aead *tfm, const u8 *key,
11236c46a329SKai Ye 				    unsigned int keylen)
11246c46a329SKai Ye {
11256c46a329SKai Ye 	crypto_aead_clear_flags(a_ctx->fallback_aead_tfm, CRYPTO_TFM_REQ_MASK);
11266c46a329SKai Ye 	crypto_aead_set_flags(a_ctx->fallback_aead_tfm,
11276c46a329SKai Ye 			      crypto_aead_get_flags(tfm) & CRYPTO_TFM_REQ_MASK);
11286c46a329SKai Ye 	return crypto_aead_setkey(a_ctx->fallback_aead_tfm, key, keylen);
11296c46a329SKai Ye }
11306c46a329SKai Ye 
11312f072d75SZaibo Xu static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
11322f072d75SZaibo Xu 			   const u32 keylen, const enum sec_hash_alg a_alg,
11332f072d75SZaibo Xu 			   const enum sec_calg c_alg,
11342f072d75SZaibo Xu 			   const enum sec_mac_len mac_len,
11352f072d75SZaibo Xu 			   const enum sec_cmode c_mode)
11362f072d75SZaibo Xu {
11372f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
11382f072d75SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
11396c46a329SKai Ye 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
1140a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
11412f072d75SZaibo Xu 	struct crypto_authenc_keys keys;
11422f072d75SZaibo Xu 	int ret;
11432f072d75SZaibo Xu 
11442f072d75SZaibo Xu 	ctx->a_ctx.a_alg = a_alg;
11452f072d75SZaibo Xu 	ctx->c_ctx.c_alg = c_alg;
11462f072d75SZaibo Xu 	ctx->a_ctx.mac_len = mac_len;
11472f072d75SZaibo Xu 	c_ctx->c_mode = c_mode;
11482f072d75SZaibo Xu 
1149c16a70c1SKai Ye 	if (c_mode == SEC_CMODE_CCM || c_mode == SEC_CMODE_GCM) {
1150c16a70c1SKai Ye 		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
1151c16a70c1SKai Ye 		if (ret) {
1152c16a70c1SKai Ye 			dev_err(dev, "set sec aes ccm cipher key err!\n");
1153c16a70c1SKai Ye 			return ret;
1154c16a70c1SKai Ye 		}
1155c16a70c1SKai Ye 		memcpy(c_ctx->c_key, key, keylen);
1156c16a70c1SKai Ye 
11576c46a329SKai Ye 		if (unlikely(a_ctx->fallback_aead_tfm)) {
11586c46a329SKai Ye 			ret = sec_aead_fallback_setkey(a_ctx, tfm, key, keylen);
11596c46a329SKai Ye 			if (ret)
11606c46a329SKai Ye 				return ret;
11616c46a329SKai Ye 		}
11626c46a329SKai Ye 
1163c16a70c1SKai Ye 		return 0;
1164c16a70c1SKai Ye 	}
1165c16a70c1SKai Ye 
11662f072d75SZaibo Xu 	if (crypto_authenc_extractkeys(&keys, key, keylen))
11672f072d75SZaibo Xu 		goto bad_key;
11682f072d75SZaibo Xu 
11692f072d75SZaibo Xu 	ret = sec_aead_aes_set_key(c_ctx, &keys);
11702f072d75SZaibo Xu 	if (ret) {
1171a44dce50SLongfang Liu 		dev_err(dev, "set sec cipher key err!\n");
11722f072d75SZaibo Xu 		goto bad_key;
11732f072d75SZaibo Xu 	}
11742f072d75SZaibo Xu 
11752f072d75SZaibo Xu 	ret = sec_aead_auth_set_key(&ctx->a_ctx, &keys);
11762f072d75SZaibo Xu 	if (ret) {
1177a44dce50SLongfang Liu 		dev_err(dev, "set sec auth key err!\n");
11782f072d75SZaibo Xu 		goto bad_key;
11792f072d75SZaibo Xu 	}
11802f072d75SZaibo Xu 
1181adc3f65aSKai Ye 	if ((ctx->a_ctx.mac_len & SEC_SQE_LEN_RATE_MASK)  ||
1182adc3f65aSKai Ye 	    (ctx->a_ctx.a_key_len & SEC_SQE_LEN_RATE_MASK)) {
1183adc3f65aSKai Ye 		dev_err(dev, "MAC or AUTH key length error!\n");
1184adc3f65aSKai Ye 		goto bad_key;
1185adc3f65aSKai Ye 	}
1186adc3f65aSKai Ye 
11872f072d75SZaibo Xu 	return 0;
1188633e507fSLongfang Liu 
11892f072d75SZaibo Xu bad_key:
11902f072d75SZaibo Xu 	memzero_explicit(&keys, sizeof(struct crypto_authenc_keys));
11912f072d75SZaibo Xu 	return -EINVAL;
11922f072d75SZaibo Xu }
11932f072d75SZaibo Xu 
11942f072d75SZaibo Xu 
11952f072d75SZaibo Xu #define GEN_SEC_AEAD_SETKEY_FUNC(name, aalg, calg, maclen, cmode)	\
11962f072d75SZaibo Xu static int sec_setkey_##name(struct crypto_aead *tfm, const u8 *key,	\
11972f072d75SZaibo Xu 	u32 keylen)							\
11982f072d75SZaibo Xu {									\
11992f072d75SZaibo Xu 	return sec_aead_setkey(tfm, key, keylen, aalg, calg, maclen, cmode);\
12002f072d75SZaibo Xu }
12012f072d75SZaibo Xu 
12022f072d75SZaibo Xu GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha1, SEC_A_HMAC_SHA1,
12032f072d75SZaibo Xu 			 SEC_CALG_AES, SEC_HMAC_SHA1_MAC, SEC_CMODE_CBC)
12042f072d75SZaibo Xu GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha256, SEC_A_HMAC_SHA256,
12052f072d75SZaibo Xu 			 SEC_CALG_AES, SEC_HMAC_SHA256_MAC, SEC_CMODE_CBC)
12062f072d75SZaibo Xu GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha512, SEC_A_HMAC_SHA512,
12072f072d75SZaibo Xu 			 SEC_CALG_AES, SEC_HMAC_SHA512_MAC, SEC_CMODE_CBC)
1208c16a70c1SKai Ye GEN_SEC_AEAD_SETKEY_FUNC(aes_ccm, 0, SEC_CALG_AES,
1209c16a70c1SKai Ye 			 SEC_HMAC_CCM_MAC, SEC_CMODE_CCM)
1210c16a70c1SKai Ye GEN_SEC_AEAD_SETKEY_FUNC(aes_gcm, 0, SEC_CALG_AES,
1211c16a70c1SKai Ye 			 SEC_HMAC_GCM_MAC, SEC_CMODE_GCM)
1212c16a70c1SKai Ye GEN_SEC_AEAD_SETKEY_FUNC(sm4_ccm, 0, SEC_CALG_SM4,
1213c16a70c1SKai Ye 			 SEC_HMAC_CCM_MAC, SEC_CMODE_CCM)
1214c16a70c1SKai Ye GEN_SEC_AEAD_SETKEY_FUNC(sm4_gcm, 0, SEC_CALG_SM4,
1215c16a70c1SKai Ye 			 SEC_HMAC_GCM_MAC, SEC_CMODE_GCM)
12162f072d75SZaibo Xu 
12172f072d75SZaibo Xu static int sec_aead_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
12182f072d75SZaibo Xu {
12192f072d75SZaibo Xu 	struct aead_request *aq = req->aead_req.aead_req;
12202f072d75SZaibo Xu 
12212514f559SLongfang Liu 	return sec_cipher_map(ctx, req, aq->src, aq->dst);
12222f072d75SZaibo Xu }
12232f072d75SZaibo Xu 
12242f072d75SZaibo Xu static void sec_aead_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
12252f072d75SZaibo Xu {
12262f072d75SZaibo Xu 	struct aead_request *aq = req->aead_req.aead_req;
12272f072d75SZaibo Xu 
12282514f559SLongfang Liu 	sec_cipher_unmap(ctx, req, aq->src, aq->dst);
12292f072d75SZaibo Xu }
12302f072d75SZaibo Xu 
1231416d8220SZaibo Xu static int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req)
1232416d8220SZaibo Xu {
1233416d8220SZaibo Xu 	int ret;
1234416d8220SZaibo Xu 
1235416d8220SZaibo Xu 	ret = ctx->req_op->buf_map(ctx, req);
1236b9c8d897SZaibo Xu 	if (unlikely(ret))
1237416d8220SZaibo Xu 		return ret;
1238416d8220SZaibo Xu 
1239416d8220SZaibo Xu 	ctx->req_op->do_transfer(ctx, req);
1240416d8220SZaibo Xu 
1241416d8220SZaibo Xu 	ret = ctx->req_op->bd_fill(ctx, req);
1242b9c8d897SZaibo Xu 	if (unlikely(ret))
1243416d8220SZaibo Xu 		goto unmap_req_buf;
1244416d8220SZaibo Xu 
1245416d8220SZaibo Xu 	return ret;
1246416d8220SZaibo Xu 
1247416d8220SZaibo Xu unmap_req_buf:
1248416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
1249416d8220SZaibo Xu 	return ret;
1250416d8220SZaibo Xu }
1251416d8220SZaibo Xu 
1252416d8220SZaibo Xu static void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req)
1253416d8220SZaibo Xu {
1254416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
1255416d8220SZaibo Xu }
1256416d8220SZaibo Xu 
1257416d8220SZaibo Xu static void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
1258416d8220SZaibo Xu {
1259416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
12602514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
1261416d8220SZaibo Xu 
12622514f559SLongfang Liu 	memcpy(c_req->c_ivin, sk_req->iv, ctx->c_ctx.ivsize);
1263416d8220SZaibo Xu }
1264416d8220SZaibo Xu 
1265416d8220SZaibo Xu static int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
1266416d8220SZaibo Xu {
1267416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
1268416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
1269416d8220SZaibo Xu 	struct sec_sqe *sec_sqe = &req->sec_sqe;
1270416d8220SZaibo Xu 	u8 scene, sa_type, da_type;
1271416d8220SZaibo Xu 	u8 bd_type, cipher;
12727c7d902aSZaibo Xu 	u8 de = 0;
1273416d8220SZaibo Xu 
1274416d8220SZaibo Xu 	memset(sec_sqe, 0, sizeof(struct sec_sqe));
1275416d8220SZaibo Xu 
1276416d8220SZaibo Xu 	sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
12772514f559SLongfang Liu 	sec_sqe->type2.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
12789039878aSKai Ye 	sec_sqe->type2.data_src_addr = cpu_to_le64(req->in_dma);
1279416d8220SZaibo Xu 	sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma);
1280416d8220SZaibo Xu 
1281416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) <<
1282416d8220SZaibo Xu 						SEC_CMODE_OFFSET);
1283416d8220SZaibo Xu 	sec_sqe->type2.c_alg = c_ctx->c_alg;
1284416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
1285416d8220SZaibo Xu 						SEC_CKEY_OFFSET);
1286416d8220SZaibo Xu 
1287416d8220SZaibo Xu 	bd_type = SEC_BD_TYPE2;
1288416d8220SZaibo Xu 	if (c_req->encrypt)
1289416d8220SZaibo Xu 		cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET;
1290416d8220SZaibo Xu 	else
1291416d8220SZaibo Xu 		cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET;
1292416d8220SZaibo Xu 	sec_sqe->type_cipher_auth = bd_type | cipher;
1293416d8220SZaibo Xu 
1294adc3f65aSKai Ye 	/* Set destination and source address type */
1295adc3f65aSKai Ye 	if (req->use_pbuf) {
129674b58db8SLongfang Liu 		sa_type = SEC_PBUF << SEC_SRC_SGL_OFFSET;
1297adc3f65aSKai Ye 		da_type = SEC_PBUF << SEC_DST_SGL_OFFSET;
1298adc3f65aSKai Ye 	} else {
1299416d8220SZaibo Xu 		sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET;
1300adc3f65aSKai Ye 		da_type = SEC_SGL << SEC_DST_SGL_OFFSET;
1301adc3f65aSKai Ye 	}
1302adc3f65aSKai Ye 
1303adc3f65aSKai Ye 	sec_sqe->sdm_addr_type |= da_type;
1304416d8220SZaibo Xu 	scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET;
13059039878aSKai Ye 	if (req->in_dma != c_req->c_out_dma)
1306416d8220SZaibo Xu 		de = 0x1 << SEC_DE_OFFSET;
1307416d8220SZaibo Xu 
1308416d8220SZaibo Xu 	sec_sqe->sds_sa_type = (de | scene | sa_type);
1309416d8220SZaibo Xu 
1310416d8220SZaibo Xu 	sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len);
1311416d8220SZaibo Xu 	sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id);
1312416d8220SZaibo Xu 
1313416d8220SZaibo Xu 	return 0;
1314416d8220SZaibo Xu }
1315416d8220SZaibo Xu 
1316adc3f65aSKai Ye static int sec_skcipher_bd_fill_v3(struct sec_ctx *ctx, struct sec_req *req)
1317adc3f65aSKai Ye {
1318adc3f65aSKai Ye 	struct sec_sqe3 *sec_sqe3 = &req->sec_sqe3;
1319adc3f65aSKai Ye 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
1320adc3f65aSKai Ye 	struct sec_cipher_req *c_req = &req->c_req;
1321adc3f65aSKai Ye 	u32 bd_param = 0;
1322adc3f65aSKai Ye 	u16 cipher;
1323adc3f65aSKai Ye 
1324adc3f65aSKai Ye 	memset(sec_sqe3, 0, sizeof(struct sec_sqe3));
1325adc3f65aSKai Ye 
1326adc3f65aSKai Ye 	sec_sqe3->c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
1327adc3f65aSKai Ye 	sec_sqe3->no_scene.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
13289039878aSKai Ye 	sec_sqe3->data_src_addr = cpu_to_le64(req->in_dma);
1329adc3f65aSKai Ye 	sec_sqe3->data_dst_addr = cpu_to_le64(c_req->c_out_dma);
1330adc3f65aSKai Ye 
1331adc3f65aSKai Ye 	sec_sqe3->c_mode_alg = ((u8)c_ctx->c_alg << SEC_CALG_OFFSET_V3) |
1332adc3f65aSKai Ye 						c_ctx->c_mode;
1333adc3f65aSKai Ye 	sec_sqe3->c_icv_key |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
1334adc3f65aSKai Ye 						SEC_CKEY_OFFSET_V3);
1335adc3f65aSKai Ye 
1336adc3f65aSKai Ye 	if (c_req->encrypt)
1337adc3f65aSKai Ye 		cipher = SEC_CIPHER_ENC;
1338adc3f65aSKai Ye 	else
1339adc3f65aSKai Ye 		cipher = SEC_CIPHER_DEC;
1340adc3f65aSKai Ye 	sec_sqe3->c_icv_key |= cpu_to_le16(cipher);
1341adc3f65aSKai Ye 
1342566f060fSKai Ye 	/* Set the CTR counter mode is 128bit rollover */
1343566f060fSKai Ye 	sec_sqe3->auth_mac_key = cpu_to_le32((u32)SEC_CTR_CNT_ROLLOVER <<
1344566f060fSKai Ye 					SEC_CTR_CNT_OFFSET);
1345566f060fSKai Ye 
1346adc3f65aSKai Ye 	if (req->use_pbuf) {
1347adc3f65aSKai Ye 		bd_param |= SEC_PBUF << SEC_SRC_SGL_OFFSET_V3;
1348adc3f65aSKai Ye 		bd_param |= SEC_PBUF << SEC_DST_SGL_OFFSET_V3;
1349adc3f65aSKai Ye 	} else {
1350adc3f65aSKai Ye 		bd_param |= SEC_SGL << SEC_SRC_SGL_OFFSET_V3;
1351adc3f65aSKai Ye 		bd_param |= SEC_SGL << SEC_DST_SGL_OFFSET_V3;
1352adc3f65aSKai Ye 	}
1353adc3f65aSKai Ye 
1354adc3f65aSKai Ye 	bd_param |= SEC_COMM_SCENE << SEC_SCENE_OFFSET_V3;
13559039878aSKai Ye 	if (req->in_dma != c_req->c_out_dma)
1356adc3f65aSKai Ye 		bd_param |= 0x1 << SEC_DE_OFFSET_V3;
1357adc3f65aSKai Ye 
1358adc3f65aSKai Ye 	bd_param |= SEC_BD_TYPE3;
1359adc3f65aSKai Ye 	sec_sqe3->bd_param = cpu_to_le32(bd_param);
1360adc3f65aSKai Ye 
1361adc3f65aSKai Ye 	sec_sqe3->c_len_ivin |= cpu_to_le32(c_req->c_len);
1362adc3f65aSKai Ye 	sec_sqe3->tag = cpu_to_le64(req);
1363adc3f65aSKai Ye 
1364adc3f65aSKai Ye 	return 0;
1365adc3f65aSKai Ye }
1366adc3f65aSKai Ye 
13677b44c0eeSKai Ye /* increment counter (128-bit int) */
13687b44c0eeSKai Ye static void ctr_iv_inc(__u8 *counter, __u8 bits, __u32 nums)
13697b44c0eeSKai Ye {
13707b44c0eeSKai Ye 	do {
13717b44c0eeSKai Ye 		--bits;
13727b44c0eeSKai Ye 		nums += counter[bits];
13737b44c0eeSKai Ye 		counter[bits] = nums & BITS_MASK;
13747b44c0eeSKai Ye 		nums >>= BYTE_BITS;
13757b44c0eeSKai Ye 	} while (bits && nums);
13767b44c0eeSKai Ye }
13777b44c0eeSKai Ye 
13782f072d75SZaibo Xu static void sec_update_iv(struct sec_req *req, enum sec_alg_type alg_type)
1379416d8220SZaibo Xu {
13802f072d75SZaibo Xu 	struct aead_request *aead_req = req->aead_req.aead_req;
1381416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
1382416d8220SZaibo Xu 	u32 iv_size = req->ctx->c_ctx.ivsize;
1383416d8220SZaibo Xu 	struct scatterlist *sgl;
13842f072d75SZaibo Xu 	unsigned int cryptlen;
1385416d8220SZaibo Xu 	size_t sz;
13862f072d75SZaibo Xu 	u8 *iv;
1387416d8220SZaibo Xu 
1388416d8220SZaibo Xu 	if (req->c_req.encrypt)
13892f072d75SZaibo Xu 		sgl = alg_type == SEC_SKCIPHER ? sk_req->dst : aead_req->dst;
1390416d8220SZaibo Xu 	else
13912f072d75SZaibo Xu 		sgl = alg_type == SEC_SKCIPHER ? sk_req->src : aead_req->src;
1392416d8220SZaibo Xu 
13932f072d75SZaibo Xu 	if (alg_type == SEC_SKCIPHER) {
13942f072d75SZaibo Xu 		iv = sk_req->iv;
13952f072d75SZaibo Xu 		cryptlen = sk_req->cryptlen;
13962f072d75SZaibo Xu 	} else {
13972f072d75SZaibo Xu 		iv = aead_req->iv;
13982f072d75SZaibo Xu 		cryptlen = aead_req->cryptlen;
13992f072d75SZaibo Xu 	}
14002f072d75SZaibo Xu 
14017b44c0eeSKai Ye 	if (req->ctx->c_ctx.c_mode == SEC_CMODE_CBC) {
14022f072d75SZaibo Xu 		sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), iv, iv_size,
14032f072d75SZaibo Xu 					cryptlen - iv_size);
1404b9c8d897SZaibo Xu 		if (unlikely(sz != iv_size))
1405a44dce50SLongfang Liu 			dev_err(req->ctx->dev, "copy output iv error!\n");
14067b44c0eeSKai Ye 	} else {
14077b44c0eeSKai Ye 		sz = cryptlen / iv_size;
14087b44c0eeSKai Ye 		if (cryptlen % iv_size)
14097b44c0eeSKai Ye 			sz += 1;
14107b44c0eeSKai Ye 		ctr_iv_inc(iv, iv_size, sz);
14117b44c0eeSKai Ye 	}
1412416d8220SZaibo Xu }
1413416d8220SZaibo Xu 
14149597efc3SKai Ye static struct sec_req *sec_back_req_clear(struct sec_ctx *ctx,
14159597efc3SKai Ye 				struct sec_qp_ctx *qp_ctx)
14169597efc3SKai Ye {
14179597efc3SKai Ye 	struct sec_req *backlog_req = NULL;
14189597efc3SKai Ye 
141902884a4fSZhengchao Shao 	spin_lock_bh(&qp_ctx->req_lock);
14209597efc3SKai Ye 	if (ctx->fake_req_limit >=
14219597efc3SKai Ye 	    atomic_read(&qp_ctx->qp->qp_status.used) &&
14229597efc3SKai Ye 	    !list_empty(&qp_ctx->backlog)) {
14239597efc3SKai Ye 		backlog_req = list_first_entry(&qp_ctx->backlog,
14249597efc3SKai Ye 				typeof(*backlog_req), backlog_head);
14259597efc3SKai Ye 		list_del(&backlog_req->backlog_head);
14269597efc3SKai Ye 	}
142702884a4fSZhengchao Shao 	spin_unlock_bh(&qp_ctx->req_lock);
14289597efc3SKai Ye 
14299597efc3SKai Ye 	return backlog_req;
14309597efc3SKai Ye }
14319597efc3SKai Ye 
1432310ea0acSZaibo Xu static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req,
1433310ea0acSZaibo Xu 				  int err)
1434416d8220SZaibo Xu {
1435416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
1436416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
14379597efc3SKai Ye 	struct skcipher_request *backlog_sk_req;
14389597efc3SKai Ye 	struct sec_req *backlog_req;
1439416d8220SZaibo Xu 
1440416d8220SZaibo Xu 	sec_free_req_id(req);
1441416d8220SZaibo Xu 
14427b44c0eeSKai Ye 	/* IV output at encrypto of CBC/CTR mode */
14437b44c0eeSKai Ye 	if (!err && (ctx->c_ctx.c_mode == SEC_CMODE_CBC ||
14447b44c0eeSKai Ye 	    ctx->c_ctx.c_mode == SEC_CMODE_CTR) && req->c_req.encrypt)
14452f072d75SZaibo Xu 		sec_update_iv(req, SEC_SKCIPHER);
1446416d8220SZaibo Xu 
14479597efc3SKai Ye 	while (1) {
14489597efc3SKai Ye 		backlog_req = sec_back_req_clear(ctx, qp_ctx);
14499597efc3SKai Ye 		if (!backlog_req)
14509597efc3SKai Ye 			break;
14519597efc3SKai Ye 
14529597efc3SKai Ye 		backlog_sk_req = backlog_req->c_req.sk_req;
14539597efc3SKai Ye 		backlog_sk_req->base.complete(&backlog_sk_req->base,
14549597efc3SKai Ye 						-EINPROGRESS);
14559597efc3SKai Ye 		atomic64_inc(&ctx->sec->debug.dfx.recv_busy_cnt);
14569597efc3SKai Ye 	}
14579597efc3SKai Ye 
1458310ea0acSZaibo Xu 	sk_req->base.complete(&sk_req->base, err);
1459416d8220SZaibo Xu }
1460416d8220SZaibo Xu 
1461c16a70c1SKai Ye static void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req)
14622f072d75SZaibo Xu {
14632f072d75SZaibo Xu 	struct aead_request *aead_req = req->aead_req.aead_req;
14642514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
1465c16a70c1SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
1466c16a70c1SKai Ye 	size_t authsize = ctx->a_ctx.mac_len;
1467c16a70c1SKai Ye 	u32 data_size = aead_req->cryptlen;
1468c16a70c1SKai Ye 	u8 flage = 0;
1469c16a70c1SKai Ye 	u8 cm, cl;
1470c16a70c1SKai Ye 
1471c16a70c1SKai Ye 	/* the specification has been checked in aead_iv_demension_check() */
1472c16a70c1SKai Ye 	cl = c_req->c_ivin[0] + 1;
1473c16a70c1SKai Ye 	c_req->c_ivin[ctx->c_ctx.ivsize - cl] = 0x00;
1474c16a70c1SKai Ye 	memset(&c_req->c_ivin[ctx->c_ctx.ivsize - cl], 0, cl);
1475c16a70c1SKai Ye 	c_req->c_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE1] = IV_CTR_INIT;
1476c16a70c1SKai Ye 
1477c16a70c1SKai Ye 	/* the last 3bit is L' */
1478c16a70c1SKai Ye 	flage |= c_req->c_ivin[0] & IV_CL_MASK;
1479c16a70c1SKai Ye 
1480c16a70c1SKai Ye 	/* the M' is bit3~bit5, the Flags is bit6 */
1481c16a70c1SKai Ye 	cm = (authsize - IV_CM_CAL_NUM) / IV_CM_CAL_NUM;
1482c16a70c1SKai Ye 	flage |= cm << IV_CM_OFFSET;
1483c16a70c1SKai Ye 	if (aead_req->assoclen)
1484c16a70c1SKai Ye 		flage |= 0x01 << IV_FLAGS_OFFSET;
1485c16a70c1SKai Ye 
1486c16a70c1SKai Ye 	memcpy(a_req->a_ivin, c_req->c_ivin, ctx->c_ctx.ivsize);
1487c16a70c1SKai Ye 	a_req->a_ivin[0] = flage;
1488c16a70c1SKai Ye 
1489c16a70c1SKai Ye 	/*
1490c16a70c1SKai Ye 	 * the last 32bit is counter's initial number,
1491c16a70c1SKai Ye 	 * but the nonce uses the first 16bit
1492c16a70c1SKai Ye 	 * the tail 16bit fill with the cipher length
1493c16a70c1SKai Ye 	 */
1494c16a70c1SKai Ye 	if (!c_req->encrypt)
1495c16a70c1SKai Ye 		data_size = aead_req->cryptlen - authsize;
1496c16a70c1SKai Ye 
1497c16a70c1SKai Ye 	a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE1] =
1498c16a70c1SKai Ye 			data_size & IV_LAST_BYTE_MASK;
1499c16a70c1SKai Ye 	data_size >>= IV_BYTE_OFFSET;
1500c16a70c1SKai Ye 	a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE2] =
1501c16a70c1SKai Ye 			data_size & IV_LAST_BYTE_MASK;
1502c16a70c1SKai Ye }
1503c16a70c1SKai Ye 
1504c16a70c1SKai Ye static void sec_aead_set_iv(struct sec_ctx *ctx, struct sec_req *req)
1505c16a70c1SKai Ye {
1506c16a70c1SKai Ye 	struct aead_request *aead_req = req->aead_req.aead_req;
1507c16a70c1SKai Ye 	struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
1508c16a70c1SKai Ye 	size_t authsize = crypto_aead_authsize(tfm);
1509c16a70c1SKai Ye 	struct sec_cipher_req *c_req = &req->c_req;
1510c16a70c1SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
15112f072d75SZaibo Xu 
15122514f559SLongfang Liu 	memcpy(c_req->c_ivin, aead_req->iv, ctx->c_ctx.ivsize);
1513c16a70c1SKai Ye 
1514c16a70c1SKai Ye 	if (ctx->c_ctx.c_mode == SEC_CMODE_CCM) {
1515c16a70c1SKai Ye 		/*
1516c16a70c1SKai Ye 		 * CCM 16Byte Cipher_IV: {1B_Flage,13B_IV,2B_counter},
1517c16a70c1SKai Ye 		 * the  counter must set to 0x01
1518c16a70c1SKai Ye 		 */
1519c16a70c1SKai Ye 		ctx->a_ctx.mac_len = authsize;
1520c16a70c1SKai Ye 		/* CCM 16Byte Auth_IV: {1B_AFlage,13B_IV,2B_Ptext_length} */
1521c16a70c1SKai Ye 		set_aead_auth_iv(ctx, req);
1522c16a70c1SKai Ye 	}
1523c16a70c1SKai Ye 
1524c16a70c1SKai Ye 	/* GCM 12Byte Cipher_IV == Auth_IV */
1525c16a70c1SKai Ye 	if (ctx->c_ctx.c_mode == SEC_CMODE_GCM) {
1526c16a70c1SKai Ye 		ctx->a_ctx.mac_len = authsize;
1527c16a70c1SKai Ye 		memcpy(a_req->a_ivin, c_req->c_ivin, SEC_AIV_SIZE);
1528c16a70c1SKai Ye 	}
1529c16a70c1SKai Ye }
1530c16a70c1SKai Ye 
1531c16a70c1SKai Ye static void sec_auth_bd_fill_xcm(struct sec_auth_ctx *ctx, int dir,
1532c16a70c1SKai Ye 				 struct sec_req *req, struct sec_sqe *sec_sqe)
1533c16a70c1SKai Ye {
1534c16a70c1SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
1535c16a70c1SKai Ye 	struct aead_request *aq = a_req->aead_req;
1536c16a70c1SKai Ye 
1537c16a70c1SKai Ye 	/* C_ICV_Len is MAC size, 0x4 ~ 0x10 */
1538c16a70c1SKai Ye 	sec_sqe->type2.icvw_kmode |= cpu_to_le16((u16)ctx->mac_len);
1539c16a70c1SKai Ye 
1540c16a70c1SKai Ye 	/* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */
1541c16a70c1SKai Ye 	sec_sqe->type2.a_key_addr = sec_sqe->type2.c_key_addr;
1542c16a70c1SKai Ye 	sec_sqe->type2.a_ivin_addr = cpu_to_le64(a_req->a_ivin_dma);
1543c16a70c1SKai Ye 	sec_sqe->type_cipher_auth |= SEC_NO_AUTH << SEC_AUTH_OFFSET;
1544c16a70c1SKai Ye 
1545c16a70c1SKai Ye 	if (dir)
1546c16a70c1SKai Ye 		sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH;
1547c16a70c1SKai Ye 	else
1548c16a70c1SKai Ye 		sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER;
1549c16a70c1SKai Ye 
1550c16a70c1SKai Ye 	sec_sqe->type2.alen_ivllen = cpu_to_le32(aq->assoclen);
1551c16a70c1SKai Ye 	sec_sqe->type2.auth_src_offset = cpu_to_le16(0x0);
1552c16a70c1SKai Ye 	sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
1553c16a70c1SKai Ye 
1554c16a70c1SKai Ye 	sec_sqe->type2.mac_addr = cpu_to_le64(a_req->out_mac_dma);
1555c16a70c1SKai Ye }
1556c16a70c1SKai Ye 
1557c16a70c1SKai Ye static void sec_auth_bd_fill_xcm_v3(struct sec_auth_ctx *ctx, int dir,
1558c16a70c1SKai Ye 				    struct sec_req *req, struct sec_sqe3 *sqe3)
1559c16a70c1SKai Ye {
1560c16a70c1SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
1561c16a70c1SKai Ye 	struct aead_request *aq = a_req->aead_req;
1562c16a70c1SKai Ye 
1563c16a70c1SKai Ye 	/* C_ICV_Len is MAC size, 0x4 ~ 0x10 */
1564c16a70c1SKai Ye 	sqe3->c_icv_key |= cpu_to_le16((u16)ctx->mac_len << SEC_MAC_OFFSET_V3);
1565c16a70c1SKai Ye 
1566c16a70c1SKai Ye 	/* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */
1567c16a70c1SKai Ye 	sqe3->a_key_addr = sqe3->c_key_addr;
1568c16a70c1SKai Ye 	sqe3->auth_ivin.a_ivin_addr = cpu_to_le64(a_req->a_ivin_dma);
1569c16a70c1SKai Ye 	sqe3->auth_mac_key |= SEC_NO_AUTH;
1570c16a70c1SKai Ye 
1571c16a70c1SKai Ye 	if (dir)
1572c16a70c1SKai Ye 		sqe3->huk_iv_seq &= SEC_CIPHER_AUTH_V3;
1573c16a70c1SKai Ye 	else
1574c16a70c1SKai Ye 		sqe3->huk_iv_seq |= SEC_AUTH_CIPHER_V3;
1575c16a70c1SKai Ye 
1576c16a70c1SKai Ye 	sqe3->a_len_key = cpu_to_le32(aq->assoclen);
1577c16a70c1SKai Ye 	sqe3->auth_src_offset = cpu_to_le16(0x0);
1578c16a70c1SKai Ye 	sqe3->cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
1579c16a70c1SKai Ye 	sqe3->mac_addr = cpu_to_le64(a_req->out_mac_dma);
15802f072d75SZaibo Xu }
15812f072d75SZaibo Xu 
15822f072d75SZaibo Xu static void sec_auth_bd_fill_ex(struct sec_auth_ctx *ctx, int dir,
15832f072d75SZaibo Xu 			       struct sec_req *req, struct sec_sqe *sec_sqe)
15842f072d75SZaibo Xu {
15852f072d75SZaibo Xu 	struct sec_aead_req *a_req = &req->aead_req;
15862f072d75SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
15872f072d75SZaibo Xu 	struct aead_request *aq = a_req->aead_req;
15882f072d75SZaibo Xu 
15892f072d75SZaibo Xu 	sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma);
15902f072d75SZaibo Xu 
15912f072d75SZaibo Xu 	sec_sqe->type2.mac_key_alg =
15922f072d75SZaibo Xu 			cpu_to_le32(ctx->mac_len / SEC_SQE_LEN_RATE);
15932f072d75SZaibo Xu 
15942f072d75SZaibo Xu 	sec_sqe->type2.mac_key_alg |=
15952f072d75SZaibo Xu 			cpu_to_le32((u32)((ctx->a_key_len) /
15962f072d75SZaibo Xu 			SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET);
15972f072d75SZaibo Xu 
15982f072d75SZaibo Xu 	sec_sqe->type2.mac_key_alg |=
15992f072d75SZaibo Xu 			cpu_to_le32((u32)(ctx->a_alg) << SEC_AEAD_ALG_OFFSET);
16002f072d75SZaibo Xu 
1601668f1ab7SKai Ye 	if (dir) {
16022f072d75SZaibo Xu 		sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE1 << SEC_AUTH_OFFSET;
16032f072d75SZaibo Xu 		sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH;
1604668f1ab7SKai Ye 	} else {
1605668f1ab7SKai Ye 		sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE2 << SEC_AUTH_OFFSET;
16062f072d75SZaibo Xu 		sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER;
1607668f1ab7SKai Ye 	}
16082f072d75SZaibo Xu 	sec_sqe->type2.alen_ivllen = cpu_to_le32(c_req->c_len + aq->assoclen);
16092f072d75SZaibo Xu 
16102f072d75SZaibo Xu 	sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
16112f072d75SZaibo Xu 
16122514f559SLongfang Liu 	sec_sqe->type2.mac_addr = cpu_to_le64(a_req->out_mac_dma);
16132f072d75SZaibo Xu }
16142f072d75SZaibo Xu 
16152f072d75SZaibo Xu static int sec_aead_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
16162f072d75SZaibo Xu {
16172f072d75SZaibo Xu 	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
16182f072d75SZaibo Xu 	struct sec_sqe *sec_sqe = &req->sec_sqe;
16192f072d75SZaibo Xu 	int ret;
16202f072d75SZaibo Xu 
16212f072d75SZaibo Xu 	ret = sec_skcipher_bd_fill(ctx, req);
16222f072d75SZaibo Xu 	if (unlikely(ret)) {
1623a44dce50SLongfang Liu 		dev_err(ctx->dev, "skcipher bd fill is error!\n");
16242f072d75SZaibo Xu 		return ret;
16252f072d75SZaibo Xu 	}
16262f072d75SZaibo Xu 
1627c16a70c1SKai Ye 	if (ctx->c_ctx.c_mode == SEC_CMODE_CCM ||
1628c16a70c1SKai Ye 	    ctx->c_ctx.c_mode == SEC_CMODE_GCM)
1629c16a70c1SKai Ye 		sec_auth_bd_fill_xcm(auth_ctx, req->c_req.encrypt, req, sec_sqe);
1630c16a70c1SKai Ye 	else
16312f072d75SZaibo Xu 		sec_auth_bd_fill_ex(auth_ctx, req->c_req.encrypt, req, sec_sqe);
16322f072d75SZaibo Xu 
16332f072d75SZaibo Xu 	return 0;
16342f072d75SZaibo Xu }
16352f072d75SZaibo Xu 
1636adc3f65aSKai Ye static void sec_auth_bd_fill_ex_v3(struct sec_auth_ctx *ctx, int dir,
1637adc3f65aSKai Ye 				   struct sec_req *req, struct sec_sqe3 *sqe3)
1638adc3f65aSKai Ye {
1639adc3f65aSKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
1640adc3f65aSKai Ye 	struct sec_cipher_req *c_req = &req->c_req;
1641adc3f65aSKai Ye 	struct aead_request *aq = a_req->aead_req;
1642adc3f65aSKai Ye 
1643adc3f65aSKai Ye 	sqe3->a_key_addr = cpu_to_le64(ctx->a_key_dma);
1644adc3f65aSKai Ye 
1645adc3f65aSKai Ye 	sqe3->auth_mac_key |=
1646adc3f65aSKai Ye 			cpu_to_le32((u32)(ctx->mac_len /
1647adc3f65aSKai Ye 			SEC_SQE_LEN_RATE) << SEC_MAC_OFFSET_V3);
1648adc3f65aSKai Ye 
1649adc3f65aSKai Ye 	sqe3->auth_mac_key |=
1650adc3f65aSKai Ye 			cpu_to_le32((u32)(ctx->a_key_len /
1651adc3f65aSKai Ye 			SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET_V3);
1652adc3f65aSKai Ye 
1653adc3f65aSKai Ye 	sqe3->auth_mac_key |=
1654adc3f65aSKai Ye 			cpu_to_le32((u32)(ctx->a_alg) << SEC_AUTH_ALG_OFFSET_V3);
1655adc3f65aSKai Ye 
1656adc3f65aSKai Ye 	if (dir) {
1657adc3f65aSKai Ye 		sqe3->auth_mac_key |= cpu_to_le32((u32)SEC_AUTH_TYPE1);
1658adc3f65aSKai Ye 		sqe3->huk_iv_seq &= SEC_CIPHER_AUTH_V3;
1659adc3f65aSKai Ye 	} else {
166060ef3ddeSKai Ye 		sqe3->auth_mac_key |= cpu_to_le32((u32)SEC_AUTH_TYPE2);
1661adc3f65aSKai Ye 		sqe3->huk_iv_seq |= SEC_AUTH_CIPHER_V3;
1662adc3f65aSKai Ye 	}
1663adc3f65aSKai Ye 	sqe3->a_len_key = cpu_to_le32(c_req->c_len + aq->assoclen);
1664adc3f65aSKai Ye 
1665adc3f65aSKai Ye 	sqe3->cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
1666adc3f65aSKai Ye 
1667adc3f65aSKai Ye 	sqe3->mac_addr = cpu_to_le64(a_req->out_mac_dma);
1668adc3f65aSKai Ye }
1669adc3f65aSKai Ye 
1670adc3f65aSKai Ye static int sec_aead_bd_fill_v3(struct sec_ctx *ctx, struct sec_req *req)
1671adc3f65aSKai Ye {
1672adc3f65aSKai Ye 	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
1673adc3f65aSKai Ye 	struct sec_sqe3 *sec_sqe3 = &req->sec_sqe3;
1674adc3f65aSKai Ye 	int ret;
1675adc3f65aSKai Ye 
1676adc3f65aSKai Ye 	ret = sec_skcipher_bd_fill_v3(ctx, req);
1677adc3f65aSKai Ye 	if (unlikely(ret)) {
1678adc3f65aSKai Ye 		dev_err(ctx->dev, "skcipher bd3 fill is error!\n");
1679adc3f65aSKai Ye 		return ret;
1680adc3f65aSKai Ye 	}
1681adc3f65aSKai Ye 
1682c16a70c1SKai Ye 	if (ctx->c_ctx.c_mode == SEC_CMODE_CCM ||
1683c16a70c1SKai Ye 	    ctx->c_ctx.c_mode == SEC_CMODE_GCM)
1684c16a70c1SKai Ye 		sec_auth_bd_fill_xcm_v3(auth_ctx, req->c_req.encrypt,
1685c16a70c1SKai Ye 					req, sec_sqe3);
1686c16a70c1SKai Ye 	else
1687c16a70c1SKai Ye 		sec_auth_bd_fill_ex_v3(auth_ctx, req->c_req.encrypt,
1688c16a70c1SKai Ye 				       req, sec_sqe3);
1689adc3f65aSKai Ye 
1690adc3f65aSKai Ye 	return 0;
1691adc3f65aSKai Ye }
1692adc3f65aSKai Ye 
16932f072d75SZaibo Xu static void sec_aead_callback(struct sec_ctx *c, struct sec_req *req, int err)
16942f072d75SZaibo Xu {
16952f072d75SZaibo Xu 	struct aead_request *a_req = req->aead_req.aead_req;
16962f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
16972514f559SLongfang Liu 	struct sec_aead_req *aead_req = &req->aead_req;
16982f072d75SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
16992f072d75SZaibo Xu 	size_t authsize = crypto_aead_authsize(tfm);
17002f072d75SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
17019597efc3SKai Ye 	struct aead_request *backlog_aead_req;
17029597efc3SKai Ye 	struct sec_req *backlog_req;
17032f072d75SZaibo Xu 	size_t sz;
17042f072d75SZaibo Xu 
17052f072d75SZaibo Xu 	if (!err && c->c_ctx.c_mode == SEC_CMODE_CBC && c_req->encrypt)
17062f072d75SZaibo Xu 		sec_update_iv(req, SEC_AEAD);
17072f072d75SZaibo Xu 
17082f072d75SZaibo Xu 	/* Copy output mac */
17092f072d75SZaibo Xu 	if (!err && c_req->encrypt) {
17102f072d75SZaibo Xu 		struct scatterlist *sgl = a_req->dst;
17112f072d75SZaibo Xu 
17122f072d75SZaibo Xu 		sz = sg_pcopy_from_buffer(sgl, sg_nents(sgl),
17132514f559SLongfang Liu 					  aead_req->out_mac,
17142f072d75SZaibo Xu 					  authsize, a_req->cryptlen +
17152f072d75SZaibo Xu 					  a_req->assoclen);
17162f072d75SZaibo Xu 		if (unlikely(sz != authsize)) {
1717a44dce50SLongfang Liu 			dev_err(c->dev, "copy out mac err!\n");
17182f072d75SZaibo Xu 			err = -EINVAL;
17192f072d75SZaibo Xu 		}
17202f072d75SZaibo Xu 	}
17212f072d75SZaibo Xu 
17222f072d75SZaibo Xu 	sec_free_req_id(req);
17232f072d75SZaibo Xu 
17249597efc3SKai Ye 	while (1) {
17259597efc3SKai Ye 		backlog_req = sec_back_req_clear(c, qp_ctx);
17269597efc3SKai Ye 		if (!backlog_req)
17279597efc3SKai Ye 			break;
17289597efc3SKai Ye 
17299597efc3SKai Ye 		backlog_aead_req = backlog_req->aead_req.aead_req;
17309597efc3SKai Ye 		backlog_aead_req->base.complete(&backlog_aead_req->base,
17319597efc3SKai Ye 						-EINPROGRESS);
17329597efc3SKai Ye 		atomic64_inc(&c->sec->debug.dfx.recv_busy_cnt);
17339597efc3SKai Ye 	}
17342f072d75SZaibo Xu 
17352f072d75SZaibo Xu 	a_req->base.complete(&a_req->base, err);
17362f072d75SZaibo Xu }
17372f072d75SZaibo Xu 
1738416d8220SZaibo Xu static void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req)
1739416d8220SZaibo Xu {
1740416d8220SZaibo Xu 	sec_free_req_id(req);
1741a181647cSZaibo Xu 	sec_free_queue_id(ctx, req);
1742416d8220SZaibo Xu }
1743416d8220SZaibo Xu 
1744416d8220SZaibo Xu static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
1745416d8220SZaibo Xu {
1746416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
17477c7d902aSZaibo Xu 	int queue_id;
1748416d8220SZaibo Xu 
1749416d8220SZaibo Xu 	/* To load balance */
1750a181647cSZaibo Xu 	queue_id = sec_alloc_queue_id(ctx, req);
1751a181647cSZaibo Xu 	qp_ctx = &ctx->qp_ctx[queue_id];
1752416d8220SZaibo Xu 
1753416d8220SZaibo Xu 	req->req_id = sec_alloc_req_id(req, qp_ctx);
1754b9c8d897SZaibo Xu 	if (unlikely(req->req_id < 0)) {
1755a181647cSZaibo Xu 		sec_free_queue_id(ctx, req);
1756416d8220SZaibo Xu 		return req->req_id;
1757416d8220SZaibo Xu 	}
1758416d8220SZaibo Xu 
17597c7d902aSZaibo Xu 	return 0;
1760416d8220SZaibo Xu }
1761416d8220SZaibo Xu 
1762416d8220SZaibo Xu static int sec_process(struct sec_ctx *ctx, struct sec_req *req)
1763416d8220SZaibo Xu {
17642514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
1765416d8220SZaibo Xu 	int ret;
1766416d8220SZaibo Xu 
1767416d8220SZaibo Xu 	ret = sec_request_init(ctx, req);
1768b9c8d897SZaibo Xu 	if (unlikely(ret))
1769416d8220SZaibo Xu 		return ret;
1770416d8220SZaibo Xu 
1771416d8220SZaibo Xu 	ret = sec_request_transfer(ctx, req);
1772b9c8d897SZaibo Xu 	if (unlikely(ret))
1773416d8220SZaibo Xu 		goto err_uninit_req;
1774416d8220SZaibo Xu 
1775416d8220SZaibo Xu 	/* Output IV as decrypto */
17767b44c0eeSKai Ye 	if (!req->c_req.encrypt && (ctx->c_ctx.c_mode == SEC_CMODE_CBC ||
17777b44c0eeSKai Ye 	    ctx->c_ctx.c_mode == SEC_CMODE_CTR))
17782f072d75SZaibo Xu 		sec_update_iv(req, ctx->alg_type);
1779416d8220SZaibo Xu 
1780416d8220SZaibo Xu 	ret = ctx->req_op->bd_send(ctx, req);
17819597efc3SKai Ye 	if (unlikely((ret != -EBUSY && ret != -EINPROGRESS) ||
17829597efc3SKai Ye 		(ret == -EBUSY && !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
1783a44dce50SLongfang Liu 		dev_err_ratelimited(ctx->dev, "send sec request failed!\n");
1784416d8220SZaibo Xu 		goto err_send_req;
1785416d8220SZaibo Xu 	}
1786416d8220SZaibo Xu 
1787416d8220SZaibo Xu 	return ret;
1788416d8220SZaibo Xu 
1789416d8220SZaibo Xu err_send_req:
1790416d8220SZaibo Xu 	/* As failing, restore the IV from user */
17912f072d75SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) {
17922f072d75SZaibo Xu 		if (ctx->alg_type == SEC_SKCIPHER)
17932514f559SLongfang Liu 			memcpy(req->c_req.sk_req->iv, c_req->c_ivin,
1794416d8220SZaibo Xu 			       ctx->c_ctx.ivsize);
17952f072d75SZaibo Xu 		else
17962514f559SLongfang Liu 			memcpy(req->aead_req.aead_req->iv, c_req->c_ivin,
17972f072d75SZaibo Xu 			       ctx->c_ctx.ivsize);
17982f072d75SZaibo Xu 	}
1799416d8220SZaibo Xu 
1800416d8220SZaibo Xu 	sec_request_untransfer(ctx, req);
1801416d8220SZaibo Xu err_uninit_req:
1802416d8220SZaibo Xu 	sec_request_uninit(ctx, req);
1803416d8220SZaibo Xu 	return ret;
1804416d8220SZaibo Xu }
1805416d8220SZaibo Xu 
1806a181647cSZaibo Xu static const struct sec_req_op sec_skcipher_req_ops = {
1807416d8220SZaibo Xu 	.buf_map	= sec_skcipher_sgl_map,
1808416d8220SZaibo Xu 	.buf_unmap	= sec_skcipher_sgl_unmap,
1809416d8220SZaibo Xu 	.do_transfer	= sec_skcipher_copy_iv,
1810416d8220SZaibo Xu 	.bd_fill	= sec_skcipher_bd_fill,
1811416d8220SZaibo Xu 	.bd_send	= sec_bd_send,
1812416d8220SZaibo Xu 	.callback	= sec_skcipher_callback,
1813416d8220SZaibo Xu 	.process	= sec_process,
1814416d8220SZaibo Xu };
1815416d8220SZaibo Xu 
18162f072d75SZaibo Xu static const struct sec_req_op sec_aead_req_ops = {
18172f072d75SZaibo Xu 	.buf_map	= sec_aead_sgl_map,
18182f072d75SZaibo Xu 	.buf_unmap	= sec_aead_sgl_unmap,
1819c16a70c1SKai Ye 	.do_transfer	= sec_aead_set_iv,
18202f072d75SZaibo Xu 	.bd_fill	= sec_aead_bd_fill,
18212f072d75SZaibo Xu 	.bd_send	= sec_bd_send,
18222f072d75SZaibo Xu 	.callback	= sec_aead_callback,
18232f072d75SZaibo Xu 	.process	= sec_process,
18242f072d75SZaibo Xu };
18252f072d75SZaibo Xu 
1826adc3f65aSKai Ye static const struct sec_req_op sec_skcipher_req_ops_v3 = {
1827adc3f65aSKai Ye 	.buf_map	= sec_skcipher_sgl_map,
1828adc3f65aSKai Ye 	.buf_unmap	= sec_skcipher_sgl_unmap,
1829adc3f65aSKai Ye 	.do_transfer	= sec_skcipher_copy_iv,
1830adc3f65aSKai Ye 	.bd_fill	= sec_skcipher_bd_fill_v3,
1831adc3f65aSKai Ye 	.bd_send	= sec_bd_send,
1832adc3f65aSKai Ye 	.callback	= sec_skcipher_callback,
1833adc3f65aSKai Ye 	.process	= sec_process,
1834adc3f65aSKai Ye };
1835adc3f65aSKai Ye 
1836adc3f65aSKai Ye static const struct sec_req_op sec_aead_req_ops_v3 = {
1837adc3f65aSKai Ye 	.buf_map	= sec_aead_sgl_map,
1838adc3f65aSKai Ye 	.buf_unmap	= sec_aead_sgl_unmap,
1839c16a70c1SKai Ye 	.do_transfer	= sec_aead_set_iv,
1840adc3f65aSKai Ye 	.bd_fill	= sec_aead_bd_fill_v3,
1841adc3f65aSKai Ye 	.bd_send	= sec_bd_send,
1842adc3f65aSKai Ye 	.callback	= sec_aead_callback,
1843adc3f65aSKai Ye 	.process	= sec_process,
1844adc3f65aSKai Ye };
1845adc3f65aSKai Ye 
1846416d8220SZaibo Xu static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
1847416d8220SZaibo Xu {
1848416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
1849adc3f65aSKai Ye 	int ret;
1850416d8220SZaibo Xu 
1851adc3f65aSKai Ye 	ret = sec_skcipher_init(tfm);
1852adc3f65aSKai Ye 	if (ret)
1853adc3f65aSKai Ye 		return ret;
1854adc3f65aSKai Ye 
1855adc3f65aSKai Ye 	if (ctx->sec->qm.ver < QM_HW_V3) {
1856adc3f65aSKai Ye 		ctx->type_supported = SEC_BD_TYPE2;
1857a181647cSZaibo Xu 		ctx->req_op = &sec_skcipher_req_ops;
1858adc3f65aSKai Ye 	} else {
1859adc3f65aSKai Ye 		ctx->type_supported = SEC_BD_TYPE3;
1860adc3f65aSKai Ye 		ctx->req_op = &sec_skcipher_req_ops_v3;
1861adc3f65aSKai Ye 	}
1862416d8220SZaibo Xu 
1863adc3f65aSKai Ye 	return ret;
1864416d8220SZaibo Xu }
1865416d8220SZaibo Xu 
1866416d8220SZaibo Xu static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm)
1867416d8220SZaibo Xu {
1868a181647cSZaibo Xu 	sec_skcipher_uninit(tfm);
1869416d8220SZaibo Xu }
1870416d8220SZaibo Xu 
18712f072d75SZaibo Xu static int sec_aead_init(struct crypto_aead *tfm)
18722f072d75SZaibo Xu {
18732f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
18742f072d75SZaibo Xu 	int ret;
18752f072d75SZaibo Xu 
18762f072d75SZaibo Xu 	crypto_aead_set_reqsize(tfm, sizeof(struct sec_req));
18772f072d75SZaibo Xu 	ctx->alg_type = SEC_AEAD;
18782f072d75SZaibo Xu 	ctx->c_ctx.ivsize = crypto_aead_ivsize(tfm);
1879c16a70c1SKai Ye 	if (ctx->c_ctx.ivsize < SEC_AIV_SIZE ||
1880c16a70c1SKai Ye 	    ctx->c_ctx.ivsize > SEC_IV_SIZE) {
1881c16a70c1SKai Ye 		pr_err("get error aead iv size!\n");
18822f072d75SZaibo Xu 		return -EINVAL;
18832f072d75SZaibo Xu 	}
18842f072d75SZaibo Xu 
18852f072d75SZaibo Xu 	ret = sec_ctx_base_init(ctx);
18862f072d75SZaibo Xu 	if (ret)
18872f072d75SZaibo Xu 		return ret;
1888adc3f65aSKai Ye 	if (ctx->sec->qm.ver < QM_HW_V3) {
1889adc3f65aSKai Ye 		ctx->type_supported = SEC_BD_TYPE2;
1890adc3f65aSKai Ye 		ctx->req_op = &sec_aead_req_ops;
1891adc3f65aSKai Ye 	} else {
1892adc3f65aSKai Ye 		ctx->type_supported = SEC_BD_TYPE3;
1893adc3f65aSKai Ye 		ctx->req_op = &sec_aead_req_ops_v3;
1894adc3f65aSKai Ye 	}
18952f072d75SZaibo Xu 
18962f072d75SZaibo Xu 	ret = sec_auth_init(ctx);
18972f072d75SZaibo Xu 	if (ret)
18982f072d75SZaibo Xu 		goto err_auth_init;
18992f072d75SZaibo Xu 
19002f072d75SZaibo Xu 	ret = sec_cipher_init(ctx);
19012f072d75SZaibo Xu 	if (ret)
19022f072d75SZaibo Xu 		goto err_cipher_init;
19032f072d75SZaibo Xu 
19042f072d75SZaibo Xu 	return ret;
19052f072d75SZaibo Xu 
19062f072d75SZaibo Xu err_cipher_init:
19072f072d75SZaibo Xu 	sec_auth_uninit(ctx);
19082f072d75SZaibo Xu err_auth_init:
19092f072d75SZaibo Xu 	sec_ctx_base_uninit(ctx);
19102f072d75SZaibo Xu 	return ret;
19112f072d75SZaibo Xu }
19122f072d75SZaibo Xu 
19132f072d75SZaibo Xu static void sec_aead_exit(struct crypto_aead *tfm)
19142f072d75SZaibo Xu {
19152f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
19162f072d75SZaibo Xu 
19172f072d75SZaibo Xu 	sec_cipher_uninit(ctx);
19182f072d75SZaibo Xu 	sec_auth_uninit(ctx);
19192f072d75SZaibo Xu 	sec_ctx_base_uninit(ctx);
19202f072d75SZaibo Xu }
19212f072d75SZaibo Xu 
19222f072d75SZaibo Xu static int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name)
19232f072d75SZaibo Xu {
19242f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
19252f072d75SZaibo Xu 	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
19262f072d75SZaibo Xu 	int ret;
19272f072d75SZaibo Xu 
19282f072d75SZaibo Xu 	ret = sec_aead_init(tfm);
19292f072d75SZaibo Xu 	if (ret) {
19302f072d75SZaibo Xu 		pr_err("hisi_sec2: aead init error!\n");
19312f072d75SZaibo Xu 		return ret;
19322f072d75SZaibo Xu 	}
19332f072d75SZaibo Xu 
19342f072d75SZaibo Xu 	auth_ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
19352f072d75SZaibo Xu 	if (IS_ERR(auth_ctx->hash_tfm)) {
1936a44dce50SLongfang Liu 		dev_err(ctx->dev, "aead alloc shash error!\n");
19372f072d75SZaibo Xu 		sec_aead_exit(tfm);
19382f072d75SZaibo Xu 		return PTR_ERR(auth_ctx->hash_tfm);
19392f072d75SZaibo Xu 	}
19402f072d75SZaibo Xu 
19412f072d75SZaibo Xu 	return 0;
19422f072d75SZaibo Xu }
19432f072d75SZaibo Xu 
19442f072d75SZaibo Xu static void sec_aead_ctx_exit(struct crypto_aead *tfm)
19452f072d75SZaibo Xu {
19462f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
19472f072d75SZaibo Xu 
19482f072d75SZaibo Xu 	crypto_free_shash(ctx->a_ctx.hash_tfm);
19492f072d75SZaibo Xu 	sec_aead_exit(tfm);
19502f072d75SZaibo Xu }
19512f072d75SZaibo Xu 
1952c16a70c1SKai Ye static int sec_aead_xcm_ctx_init(struct crypto_aead *tfm)
1953c16a70c1SKai Ye {
19546c46a329SKai Ye 	struct aead_alg *alg = crypto_aead_alg(tfm);
1955c16a70c1SKai Ye 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
19566c46a329SKai Ye 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
19576c46a329SKai Ye 	const char *aead_name = alg->base.cra_name;
1958c16a70c1SKai Ye 	int ret;
1959c16a70c1SKai Ye 
1960c16a70c1SKai Ye 	ret = sec_aead_init(tfm);
1961c16a70c1SKai Ye 	if (ret) {
1962c16a70c1SKai Ye 		dev_err(ctx->dev, "hisi_sec2: aead xcm init error!\n");
1963c16a70c1SKai Ye 		return ret;
1964c16a70c1SKai Ye 	}
1965c16a70c1SKai Ye 
19666c46a329SKai Ye 	a_ctx->fallback_aead_tfm = crypto_alloc_aead(aead_name, 0,
19676c46a329SKai Ye 						     CRYPTO_ALG_NEED_FALLBACK |
19686c46a329SKai Ye 						     CRYPTO_ALG_ASYNC);
19696c46a329SKai Ye 	if (IS_ERR(a_ctx->fallback_aead_tfm)) {
19706c46a329SKai Ye 		dev_err(ctx->dev, "aead driver alloc fallback tfm error!\n");
19716c46a329SKai Ye 		sec_aead_exit(tfm);
19726c46a329SKai Ye 		return PTR_ERR(a_ctx->fallback_aead_tfm);
19736c46a329SKai Ye 	}
19746c46a329SKai Ye 	a_ctx->fallback = false;
19756c46a329SKai Ye 
1976c16a70c1SKai Ye 	return 0;
1977c16a70c1SKai Ye }
1978c16a70c1SKai Ye 
1979c16a70c1SKai Ye static void sec_aead_xcm_ctx_exit(struct crypto_aead *tfm)
1980c16a70c1SKai Ye {
19816c46a329SKai Ye 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
19826c46a329SKai Ye 
19836c46a329SKai Ye 	crypto_free_aead(ctx->a_ctx.fallback_aead_tfm);
1984c16a70c1SKai Ye 	sec_aead_exit(tfm);
1985c16a70c1SKai Ye }
1986c16a70c1SKai Ye 
19872f072d75SZaibo Xu static int sec_aead_sha1_ctx_init(struct crypto_aead *tfm)
19882f072d75SZaibo Xu {
19892f072d75SZaibo Xu 	return sec_aead_ctx_init(tfm, "sha1");
19902f072d75SZaibo Xu }
19912f072d75SZaibo Xu 
19922f072d75SZaibo Xu static int sec_aead_sha256_ctx_init(struct crypto_aead *tfm)
19932f072d75SZaibo Xu {
19942f072d75SZaibo Xu 	return sec_aead_ctx_init(tfm, "sha256");
19952f072d75SZaibo Xu }
19962f072d75SZaibo Xu 
19972f072d75SZaibo Xu static int sec_aead_sha512_ctx_init(struct crypto_aead *tfm)
19982f072d75SZaibo Xu {
19992f072d75SZaibo Xu 	return sec_aead_ctx_init(tfm, "sha512");
20002f072d75SZaibo Xu }
20012f072d75SZaibo Xu 
2002059c5342SLongfang Liu static int sec_skcipher_cryptlen_ckeck(struct sec_ctx *ctx,
2003059c5342SLongfang Liu 	struct sec_req *sreq)
2004059c5342SLongfang Liu {
2005059c5342SLongfang Liu 	u32 cryptlen = sreq->c_req.sk_req->cryptlen;
2006059c5342SLongfang Liu 	struct device *dev = ctx->dev;
2007059c5342SLongfang Liu 	u8 c_mode = ctx->c_ctx.c_mode;
2008059c5342SLongfang Liu 	int ret = 0;
2009059c5342SLongfang Liu 
2010059c5342SLongfang Liu 	switch (c_mode) {
2011059c5342SLongfang Liu 	case SEC_CMODE_XTS:
2012059c5342SLongfang Liu 		if (unlikely(cryptlen < AES_BLOCK_SIZE)) {
2013059c5342SLongfang Liu 			dev_err(dev, "skcipher XTS mode input length error!\n");
2014059c5342SLongfang Liu 			ret = -EINVAL;
2015059c5342SLongfang Liu 		}
2016059c5342SLongfang Liu 		break;
2017059c5342SLongfang Liu 	case SEC_CMODE_ECB:
2018059c5342SLongfang Liu 	case SEC_CMODE_CBC:
2019059c5342SLongfang Liu 		if (unlikely(cryptlen & (AES_BLOCK_SIZE - 1))) {
2020059c5342SLongfang Liu 			dev_err(dev, "skcipher AES input length error!\n");
2021059c5342SLongfang Liu 			ret = -EINVAL;
2022059c5342SLongfang Liu 		}
2023059c5342SLongfang Liu 		break;
20247b44c0eeSKai Ye 	case SEC_CMODE_CFB:
20257b44c0eeSKai Ye 	case SEC_CMODE_OFB:
20267b44c0eeSKai Ye 	case SEC_CMODE_CTR:
20277b44c0eeSKai Ye 		if (unlikely(ctx->sec->qm.ver < QM_HW_V3)) {
20287b44c0eeSKai Ye 			dev_err(dev, "skcipher HW version error!\n");
20297b44c0eeSKai Ye 			ret = -EINVAL;
20307b44c0eeSKai Ye 		}
20317b44c0eeSKai Ye 		break;
2032059c5342SLongfang Liu 	default:
2033059c5342SLongfang Liu 		ret = -EINVAL;
2034059c5342SLongfang Liu 	}
2035059c5342SLongfang Liu 
2036059c5342SLongfang Liu 	return ret;
2037059c5342SLongfang Liu }
2038059c5342SLongfang Liu 
2039d6de2a59SZaibo Xu static int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
2040416d8220SZaibo Xu {
2041d6de2a59SZaibo Xu 	struct skcipher_request *sk_req = sreq->c_req.sk_req;
2042a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
2043d6de2a59SZaibo Xu 	u8 c_alg = ctx->c_ctx.c_alg;
2044416d8220SZaibo Xu 
20457b44c0eeSKai Ye 	if (unlikely(!sk_req->src || !sk_req->dst ||
20467b44c0eeSKai Ye 		     sk_req->cryptlen > MAX_INPUT_DATA_LEN)) {
2047416d8220SZaibo Xu 		dev_err(dev, "skcipher input param error!\n");
2048416d8220SZaibo Xu 		return -EINVAL;
2049416d8220SZaibo Xu 	}
2050d6de2a59SZaibo Xu 	sreq->c_req.c_len = sk_req->cryptlen;
205174b58db8SLongfang Liu 
205274b58db8SLongfang Liu 	if (ctx->pbuf_supported && sk_req->cryptlen <= SEC_PBUF_SZ)
205374b58db8SLongfang Liu 		sreq->use_pbuf = true;
205474b58db8SLongfang Liu 	else
205574b58db8SLongfang Liu 		sreq->use_pbuf = false;
205674b58db8SLongfang Liu 
2057416d8220SZaibo Xu 	if (c_alg == SEC_CALG_3DES) {
2058b9c8d897SZaibo Xu 		if (unlikely(sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1))) {
2059416d8220SZaibo Xu 			dev_err(dev, "skcipher 3des input length error!\n");
2060416d8220SZaibo Xu 			return -EINVAL;
2061416d8220SZaibo Xu 		}
2062416d8220SZaibo Xu 		return 0;
2063416d8220SZaibo Xu 	} else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) {
2064059c5342SLongfang Liu 		return sec_skcipher_cryptlen_ckeck(ctx, sreq);
2065416d8220SZaibo Xu 	}
2066059c5342SLongfang Liu 
2067416d8220SZaibo Xu 	dev_err(dev, "skcipher algorithm error!\n");
2068633e507fSLongfang Liu 
2069416d8220SZaibo Xu 	return -EINVAL;
2070416d8220SZaibo Xu }
2071416d8220SZaibo Xu 
20725652d55aSKai Ye static int sec_skcipher_soft_crypto(struct sec_ctx *ctx,
20735652d55aSKai Ye 				    struct skcipher_request *sreq, bool encrypt)
20745652d55aSKai Ye {
20755652d55aSKai Ye 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
2076e764d81dSKai Ye 	SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, c_ctx->fbtfm);
20775652d55aSKai Ye 	struct device *dev = ctx->dev;
20785652d55aSKai Ye 	int ret;
20795652d55aSKai Ye 
20805652d55aSKai Ye 	if (!c_ctx->fbtfm) {
2081e764d81dSKai Ye 		dev_err_ratelimited(dev, "the soft tfm isn't supported in the current system.\n");
20825652d55aSKai Ye 		return -EINVAL;
20835652d55aSKai Ye 	}
20845652d55aSKai Ye 
20855652d55aSKai Ye 	skcipher_request_set_sync_tfm(subreq, c_ctx->fbtfm);
20865652d55aSKai Ye 
20875652d55aSKai Ye 	/* software need sync mode to do crypto */
20885652d55aSKai Ye 	skcipher_request_set_callback(subreq, sreq->base.flags,
20895652d55aSKai Ye 				      NULL, NULL);
20905652d55aSKai Ye 	skcipher_request_set_crypt(subreq, sreq->src, sreq->dst,
20915652d55aSKai Ye 				   sreq->cryptlen, sreq->iv);
20925652d55aSKai Ye 	if (encrypt)
20935652d55aSKai Ye 		ret = crypto_skcipher_encrypt(subreq);
20945652d55aSKai Ye 	else
20955652d55aSKai Ye 		ret = crypto_skcipher_decrypt(subreq);
20965652d55aSKai Ye 
20975652d55aSKai Ye 	skcipher_request_zero(subreq);
20985652d55aSKai Ye 
20995652d55aSKai Ye 	return ret;
21005652d55aSKai Ye }
21015652d55aSKai Ye 
2102416d8220SZaibo Xu static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt)
2103416d8220SZaibo Xu {
2104416d8220SZaibo Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req);
2105416d8220SZaibo Xu 	struct sec_req *req = skcipher_request_ctx(sk_req);
2106416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
2107416d8220SZaibo Xu 	int ret;
2108416d8220SZaibo Xu 
21095652d55aSKai Ye 	if (!sk_req->cryptlen) {
21105652d55aSKai Ye 		if (ctx->c_ctx.c_mode == SEC_CMODE_XTS)
21115652d55aSKai Ye 			return -EINVAL;
2112416d8220SZaibo Xu 		return 0;
21135652d55aSKai Ye 	}
2114416d8220SZaibo Xu 
21159597efc3SKai Ye 	req->flag = sk_req->base.flags;
2116416d8220SZaibo Xu 	req->c_req.sk_req = sk_req;
2117416d8220SZaibo Xu 	req->c_req.encrypt = encrypt;
2118416d8220SZaibo Xu 	req->ctx = ctx;
2119416d8220SZaibo Xu 
2120d6de2a59SZaibo Xu 	ret = sec_skcipher_param_check(ctx, req);
2121d6de2a59SZaibo Xu 	if (unlikely(ret))
2122d6de2a59SZaibo Xu 		return -EINVAL;
2123d6de2a59SZaibo Xu 
21245652d55aSKai Ye 	if (unlikely(ctx->c_ctx.fallback))
21255652d55aSKai Ye 		return sec_skcipher_soft_crypto(ctx, sk_req, encrypt);
21265652d55aSKai Ye 
2127416d8220SZaibo Xu 	return ctx->req_op->process(ctx, req);
2128416d8220SZaibo Xu }
2129416d8220SZaibo Xu 
2130416d8220SZaibo Xu static int sec_skcipher_encrypt(struct skcipher_request *sk_req)
2131416d8220SZaibo Xu {
2132416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, true);
2133416d8220SZaibo Xu }
2134416d8220SZaibo Xu 
2135416d8220SZaibo Xu static int sec_skcipher_decrypt(struct skcipher_request *sk_req)
2136416d8220SZaibo Xu {
2137416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, false);
2138416d8220SZaibo Xu }
2139416d8220SZaibo Xu 
2140416d8220SZaibo Xu #define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \
2141416d8220SZaibo Xu 	sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\
2142416d8220SZaibo Xu {\
2143416d8220SZaibo Xu 	.base = {\
2144416d8220SZaibo Xu 		.cra_name = sec_cra_name,\
2145416d8220SZaibo Xu 		.cra_driver_name = "hisi_sec_"sec_cra_name,\
2146416d8220SZaibo Xu 		.cra_priority = SEC_PRIORITY,\
21475652d55aSKai Ye 		.cra_flags = CRYPTO_ALG_ASYNC |\
21485652d55aSKai Ye 		 CRYPTO_ALG_NEED_FALLBACK,\
2149416d8220SZaibo Xu 		.cra_blocksize = blk_size,\
2150416d8220SZaibo Xu 		.cra_ctxsize = sizeof(struct sec_ctx),\
2151416d8220SZaibo Xu 		.cra_module = THIS_MODULE,\
2152416d8220SZaibo Xu 	},\
2153416d8220SZaibo Xu 	.init = ctx_init,\
2154416d8220SZaibo Xu 	.exit = ctx_exit,\
2155416d8220SZaibo Xu 	.setkey = sec_set_key,\
2156416d8220SZaibo Xu 	.decrypt = sec_skcipher_decrypt,\
2157416d8220SZaibo Xu 	.encrypt = sec_skcipher_encrypt,\
2158416d8220SZaibo Xu 	.min_keysize = sec_min_key_size,\
2159416d8220SZaibo Xu 	.max_keysize = sec_max_key_size,\
2160416d8220SZaibo Xu 	.ivsize = iv_size,\
2161416d8220SZaibo Xu },
2162416d8220SZaibo Xu 
2163416d8220SZaibo Xu #define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \
2164416d8220SZaibo Xu 	max_key_size, blk_size, iv_size) \
2165416d8220SZaibo Xu 	SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \
2166416d8220SZaibo Xu 	sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size)
2167416d8220SZaibo Xu 
2168a181647cSZaibo Xu static struct skcipher_alg sec_skciphers[] = {
2169416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb,
2170416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
2171416d8220SZaibo Xu 			 AES_BLOCK_SIZE, 0)
2172416d8220SZaibo Xu 
2173416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc,
2174416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
2175416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
2176416d8220SZaibo Xu 
2177416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts,
2178416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE,
2179416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
2180416d8220SZaibo Xu 
2181416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb,
21826161f40cSKai Ye 			 SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE,
2183416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, 0)
2184416d8220SZaibo Xu 
2185416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc,
21866161f40cSKai Ye 			 SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE,
2187416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE)
2188416d8220SZaibo Xu 
2189416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,
2190416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE,
2191416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
2192416d8220SZaibo Xu 
2193416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc,
2194416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
2195416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
2196416d8220SZaibo Xu };
2197416d8220SZaibo Xu 
21987b44c0eeSKai Ye static struct skcipher_alg sec_skciphers_v3[] = {
21997b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("ofb(aes)", sec_setkey_aes_ofb,
22007b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
22017b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
22027b44c0eeSKai Ye 
22037b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("cfb(aes)", sec_setkey_aes_cfb,
22047b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
22057b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
22067b44c0eeSKai Ye 
22077b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("ctr(aes)", sec_setkey_aes_ctr,
22087b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
22097b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
22107b44c0eeSKai Ye 
22117b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("ofb(sm4)", sec_setkey_sm4_ofb,
22127b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
22137b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
22147b44c0eeSKai Ye 
22157b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("cfb(sm4)", sec_setkey_sm4_cfb,
22167b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
22177b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
22187b44c0eeSKai Ye 
22197b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("ctr(sm4)", sec_setkey_sm4_ctr,
22207b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
22217b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
22227b44c0eeSKai Ye };
22237b44c0eeSKai Ye 
2224c16a70c1SKai Ye static int aead_iv_demension_check(struct aead_request *aead_req)
2225c16a70c1SKai Ye {
2226c16a70c1SKai Ye 	u8 cl;
2227c16a70c1SKai Ye 
2228c16a70c1SKai Ye 	cl = aead_req->iv[0] + 1;
2229c16a70c1SKai Ye 	if (cl < IV_CL_MIN || cl > IV_CL_MAX)
2230c16a70c1SKai Ye 		return -EINVAL;
2231c16a70c1SKai Ye 
2232c16a70c1SKai Ye 	if (cl < IV_CL_MID && aead_req->cryptlen >> (BYTE_BITS * cl))
2233c16a70c1SKai Ye 		return -EOVERFLOW;
2234c16a70c1SKai Ye 
2235c16a70c1SKai Ye 	return 0;
2236c16a70c1SKai Ye }
2237c16a70c1SKai Ye 
2238c16a70c1SKai Ye static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq)
2239c16a70c1SKai Ye {
2240c16a70c1SKai Ye 	struct aead_request *req = sreq->aead_req.aead_req;
2241c16a70c1SKai Ye 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
2242c16a70c1SKai Ye 	size_t authsize = crypto_aead_authsize(tfm);
2243c16a70c1SKai Ye 	u8 c_mode = ctx->c_ctx.c_mode;
2244c16a70c1SKai Ye 	struct device *dev = ctx->dev;
2245c16a70c1SKai Ye 	int ret;
2246c16a70c1SKai Ye 
2247c16a70c1SKai Ye 	if (unlikely(req->cryptlen + req->assoclen > MAX_INPUT_DATA_LEN ||
2248c16a70c1SKai Ye 	    req->assoclen > SEC_MAX_AAD_LEN)) {
2249c16a70c1SKai Ye 		dev_err(dev, "aead input spec error!\n");
2250c16a70c1SKai Ye 		return -EINVAL;
2251c16a70c1SKai Ye 	}
2252c16a70c1SKai Ye 
2253c16a70c1SKai Ye 	if (unlikely((c_mode == SEC_CMODE_GCM && authsize < DES_BLOCK_SIZE) ||
2254c16a70c1SKai Ye 	   (c_mode == SEC_CMODE_CCM && (authsize < MIN_MAC_LEN ||
2255c16a70c1SKai Ye 		authsize & MAC_LEN_MASK)))) {
2256c16a70c1SKai Ye 		dev_err(dev, "aead input mac length error!\n");
2257c16a70c1SKai Ye 		return -EINVAL;
2258c16a70c1SKai Ye 	}
2259c16a70c1SKai Ye 
2260c16a70c1SKai Ye 	if (c_mode == SEC_CMODE_CCM) {
22615e340558SKai Ye 		if (unlikely(req->assoclen > SEC_MAX_CCM_AAD_LEN)) {
22625e340558SKai Ye 			dev_err_ratelimited(dev, "CCM input aad parameter is too long!\n");
22635e340558SKai Ye 			return -EINVAL;
22645e340558SKai Ye 		}
2265c16a70c1SKai Ye 		ret = aead_iv_demension_check(req);
2266c16a70c1SKai Ye 		if (ret) {
2267c16a70c1SKai Ye 			dev_err(dev, "aead input iv param error!\n");
2268c16a70c1SKai Ye 			return ret;
2269c16a70c1SKai Ye 		}
2270c16a70c1SKai Ye 	}
2271c16a70c1SKai Ye 
2272c16a70c1SKai Ye 	if (sreq->c_req.encrypt)
2273c16a70c1SKai Ye 		sreq->c_req.c_len = req->cryptlen;
2274c16a70c1SKai Ye 	else
2275c16a70c1SKai Ye 		sreq->c_req.c_len = req->cryptlen - authsize;
2276c16a70c1SKai Ye 	if (c_mode == SEC_CMODE_CBC) {
2277c16a70c1SKai Ye 		if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) {
2278c16a70c1SKai Ye 			dev_err(dev, "aead crypto length error!\n");
2279c16a70c1SKai Ye 			return -EINVAL;
2280c16a70c1SKai Ye 		}
2281c16a70c1SKai Ye 	}
2282c16a70c1SKai Ye 
2283c16a70c1SKai Ye 	return 0;
2284c16a70c1SKai Ye }
2285c16a70c1SKai Ye 
22862f072d75SZaibo Xu static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
22872f072d75SZaibo Xu {
22882f072d75SZaibo Xu 	struct aead_request *req = sreq->aead_req.aead_req;
22892f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
22902f072d75SZaibo Xu 	size_t authsize = crypto_aead_authsize(tfm);
2291a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
2292a44dce50SLongfang Liu 	u8 c_alg = ctx->c_ctx.c_alg;
22932f072d75SZaibo Xu 
2294c16a70c1SKai Ye 	if (unlikely(!req->src || !req->dst)) {
2295a44dce50SLongfang Liu 		dev_err(dev, "aead input param error!\n");
22962f072d75SZaibo Xu 		return -EINVAL;
22972f072d75SZaibo Xu 	}
22982f072d75SZaibo Xu 
2299c16a70c1SKai Ye 	if (ctx->sec->qm.ver == QM_HW_V2) {
2300c16a70c1SKai Ye 		if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt &&
2301c16a70c1SKai Ye 		    req->cryptlen <= authsize))) {
23026c46a329SKai Ye 			ctx->a_ctx.fallback = true;
2303c16a70c1SKai Ye 			return -EINVAL;
2304c16a70c1SKai Ye 		}
2305c16a70c1SKai Ye 	}
2306c16a70c1SKai Ye 
2307c16a70c1SKai Ye 	/* Support AES or SM4 */
2308c16a70c1SKai Ye 	if (unlikely(c_alg != SEC_CALG_AES && c_alg != SEC_CALG_SM4)) {
2309c16a70c1SKai Ye 		dev_err(dev, "aead crypto alg error!\n");
2310c16a70c1SKai Ye 		return -EINVAL;
2311c16a70c1SKai Ye 	}
2312c16a70c1SKai Ye 
2313c16a70c1SKai Ye 	if (unlikely(sec_aead_spec_check(ctx, sreq)))
2314c16a70c1SKai Ye 		return -EINVAL;
2315c16a70c1SKai Ye 
231674b58db8SLongfang Liu 	if (ctx->pbuf_supported && (req->cryptlen + req->assoclen) <=
231774b58db8SLongfang Liu 		SEC_PBUF_SZ)
231874b58db8SLongfang Liu 		sreq->use_pbuf = true;
231974b58db8SLongfang Liu 	else
232074b58db8SLongfang Liu 		sreq->use_pbuf = false;
232174b58db8SLongfang Liu 
23222f072d75SZaibo Xu 	return 0;
23232f072d75SZaibo Xu }
23242f072d75SZaibo Xu 
23256c46a329SKai Ye static int sec_aead_soft_crypto(struct sec_ctx *ctx,
23266c46a329SKai Ye 				struct aead_request *aead_req,
23276c46a329SKai Ye 				bool encrypt)
23286c46a329SKai Ye {
23296c46a329SKai Ye 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
23306c46a329SKai Ye 	struct device *dev = ctx->dev;
23310a2a464fSKai Ye 	struct aead_request *subreq;
23320a2a464fSKai Ye 	int ret;
23336c46a329SKai Ye 
23346c46a329SKai Ye 	/* Kunpeng920 aead mode not support input 0 size */
23356c46a329SKai Ye 	if (!a_ctx->fallback_aead_tfm) {
233684c2c729SColin Ian King 		dev_err(dev, "aead fallback tfm is NULL!\n");
23376c46a329SKai Ye 		return -EINVAL;
23386c46a329SKai Ye 	}
23396c46a329SKai Ye 
23400a2a464fSKai Ye 	subreq = aead_request_alloc(a_ctx->fallback_aead_tfm, GFP_KERNEL);
23410a2a464fSKai Ye 	if (!subreq)
23420a2a464fSKai Ye 		return -ENOMEM;
23430a2a464fSKai Ye 
23446c46a329SKai Ye 	aead_request_set_tfm(subreq, a_ctx->fallback_aead_tfm);
23456c46a329SKai Ye 	aead_request_set_callback(subreq, aead_req->base.flags,
23466c46a329SKai Ye 				  aead_req->base.complete, aead_req->base.data);
23476c46a329SKai Ye 	aead_request_set_crypt(subreq, aead_req->src, aead_req->dst,
23486c46a329SKai Ye 			       aead_req->cryptlen, aead_req->iv);
23496c46a329SKai Ye 	aead_request_set_ad(subreq, aead_req->assoclen);
23506c46a329SKai Ye 
23510a2a464fSKai Ye 	if (encrypt)
23520a2a464fSKai Ye 		ret = crypto_aead_encrypt(subreq);
23530a2a464fSKai Ye 	else
23540a2a464fSKai Ye 		ret = crypto_aead_decrypt(subreq);
23550a2a464fSKai Ye 	aead_request_free(subreq);
23560a2a464fSKai Ye 
23570a2a464fSKai Ye 	return ret;
23586c46a329SKai Ye }
23596c46a329SKai Ye 
23602f072d75SZaibo Xu static int sec_aead_crypto(struct aead_request *a_req, bool encrypt)
23612f072d75SZaibo Xu {
23622f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
23632f072d75SZaibo Xu 	struct sec_req *req = aead_request_ctx(a_req);
23642f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
23652f072d75SZaibo Xu 	int ret;
23662f072d75SZaibo Xu 
23679597efc3SKai Ye 	req->flag = a_req->base.flags;
23682f072d75SZaibo Xu 	req->aead_req.aead_req = a_req;
23692f072d75SZaibo Xu 	req->c_req.encrypt = encrypt;
23702f072d75SZaibo Xu 	req->ctx = ctx;
23712f072d75SZaibo Xu 
23722f072d75SZaibo Xu 	ret = sec_aead_param_check(ctx, req);
23736c46a329SKai Ye 	if (unlikely(ret)) {
23746c46a329SKai Ye 		if (ctx->a_ctx.fallback)
23756c46a329SKai Ye 			return sec_aead_soft_crypto(ctx, a_req, encrypt);
23762f072d75SZaibo Xu 		return -EINVAL;
23776c46a329SKai Ye 	}
23782f072d75SZaibo Xu 
23792f072d75SZaibo Xu 	return ctx->req_op->process(ctx, req);
23802f072d75SZaibo Xu }
23812f072d75SZaibo Xu 
23822f072d75SZaibo Xu static int sec_aead_encrypt(struct aead_request *a_req)
23832f072d75SZaibo Xu {
23842f072d75SZaibo Xu 	return sec_aead_crypto(a_req, true);
23852f072d75SZaibo Xu }
23862f072d75SZaibo Xu 
23872f072d75SZaibo Xu static int sec_aead_decrypt(struct aead_request *a_req)
23882f072d75SZaibo Xu {
23892f072d75SZaibo Xu 	return sec_aead_crypto(a_req, false);
23902f072d75SZaibo Xu }
23912f072d75SZaibo Xu 
2392c16a70c1SKai Ye #define SEC_AEAD_ALG(sec_cra_name, sec_set_key, ctx_init,\
23932f072d75SZaibo Xu 			 ctx_exit, blk_size, iv_size, max_authsize)\
23942f072d75SZaibo Xu {\
23952f072d75SZaibo Xu 	.base = {\
23962f072d75SZaibo Xu 		.cra_name = sec_cra_name,\
23972f072d75SZaibo Xu 		.cra_driver_name = "hisi_sec_"sec_cra_name,\
23982f072d75SZaibo Xu 		.cra_priority = SEC_PRIORITY,\
23996c46a329SKai Ye 		.cra_flags = CRYPTO_ALG_ASYNC |\
24006c46a329SKai Ye 		 CRYPTO_ALG_NEED_FALLBACK,\
24012f072d75SZaibo Xu 		.cra_blocksize = blk_size,\
24022f072d75SZaibo Xu 		.cra_ctxsize = sizeof(struct sec_ctx),\
24032f072d75SZaibo Xu 		.cra_module = THIS_MODULE,\
24042f072d75SZaibo Xu 	},\
24052f072d75SZaibo Xu 	.init = ctx_init,\
24062f072d75SZaibo Xu 	.exit = ctx_exit,\
24072f072d75SZaibo Xu 	.setkey = sec_set_key,\
24086c46a329SKai Ye 	.setauthsize = sec_aead_setauthsize,\
24092f072d75SZaibo Xu 	.decrypt = sec_aead_decrypt,\
24102f072d75SZaibo Xu 	.encrypt = sec_aead_encrypt,\
24112f072d75SZaibo Xu 	.ivsize = iv_size,\
24122f072d75SZaibo Xu 	.maxauthsize = max_authsize,\
24132f072d75SZaibo Xu }
24142f072d75SZaibo Xu 
24152f072d75SZaibo Xu static struct aead_alg sec_aeads[] = {
24162f072d75SZaibo Xu 	SEC_AEAD_ALG("authenc(hmac(sha1),cbc(aes))",
24172f072d75SZaibo Xu 		     sec_setkey_aes_cbc_sha1, sec_aead_sha1_ctx_init,
2418c16a70c1SKai Ye 		     sec_aead_ctx_exit, AES_BLOCK_SIZE,
2419c16a70c1SKai Ye 		     AES_BLOCK_SIZE, SHA1_DIGEST_SIZE),
24202f072d75SZaibo Xu 
24212f072d75SZaibo Xu 	SEC_AEAD_ALG("authenc(hmac(sha256),cbc(aes))",
24222f072d75SZaibo Xu 		     sec_setkey_aes_cbc_sha256, sec_aead_sha256_ctx_init,
2423c16a70c1SKai Ye 		     sec_aead_ctx_exit, AES_BLOCK_SIZE,
2424c16a70c1SKai Ye 		     AES_BLOCK_SIZE, SHA256_DIGEST_SIZE),
24252f072d75SZaibo Xu 
24262f072d75SZaibo Xu 	SEC_AEAD_ALG("authenc(hmac(sha512),cbc(aes))",
24272f072d75SZaibo Xu 		     sec_setkey_aes_cbc_sha512, sec_aead_sha512_ctx_init,
2428c16a70c1SKai Ye 		     sec_aead_ctx_exit, AES_BLOCK_SIZE,
2429c16a70c1SKai Ye 		     AES_BLOCK_SIZE, SHA512_DIGEST_SIZE),
2430c16a70c1SKai Ye 
2431c16a70c1SKai Ye 	SEC_AEAD_ALG("ccm(aes)", sec_setkey_aes_ccm, sec_aead_xcm_ctx_init,
2432c16a70c1SKai Ye 		     sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ,
2433c16a70c1SKai Ye 		     AES_BLOCK_SIZE, AES_BLOCK_SIZE),
2434c16a70c1SKai Ye 
2435c16a70c1SKai Ye 	SEC_AEAD_ALG("gcm(aes)", sec_setkey_aes_gcm, sec_aead_xcm_ctx_init,
2436c16a70c1SKai Ye 		     sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ,
2437c16a70c1SKai Ye 		     SEC_AIV_SIZE, AES_BLOCK_SIZE)
2438c16a70c1SKai Ye };
2439c16a70c1SKai Ye 
2440c16a70c1SKai Ye static struct aead_alg sec_aeads_v3[] = {
2441c16a70c1SKai Ye 	SEC_AEAD_ALG("ccm(sm4)", sec_setkey_sm4_ccm, sec_aead_xcm_ctx_init,
2442c16a70c1SKai Ye 		     sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ,
2443c16a70c1SKai Ye 		     AES_BLOCK_SIZE, AES_BLOCK_SIZE),
2444c16a70c1SKai Ye 
2445c16a70c1SKai Ye 	SEC_AEAD_ALG("gcm(sm4)", sec_setkey_sm4_gcm, sec_aead_xcm_ctx_init,
2446c16a70c1SKai Ye 		     sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ,
2447c16a70c1SKai Ye 		     SEC_AIV_SIZE, AES_BLOCK_SIZE)
24482f072d75SZaibo Xu };
24492f072d75SZaibo Xu 
24508123455aSMeng Yu int sec_register_to_crypto(struct hisi_qm *qm)
2451416d8220SZaibo Xu {
24523d29e98dSYang Shen 	int ret;
2453416d8220SZaibo Xu 
2454416d8220SZaibo Xu 	/* To avoid repeat register */
2455a181647cSZaibo Xu 	ret = crypto_register_skciphers(sec_skciphers,
2456a181647cSZaibo Xu 					ARRAY_SIZE(sec_skciphers));
24572f072d75SZaibo Xu 	if (ret)
24582f072d75SZaibo Xu 		return ret;
24592f072d75SZaibo Xu 
24607b44c0eeSKai Ye 	if (qm->ver > QM_HW_V2) {
24617b44c0eeSKai Ye 		ret = crypto_register_skciphers(sec_skciphers_v3,
24627b44c0eeSKai Ye 						ARRAY_SIZE(sec_skciphers_v3));
24637b44c0eeSKai Ye 		if (ret)
24647b44c0eeSKai Ye 			goto reg_skcipher_fail;
24657b44c0eeSKai Ye 	}
2466c16a70c1SKai Ye 
24672f072d75SZaibo Xu 	ret = crypto_register_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
24682f072d75SZaibo Xu 	if (ret)
24697b44c0eeSKai Ye 		goto reg_aead_fail;
2470c16a70c1SKai Ye 	if (qm->ver > QM_HW_V2) {
2471c16a70c1SKai Ye 		ret = crypto_register_aeads(sec_aeads_v3, ARRAY_SIZE(sec_aeads_v3));
2472c16a70c1SKai Ye 		if (ret)
2473c16a70c1SKai Ye 			goto reg_aead_v3_fail;
2474c16a70c1SKai Ye 	}
24757b44c0eeSKai Ye 	return ret;
24767b44c0eeSKai Ye 
2477c16a70c1SKai Ye reg_aead_v3_fail:
2478c16a70c1SKai Ye 	crypto_unregister_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
24797b44c0eeSKai Ye reg_aead_fail:
24807b44c0eeSKai Ye 	if (qm->ver > QM_HW_V2)
24817b44c0eeSKai Ye 		crypto_unregister_skciphers(sec_skciphers_v3,
24827b44c0eeSKai Ye 					    ARRAY_SIZE(sec_skciphers_v3));
24837b44c0eeSKai Ye reg_skcipher_fail:
24843d29e98dSYang Shen 	crypto_unregister_skciphers(sec_skciphers,
24853d29e98dSYang Shen 				    ARRAY_SIZE(sec_skciphers));
2486416d8220SZaibo Xu 	return ret;
2487416d8220SZaibo Xu }
2488416d8220SZaibo Xu 
24898123455aSMeng Yu void sec_unregister_from_crypto(struct hisi_qm *qm)
2490416d8220SZaibo Xu {
24917b44c0eeSKai Ye 	if (qm->ver > QM_HW_V2)
2492c16a70c1SKai Ye 		crypto_unregister_aeads(sec_aeads_v3,
2493c16a70c1SKai Ye 					ARRAY_SIZE(sec_aeads_v3));
2494c16a70c1SKai Ye 	crypto_unregister_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
2495c16a70c1SKai Ye 
2496c16a70c1SKai Ye 	if (qm->ver > QM_HW_V2)
24977b44c0eeSKai Ye 		crypto_unregister_skciphers(sec_skciphers_v3,
24987b44c0eeSKai Ye 					    ARRAY_SIZE(sec_skciphers_v3));
2499a181647cSZaibo Xu 	crypto_unregister_skciphers(sec_skciphers,
2500a181647cSZaibo Xu 				    ARRAY_SIZE(sec_skciphers));
25012f072d75SZaibo Xu }
2502