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 
62416d8220SZaibo Xu #define SEC_TOTAL_IV_SZ		(SEC_IV_SIZE * QM_Q_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
692f072d75SZaibo Xu #define SEC_TOTAL_MAC_SZ	(SEC_MAX_MAC_LEN * QM_Q_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)
7774b58db8SLongfang Liu #define SEC_PBUF_PAGE_NUM	(QM_Q_DEPTH / SEC_PBUF_NUM)
7874b58db8SLongfang Liu #define SEC_PBUF_LEFT_SZ	(SEC_PBUF_PKG * (QM_Q_DEPTH -	\
7974b58db8SLongfang Liu 			SEC_PBUF_PAGE_NUM * SEC_PBUF_NUM))
8074b58db8SLongfang Liu #define SEC_TOTAL_PBUF_SZ	(PAGE_SIZE * SEC_PBUF_PAGE_NUM +	\
8174b58db8SLongfang Liu 			SEC_PBUF_LEFT_SZ)
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 
130*02884a4fSZhengchao Shao 	spin_lock_bh(&qp_ctx->req_lock);
131416d8220SZaibo Xu 
132416d8220SZaibo Xu 	req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL,
133416d8220SZaibo Xu 				  0, QM_Q_DEPTH, GFP_ATOMIC);
134*02884a4fSZhengchao Shao 	spin_unlock_bh(&qp_ctx->req_lock);
135b9c8d897SZaibo Xu 	if (unlikely(req_id < 0)) {
136a44dce50SLongfang Liu 		dev_err(req->ctx->dev, "alloc req id fail!\n");
137416d8220SZaibo Xu 		return req_id;
138416d8220SZaibo Xu 	}
139416d8220SZaibo Xu 
140416d8220SZaibo Xu 	req->qp_ctx = qp_ctx;
141416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = req;
142633e507fSLongfang Liu 
143416d8220SZaibo Xu 	return req_id;
144416d8220SZaibo Xu }
145416d8220SZaibo Xu 
146416d8220SZaibo Xu static void sec_free_req_id(struct sec_req *req)
147416d8220SZaibo Xu {
148416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
149416d8220SZaibo Xu 	int req_id = req->req_id;
150416d8220SZaibo Xu 
151b9c8d897SZaibo Xu 	if (unlikely(req_id < 0 || req_id >= QM_Q_DEPTH)) {
152a44dce50SLongfang Liu 		dev_err(req->ctx->dev, "free request id invalid!\n");
153416d8220SZaibo Xu 		return;
154416d8220SZaibo Xu 	}
155416d8220SZaibo Xu 
156416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = NULL;
157416d8220SZaibo Xu 	req->qp_ctx = NULL;
158416d8220SZaibo Xu 
159*02884a4fSZhengchao Shao 	spin_lock_bh(&qp_ctx->req_lock);
160416d8220SZaibo Xu 	idr_remove(&qp_ctx->req_idr, req_id);
161*02884a4fSZhengchao Shao 	spin_unlock_bh(&qp_ctx->req_lock);
162416d8220SZaibo Xu }
163416d8220SZaibo Xu 
164adc3f65aSKai Ye static u8 pre_parse_finished_bd(struct bd_status *status, void *resp)
165adc3f65aSKai Ye {
166adc3f65aSKai Ye 	struct sec_sqe *bd = resp;
167adc3f65aSKai Ye 
168adc3f65aSKai Ye 	status->done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK;
169668f1ab7SKai Ye 	status->icv = (le16_to_cpu(bd->type2.done_flag) & SEC_ICV_MASK) >> 1;
170adc3f65aSKai Ye 	status->flag = (le16_to_cpu(bd->type2.done_flag) &
171adc3f65aSKai Ye 					SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
172adc3f65aSKai Ye 	status->tag = le16_to_cpu(bd->type2.tag);
173adc3f65aSKai Ye 	status->err_type = bd->type2.error_type;
174adc3f65aSKai Ye 
175adc3f65aSKai Ye 	return bd->type_cipher_auth & SEC_TYPE_MASK;
176adc3f65aSKai Ye }
177adc3f65aSKai Ye 
178adc3f65aSKai Ye static u8 pre_parse_finished_bd3(struct bd_status *status, void *resp)
179adc3f65aSKai Ye {
180adc3f65aSKai Ye 	struct sec_sqe3 *bd3 = resp;
181adc3f65aSKai Ye 
182adc3f65aSKai Ye 	status->done = le16_to_cpu(bd3->done_flag) & SEC_DONE_MASK;
183668f1ab7SKai Ye 	status->icv = (le16_to_cpu(bd3->done_flag) & SEC_ICV_MASK) >> 1;
184adc3f65aSKai Ye 	status->flag = (le16_to_cpu(bd3->done_flag) &
185adc3f65aSKai Ye 					SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
186adc3f65aSKai Ye 	status->tag = le64_to_cpu(bd3->tag);
187adc3f65aSKai Ye 	status->err_type = bd3->error_type;
188adc3f65aSKai Ye 
189adc3f65aSKai Ye 	return le32_to_cpu(bd3->bd_param) & SEC_TYPE_MASK;
190adc3f65aSKai Ye }
191adc3f65aSKai Ye 
192adc3f65aSKai Ye static int sec_cb_status_check(struct sec_req *req,
193adc3f65aSKai Ye 			       struct bd_status *status)
194adc3f65aSKai Ye {
195adc3f65aSKai Ye 	struct sec_ctx *ctx = req->ctx;
196adc3f65aSKai Ye 
197adc3f65aSKai Ye 	if (unlikely(req->err_type || status->done != SEC_SQE_DONE)) {
198adc3f65aSKai Ye 		dev_err_ratelimited(ctx->dev, "err_type[%d], done[%u]\n",
199adc3f65aSKai Ye 				    req->err_type, status->done);
200adc3f65aSKai Ye 		return -EIO;
201adc3f65aSKai Ye 	}
202adc3f65aSKai Ye 
203adc3f65aSKai Ye 	if (unlikely(ctx->alg_type == SEC_SKCIPHER)) {
204adc3f65aSKai Ye 		if (unlikely(status->flag != SEC_SQE_CFLAG)) {
205adc3f65aSKai Ye 			dev_err_ratelimited(ctx->dev, "flag[%u]\n",
206adc3f65aSKai Ye 					    status->flag);
207adc3f65aSKai Ye 			return -EIO;
208adc3f65aSKai Ye 		}
209668f1ab7SKai Ye 	} else if (unlikely(ctx->alg_type == SEC_AEAD)) {
210668f1ab7SKai Ye 		if (unlikely(status->flag != SEC_SQE_AEAD_FLAG ||
211668f1ab7SKai Ye 			     status->icv == SEC_ICV_ERR)) {
212668f1ab7SKai Ye 			dev_err_ratelimited(ctx->dev,
213668f1ab7SKai Ye 					    "flag[%u], icv[%u]\n",
214668f1ab7SKai Ye 					    status->flag, status->icv);
215668f1ab7SKai Ye 			return -EBADMSG;
216668f1ab7SKai Ye 		}
217adc3f65aSKai Ye 	}
218adc3f65aSKai Ye 
219adc3f65aSKai Ye 	return 0;
220adc3f65aSKai Ye }
221adc3f65aSKai Ye 
222416d8220SZaibo Xu static void sec_req_cb(struct hisi_qp *qp, void *resp)
223416d8220SZaibo Xu {
224416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = qp->qp_ctx;
2258213a1a6SKai Ye 	struct sec_dfx *dfx = &qp_ctx->ctx->sec->debug.dfx;
226adc3f65aSKai Ye 	u8 type_supported = qp_ctx->ctx->type_supported;
227adc3f65aSKai Ye 	struct bd_status status;
228d6de2a59SZaibo Xu 	struct sec_ctx *ctx;
229d6de2a59SZaibo Xu 	struct sec_req *req;
230adc3f65aSKai Ye 	int err;
231416d8220SZaibo Xu 	u8 type;
232416d8220SZaibo Xu 
233adc3f65aSKai Ye 	if (type_supported == SEC_BD_TYPE2) {
234adc3f65aSKai Ye 		type = pre_parse_finished_bd(&status, resp);
235adc3f65aSKai Ye 		req = qp_ctx->req_list[status.tag];
236adc3f65aSKai Ye 	} else {
237adc3f65aSKai Ye 		type = pre_parse_finished_bd3(&status, resp);
238adc3f65aSKai Ye 		req = (void *)(uintptr_t)status.tag;
239adc3f65aSKai Ye 	}
240adc3f65aSKai Ye 
241adc3f65aSKai Ye 	if (unlikely(type != type_supported)) {
2428213a1a6SKai Ye 		atomic64_inc(&dfx->err_bd_cnt);
24349838259SKai Ye 		pr_err("err bd type [%u]\n", type);
244416d8220SZaibo Xu 		return;
245416d8220SZaibo Xu 	}
246416d8220SZaibo Xu 
2478213a1a6SKai Ye 	if (unlikely(!req)) {
2488213a1a6SKai Ye 		atomic64_inc(&dfx->invalid_req_cnt);
2499597efc3SKai Ye 		atomic_inc(&qp->qp_status.used);
2508213a1a6SKai Ye 		return;
2518213a1a6SKai Ye 	}
252adc3f65aSKai Ye 
253adc3f65aSKai Ye 	req->err_type = status.err_type;
254d6de2a59SZaibo Xu 	ctx = req->ctx;
255adc3f65aSKai Ye 	err = sec_cb_status_check(req, &status);
256adc3f65aSKai Ye 	if (err)
2578213a1a6SKai Ye 		atomic64_inc(&dfx->done_flag_cnt);
2581e9bc276SZaibo Xu 
2598213a1a6SKai Ye 	atomic64_inc(&dfx->recv_cnt);
260416d8220SZaibo Xu 
261d6de2a59SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
262d6de2a59SZaibo Xu 
263310ea0acSZaibo Xu 	ctx->req_op->callback(ctx, req, err);
264416d8220SZaibo Xu }
265416d8220SZaibo Xu 
266416d8220SZaibo Xu static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req)
267416d8220SZaibo Xu {
268416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
269416d8220SZaibo Xu 	int ret;
270416d8220SZaibo Xu 
2719597efc3SKai Ye 	if (ctx->fake_req_limit <=
2729597efc3SKai Ye 	    atomic_read(&qp_ctx->qp->qp_status.used) &&
2739597efc3SKai Ye 	    !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG))
2749597efc3SKai Ye 		return -EBUSY;
2759597efc3SKai Ye 
276*02884a4fSZhengchao Shao 	spin_lock_bh(&qp_ctx->req_lock);
277416d8220SZaibo Xu 	ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
2789597efc3SKai Ye 
2799597efc3SKai Ye 	if (ctx->fake_req_limit <=
2809597efc3SKai Ye 	    atomic_read(&qp_ctx->qp->qp_status.used) && !ret) {
2819597efc3SKai Ye 		list_add_tail(&req->backlog_head, &qp_ctx->backlog);
282cb1eeb75SArnd Bergmann 		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
2839597efc3SKai Ye 		atomic64_inc(&ctx->sec->debug.dfx.send_busy_cnt);
284*02884a4fSZhengchao Shao 		spin_unlock_bh(&qp_ctx->req_lock);
2859597efc3SKai Ye 		return -EBUSY;
2869597efc3SKai Ye 	}
287*02884a4fSZhengchao Shao 	spin_unlock_bh(&qp_ctx->req_lock);
288416d8220SZaibo Xu 
289b9c8d897SZaibo Xu 	if (unlikely(ret == -EBUSY))
290416d8220SZaibo Xu 		return -ENOBUFS;
291416d8220SZaibo Xu 
2929597efc3SKai Ye 	if (likely(!ret)) {
293416d8220SZaibo Xu 		ret = -EINPROGRESS;
2949597efc3SKai Ye 		atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
2958213a1a6SKai Ye 	}
296416d8220SZaibo Xu 
297416d8220SZaibo Xu 	return ret;
298416d8220SZaibo Xu }
299416d8220SZaibo Xu 
3007c7d902aSZaibo Xu /* Get DMA memory resources */
3017c7d902aSZaibo Xu static int sec_alloc_civ_resource(struct device *dev, struct sec_alg_res *res)
3027c7d902aSZaibo Xu {
3037c7d902aSZaibo Xu 	int i;
3047c7d902aSZaibo Xu 
3057c7d902aSZaibo Xu 	res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ,
3067c7d902aSZaibo Xu 					 &res->c_ivin_dma, GFP_KERNEL);
3077c7d902aSZaibo Xu 	if (!res->c_ivin)
3087c7d902aSZaibo Xu 		return -ENOMEM;
3097c7d902aSZaibo Xu 
3107c7d902aSZaibo Xu 	for (i = 1; i < QM_Q_DEPTH; i++) {
3117c7d902aSZaibo Xu 		res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE;
3127c7d902aSZaibo Xu 		res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE;
3137c7d902aSZaibo Xu 	}
3147c7d902aSZaibo Xu 
3157c7d902aSZaibo Xu 	return 0;
3167c7d902aSZaibo Xu }
3177c7d902aSZaibo Xu 
3187c7d902aSZaibo Xu static void sec_free_civ_resource(struct device *dev, struct sec_alg_res *res)
3197c7d902aSZaibo Xu {
3207c7d902aSZaibo Xu 	if (res->c_ivin)
3217c7d902aSZaibo Xu 		dma_free_coherent(dev, SEC_TOTAL_IV_SZ,
3227c7d902aSZaibo Xu 				  res->c_ivin, res->c_ivin_dma);
3237c7d902aSZaibo Xu }
3247c7d902aSZaibo Xu 
325c16a70c1SKai Ye static int sec_alloc_aiv_resource(struct device *dev, struct sec_alg_res *res)
326c16a70c1SKai Ye {
327c16a70c1SKai Ye 	int i;
328c16a70c1SKai Ye 
329c16a70c1SKai Ye 	res->a_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ,
330c16a70c1SKai Ye 					 &res->a_ivin_dma, GFP_KERNEL);
331c16a70c1SKai Ye 	if (!res->a_ivin)
332c16a70c1SKai Ye 		return -ENOMEM;
333c16a70c1SKai Ye 
334c16a70c1SKai Ye 	for (i = 1; i < QM_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)
345c16a70c1SKai Ye 		dma_free_coherent(dev, SEC_TOTAL_IV_SZ,
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 {
3512f072d75SZaibo Xu 	int i;
3522f072d75SZaibo Xu 
3532f072d75SZaibo Xu 	res->out_mac = dma_alloc_coherent(dev, SEC_TOTAL_MAC_SZ << 1,
3542f072d75SZaibo Xu 					  &res->out_mac_dma, GFP_KERNEL);
3552f072d75SZaibo Xu 	if (!res->out_mac)
3562f072d75SZaibo Xu 		return -ENOMEM;
3572f072d75SZaibo Xu 
3582f072d75SZaibo Xu 	for (i = 1; i < QM_Q_DEPTH; i++) {
3592f072d75SZaibo Xu 		res[i].out_mac_dma = res->out_mac_dma +
3602f072d75SZaibo Xu 				     i * (SEC_MAX_MAC_LEN << 1);
3612f072d75SZaibo Xu 		res[i].out_mac = res->out_mac + i * (SEC_MAX_MAC_LEN << 1);
3622f072d75SZaibo Xu 	}
3632f072d75SZaibo Xu 
3642f072d75SZaibo Xu 	return 0;
3652f072d75SZaibo Xu }
3662f072d75SZaibo Xu 
3672f072d75SZaibo Xu static void sec_free_mac_resource(struct device *dev, struct sec_alg_res *res)
3682f072d75SZaibo Xu {
3692f072d75SZaibo Xu 	if (res->out_mac)
3702f072d75SZaibo Xu 		dma_free_coherent(dev, SEC_TOTAL_MAC_SZ << 1,
3712f072d75SZaibo Xu 				  res->out_mac, res->out_mac_dma);
3722f072d75SZaibo Xu }
3732f072d75SZaibo Xu 
37474b58db8SLongfang Liu static void sec_free_pbuf_resource(struct device *dev, struct sec_alg_res *res)
37574b58db8SLongfang Liu {
37674b58db8SLongfang Liu 	if (res->pbuf)
37774b58db8SLongfang Liu 		dma_free_coherent(dev, SEC_TOTAL_PBUF_SZ,
37874b58db8SLongfang Liu 				  res->pbuf, res->pbuf_dma);
37974b58db8SLongfang Liu }
38074b58db8SLongfang Liu 
38174b58db8SLongfang Liu /*
38274b58db8SLongfang Liu  * To improve performance, pbuffer is used for
38374b58db8SLongfang Liu  * small packets (< 512Bytes) as IOMMU translation using.
38474b58db8SLongfang Liu  */
38574b58db8SLongfang Liu static int sec_alloc_pbuf_resource(struct device *dev, struct sec_alg_res *res)
38674b58db8SLongfang Liu {
38774b58db8SLongfang Liu 	int pbuf_page_offset;
38874b58db8SLongfang Liu 	int i, j, k;
38974b58db8SLongfang Liu 
39074b58db8SLongfang Liu 	res->pbuf = dma_alloc_coherent(dev, SEC_TOTAL_PBUF_SZ,
39174b58db8SLongfang Liu 				&res->pbuf_dma, GFP_KERNEL);
39274b58db8SLongfang Liu 	if (!res->pbuf)
39374b58db8SLongfang Liu 		return -ENOMEM;
39474b58db8SLongfang Liu 
39574b58db8SLongfang Liu 	/*
39674b58db8SLongfang Liu 	 * SEC_PBUF_PKG contains data pbuf, iv and
39774b58db8SLongfang Liu 	 * out_mac : <SEC_PBUF|SEC_IV|SEC_MAC>
39874b58db8SLongfang Liu 	 * Every PAGE contains six SEC_PBUF_PKG
39974b58db8SLongfang Liu 	 * The sec_qp_ctx contains QM_Q_DEPTH numbers of SEC_PBUF_PKG
40074b58db8SLongfang Liu 	 * So we need SEC_PBUF_PAGE_NUM numbers of PAGE
40174b58db8SLongfang Liu 	 * for the SEC_TOTAL_PBUF_SZ
40274b58db8SLongfang Liu 	 */
40374b58db8SLongfang Liu 	for (i = 0; i <= SEC_PBUF_PAGE_NUM; i++) {
40474b58db8SLongfang Liu 		pbuf_page_offset = PAGE_SIZE * i;
40574b58db8SLongfang Liu 		for (j = 0; j < SEC_PBUF_NUM; j++) {
40674b58db8SLongfang Liu 			k = i * SEC_PBUF_NUM + j;
40774b58db8SLongfang Liu 			if (k == QM_Q_DEPTH)
40874b58db8SLongfang Liu 				break;
40974b58db8SLongfang Liu 			res[k].pbuf = res->pbuf +
41074b58db8SLongfang Liu 				j * SEC_PBUF_PKG + pbuf_page_offset;
41174b58db8SLongfang Liu 			res[k].pbuf_dma = res->pbuf_dma +
41274b58db8SLongfang Liu 				j * SEC_PBUF_PKG + pbuf_page_offset;
41374b58db8SLongfang Liu 		}
41474b58db8SLongfang Liu 	}
415633e507fSLongfang Liu 
41674b58db8SLongfang Liu 	return 0;
41774b58db8SLongfang Liu }
41874b58db8SLongfang Liu 
4197c7d902aSZaibo Xu static int sec_alg_resource_alloc(struct sec_ctx *ctx,
4207c7d902aSZaibo Xu 				  struct sec_qp_ctx *qp_ctx)
4217c7d902aSZaibo Xu {
4222f072d75SZaibo Xu 	struct sec_alg_res *res = qp_ctx->res;
423a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
4242f072d75SZaibo Xu 	int ret;
4257c7d902aSZaibo Xu 
4262f072d75SZaibo Xu 	ret = sec_alloc_civ_resource(dev, res);
4272f072d75SZaibo Xu 	if (ret)
4282f072d75SZaibo Xu 		return ret;
4292f072d75SZaibo Xu 
4302f072d75SZaibo Xu 	if (ctx->alg_type == SEC_AEAD) {
431c16a70c1SKai Ye 		ret = sec_alloc_aiv_resource(dev, res);
432c16a70c1SKai Ye 		if (ret)
433c16a70c1SKai Ye 			goto alloc_aiv_fail;
434c16a70c1SKai Ye 
4352f072d75SZaibo Xu 		ret = sec_alloc_mac_resource(dev, res);
4362f072d75SZaibo Xu 		if (ret)
437c16a70c1SKai Ye 			goto alloc_mac_fail;
4382f072d75SZaibo Xu 	}
43974b58db8SLongfang Liu 	if (ctx->pbuf_supported) {
44074b58db8SLongfang Liu 		ret = sec_alloc_pbuf_resource(dev, res);
44174b58db8SLongfang Liu 		if (ret) {
44274b58db8SLongfang Liu 			dev_err(dev, "fail to alloc pbuf dma resource!\n");
44324efcec2SLongfang Liu 			goto alloc_pbuf_fail;
44474b58db8SLongfang Liu 		}
44574b58db8SLongfang Liu 	}
4462f072d75SZaibo Xu 
4472f072d75SZaibo Xu 	return 0;
448633e507fSLongfang Liu 
44924efcec2SLongfang Liu alloc_pbuf_fail:
45024efcec2SLongfang Liu 	if (ctx->alg_type == SEC_AEAD)
45124efcec2SLongfang Liu 		sec_free_mac_resource(dev, qp_ctx->res);
452c16a70c1SKai Ye alloc_mac_fail:
453c16a70c1SKai Ye 	if (ctx->alg_type == SEC_AEAD)
454c16a70c1SKai Ye 		sec_free_aiv_resource(dev, res);
455c16a70c1SKai Ye alloc_aiv_fail:
4562f072d75SZaibo Xu 	sec_free_civ_resource(dev, res);
4572f072d75SZaibo Xu 	return ret;
4587c7d902aSZaibo Xu }
4597c7d902aSZaibo Xu 
4607c7d902aSZaibo Xu static void sec_alg_resource_free(struct sec_ctx *ctx,
4617c7d902aSZaibo Xu 				  struct sec_qp_ctx *qp_ctx)
4627c7d902aSZaibo Xu {
463a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
4647c7d902aSZaibo Xu 
4657c7d902aSZaibo Xu 	sec_free_civ_resource(dev, qp_ctx->res);
4662f072d75SZaibo Xu 
46774b58db8SLongfang Liu 	if (ctx->pbuf_supported)
46874b58db8SLongfang Liu 		sec_free_pbuf_resource(dev, qp_ctx->res);
4692f072d75SZaibo Xu 	if (ctx->alg_type == SEC_AEAD)
4702f072d75SZaibo Xu 		sec_free_mac_resource(dev, qp_ctx->res);
4717c7d902aSZaibo Xu }
4727c7d902aSZaibo Xu 
473416d8220SZaibo Xu static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx,
474416d8220SZaibo Xu 			     int qp_ctx_id, int alg_type)
475416d8220SZaibo Xu {
476a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
477416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
478416d8220SZaibo Xu 	struct hisi_qp *qp;
479416d8220SZaibo Xu 	int ret = -ENOMEM;
480416d8220SZaibo Xu 
481416d8220SZaibo Xu 	qp_ctx = &ctx->qp_ctx[qp_ctx_id];
4820b5e43bcSKai Ye 	qp = ctx->qps[qp_ctx_id];
483416d8220SZaibo Xu 	qp->req_type = 0;
484416d8220SZaibo Xu 	qp->qp_ctx = qp_ctx;
485416d8220SZaibo Xu 	qp_ctx->qp = qp;
486416d8220SZaibo Xu 	qp_ctx->ctx = ctx;
487416d8220SZaibo Xu 
488adc3f65aSKai Ye 	qp->req_cb = sec_req_cb;
489adc3f65aSKai Ye 
490*02884a4fSZhengchao Shao 	spin_lock_init(&qp_ctx->req_lock);
491416d8220SZaibo Xu 	idr_init(&qp_ctx->req_idr);
4929597efc3SKai Ye 	INIT_LIST_HEAD(&qp_ctx->backlog);
493416d8220SZaibo Xu 
494416d8220SZaibo Xu 	qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
495416d8220SZaibo Xu 						     SEC_SGL_SGE_NR);
4968a6b8f4dSDan Carpenter 	if (IS_ERR(qp_ctx->c_in_pool)) {
497416d8220SZaibo Xu 		dev_err(dev, "fail to create sgl pool for input!\n");
4987c7d902aSZaibo Xu 		goto err_destroy_idr;
499416d8220SZaibo Xu 	}
500416d8220SZaibo Xu 
501416d8220SZaibo Xu 	qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
502416d8220SZaibo Xu 						      SEC_SGL_SGE_NR);
5038a6b8f4dSDan Carpenter 	if (IS_ERR(qp_ctx->c_out_pool)) {
504416d8220SZaibo Xu 		dev_err(dev, "fail to create sgl pool for output!\n");
505416d8220SZaibo Xu 		goto err_free_c_in_pool;
506416d8220SZaibo Xu 	}
507416d8220SZaibo Xu 
5087c7d902aSZaibo Xu 	ret = sec_alg_resource_alloc(ctx, qp_ctx);
509416d8220SZaibo Xu 	if (ret)
510416d8220SZaibo Xu 		goto err_free_c_out_pool;
511416d8220SZaibo Xu 
512416d8220SZaibo Xu 	ret = hisi_qm_start_qp(qp, 0);
513416d8220SZaibo Xu 	if (ret < 0)
514416d8220SZaibo Xu 		goto err_queue_free;
515416d8220SZaibo Xu 
516416d8220SZaibo Xu 	return 0;
517416d8220SZaibo Xu 
518416d8220SZaibo Xu err_queue_free:
5197c7d902aSZaibo Xu 	sec_alg_resource_free(ctx, qp_ctx);
520416d8220SZaibo Xu err_free_c_out_pool:
521416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
522416d8220SZaibo Xu err_free_c_in_pool:
523416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
524416d8220SZaibo Xu err_destroy_idr:
525416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
526416d8220SZaibo Xu 	return ret;
527416d8220SZaibo Xu }
528416d8220SZaibo Xu 
529416d8220SZaibo Xu static void sec_release_qp_ctx(struct sec_ctx *ctx,
530416d8220SZaibo Xu 			       struct sec_qp_ctx *qp_ctx)
531416d8220SZaibo Xu {
532a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
533416d8220SZaibo Xu 
534416d8220SZaibo Xu 	hisi_qm_stop_qp(qp_ctx->qp);
5357c7d902aSZaibo Xu 	sec_alg_resource_free(ctx, qp_ctx);
536416d8220SZaibo Xu 
537416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
538416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
539416d8220SZaibo Xu 
540416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
541416d8220SZaibo Xu }
542416d8220SZaibo Xu 
543473a0f96SZaibo Xu static int sec_ctx_base_init(struct sec_ctx *ctx)
544416d8220SZaibo Xu {
545416d8220SZaibo Xu 	struct sec_dev *sec;
546416d8220SZaibo Xu 	int i, ret;
547416d8220SZaibo Xu 
5480b5e43bcSKai Ye 	ctx->qps = sec_create_qps();
5490b5e43bcSKai Ye 	if (!ctx->qps) {
5500b5e43bcSKai Ye 		pr_err("Can not create sec qps!\n");
551416d8220SZaibo Xu 		return -ENODEV;
552416d8220SZaibo Xu 	}
5530b5e43bcSKai Ye 
5540b5e43bcSKai Ye 	sec = container_of(ctx->qps[0]->qm, struct sec_dev, qm);
555416d8220SZaibo Xu 	ctx->sec = sec;
556a44dce50SLongfang Liu 	ctx->dev = &sec->qm.pdev->dev;
557a718cfceSZaibo Xu 	ctx->hlf_q_num = sec->ctx_q_num >> 1;
558416d8220SZaibo Xu 
55974b58db8SLongfang Liu 	ctx->pbuf_supported = ctx->sec->iommu_used;
56074b58db8SLongfang Liu 
561416d8220SZaibo Xu 	/* Half of queue depth is taken as fake requests limit in the queue. */
562a718cfceSZaibo Xu 	ctx->fake_req_limit = QM_Q_DEPTH >> 1;
563416d8220SZaibo Xu 	ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx),
564416d8220SZaibo Xu 			      GFP_KERNEL);
56524efcec2SLongfang Liu 	if (!ctx->qp_ctx) {
56624efcec2SLongfang Liu 		ret = -ENOMEM;
56724efcec2SLongfang Liu 		goto err_destroy_qps;
56824efcec2SLongfang Liu 	}
569416d8220SZaibo Xu 
570416d8220SZaibo Xu 	for (i = 0; i < sec->ctx_q_num; i++) {
571473a0f96SZaibo Xu 		ret = sec_create_qp_ctx(&sec->qm, ctx, i, 0);
572416d8220SZaibo Xu 		if (ret)
573416d8220SZaibo Xu 			goto err_sec_release_qp_ctx;
574416d8220SZaibo Xu 	}
575416d8220SZaibo Xu 
576416d8220SZaibo Xu 	return 0;
57724efcec2SLongfang Liu 
578416d8220SZaibo Xu err_sec_release_qp_ctx:
579416d8220SZaibo Xu 	for (i = i - 1; i >= 0; i--)
580416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
581416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
58224efcec2SLongfang Liu err_destroy_qps:
58324efcec2SLongfang Liu 	sec_destroy_qps(ctx->qps, sec->ctx_q_num);
584416d8220SZaibo Xu 	return ret;
585416d8220SZaibo Xu }
586416d8220SZaibo Xu 
587473a0f96SZaibo Xu static void sec_ctx_base_uninit(struct sec_ctx *ctx)
588416d8220SZaibo Xu {
589473a0f96SZaibo Xu 	int i;
590416d8220SZaibo Xu 
591416d8220SZaibo Xu 	for (i = 0; i < ctx->sec->ctx_q_num; i++)
592416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
593416d8220SZaibo Xu 
5940b5e43bcSKai Ye 	sec_destroy_qps(ctx->qps, ctx->sec->ctx_q_num);
595416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
596416d8220SZaibo Xu }
597416d8220SZaibo Xu 
598473a0f96SZaibo Xu static int sec_cipher_init(struct sec_ctx *ctx)
599473a0f96SZaibo Xu {
600473a0f96SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
601473a0f96SZaibo Xu 
602a44dce50SLongfang Liu 	c_ctx->c_key = dma_alloc_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
603473a0f96SZaibo Xu 					  &c_ctx->c_key_dma, GFP_KERNEL);
604473a0f96SZaibo Xu 	if (!c_ctx->c_key)
605473a0f96SZaibo Xu 		return -ENOMEM;
606473a0f96SZaibo Xu 
607473a0f96SZaibo Xu 	return 0;
608473a0f96SZaibo Xu }
609473a0f96SZaibo Xu 
610473a0f96SZaibo Xu static void sec_cipher_uninit(struct sec_ctx *ctx)
611473a0f96SZaibo Xu {
612473a0f96SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
613473a0f96SZaibo Xu 
614473a0f96SZaibo Xu 	memzero_explicit(c_ctx->c_key, SEC_MAX_KEY_SIZE);
615a44dce50SLongfang Liu 	dma_free_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
616473a0f96SZaibo Xu 			  c_ctx->c_key, c_ctx->c_key_dma);
617473a0f96SZaibo Xu }
618473a0f96SZaibo Xu 
6192f072d75SZaibo Xu static int sec_auth_init(struct sec_ctx *ctx)
6202f072d75SZaibo Xu {
6212f072d75SZaibo Xu 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
6222f072d75SZaibo Xu 
623a44dce50SLongfang Liu 	a_ctx->a_key = dma_alloc_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
6242f072d75SZaibo Xu 					  &a_ctx->a_key_dma, GFP_KERNEL);
6252f072d75SZaibo Xu 	if (!a_ctx->a_key)
6262f072d75SZaibo Xu 		return -ENOMEM;
6272f072d75SZaibo Xu 
6282f072d75SZaibo Xu 	return 0;
6292f072d75SZaibo Xu }
6302f072d75SZaibo Xu 
6312f072d75SZaibo Xu static void sec_auth_uninit(struct sec_ctx *ctx)
6322f072d75SZaibo Xu {
6332f072d75SZaibo Xu 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
6342f072d75SZaibo Xu 
6352f072d75SZaibo Xu 	memzero_explicit(a_ctx->a_key, SEC_MAX_KEY_SIZE);
636a44dce50SLongfang Liu 	dma_free_coherent(ctx->dev, SEC_MAX_KEY_SIZE,
6372f072d75SZaibo Xu 			  a_ctx->a_key, a_ctx->a_key_dma);
6382f072d75SZaibo Xu }
6392f072d75SZaibo Xu 
6405652d55aSKai Ye static int sec_skcipher_fbtfm_init(struct crypto_skcipher *tfm)
6415652d55aSKai Ye {
6425652d55aSKai Ye 	const char *alg = crypto_tfm_alg_name(&tfm->base);
6435652d55aSKai Ye 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
6445652d55aSKai Ye 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
6455652d55aSKai Ye 
6465652d55aSKai Ye 	c_ctx->fallback = false;
647e764d81dSKai Ye 
648e764d81dSKai Ye 	/* Currently, only XTS mode need fallback tfm when using 192bit key */
6495652d55aSKai Ye 	if (likely(strncmp(alg, "xts", SEC_XTS_NAME_SZ)))
6505652d55aSKai Ye 		return 0;
6515652d55aSKai Ye 
6525652d55aSKai Ye 	c_ctx->fbtfm = crypto_alloc_sync_skcipher(alg, 0,
6535652d55aSKai Ye 						  CRYPTO_ALG_NEED_FALLBACK);
6545652d55aSKai Ye 	if (IS_ERR(c_ctx->fbtfm)) {
655e764d81dSKai Ye 		pr_err("failed to alloc xts mode fallback tfm!\n");
6565652d55aSKai Ye 		return PTR_ERR(c_ctx->fbtfm);
6575652d55aSKai Ye 	}
6585652d55aSKai Ye 
6595652d55aSKai Ye 	return 0;
6605652d55aSKai Ye }
6615652d55aSKai Ye 
662473a0f96SZaibo Xu static int sec_skcipher_init(struct crypto_skcipher *tfm)
663473a0f96SZaibo Xu {
664473a0f96SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
665473a0f96SZaibo Xu 	int ret;
666473a0f96SZaibo Xu 
6672f072d75SZaibo Xu 	ctx->alg_type = SEC_SKCIPHER;
668473a0f96SZaibo Xu 	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req));
669473a0f96SZaibo Xu 	ctx->c_ctx.ivsize = crypto_skcipher_ivsize(tfm);
670473a0f96SZaibo Xu 	if (ctx->c_ctx.ivsize > SEC_IV_SIZE) {
6714b7aef02SLongfang Liu 		pr_err("get error skcipher iv size!\n");
672473a0f96SZaibo Xu 		return -EINVAL;
673473a0f96SZaibo Xu 	}
674473a0f96SZaibo Xu 
675473a0f96SZaibo Xu 	ret = sec_ctx_base_init(ctx);
676473a0f96SZaibo Xu 	if (ret)
677473a0f96SZaibo Xu 		return ret;
678473a0f96SZaibo Xu 
679473a0f96SZaibo Xu 	ret = sec_cipher_init(ctx);
680473a0f96SZaibo Xu 	if (ret)
681473a0f96SZaibo Xu 		goto err_cipher_init;
682473a0f96SZaibo Xu 
6835652d55aSKai Ye 	ret = sec_skcipher_fbtfm_init(tfm);
6845652d55aSKai Ye 	if (ret)
6855652d55aSKai Ye 		goto err_fbtfm_init;
6865652d55aSKai Ye 
687473a0f96SZaibo Xu 	return 0;
688633e507fSLongfang Liu 
6895652d55aSKai Ye err_fbtfm_init:
6905652d55aSKai Ye 	sec_cipher_uninit(ctx);
691473a0f96SZaibo Xu err_cipher_init:
692473a0f96SZaibo Xu 	sec_ctx_base_uninit(ctx);
693473a0f96SZaibo Xu 	return ret;
694473a0f96SZaibo Xu }
695473a0f96SZaibo Xu 
696473a0f96SZaibo Xu static void sec_skcipher_uninit(struct crypto_skcipher *tfm)
697473a0f96SZaibo Xu {
698473a0f96SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
699473a0f96SZaibo Xu 
7005652d55aSKai Ye 	if (ctx->c_ctx.fbtfm)
7015652d55aSKai Ye 		crypto_free_sync_skcipher(ctx->c_ctx.fbtfm);
7025652d55aSKai Ye 
703473a0f96SZaibo Xu 	sec_cipher_uninit(ctx);
704473a0f96SZaibo Xu 	sec_ctx_base_uninit(ctx);
705473a0f96SZaibo Xu }
706473a0f96SZaibo Xu 
707ae6ce7b1SKai Ye static int sec_skcipher_3des_setkey(struct crypto_skcipher *tfm, const u8 *key,
708416d8220SZaibo Xu 				    const u32 keylen,
709416d8220SZaibo Xu 				    const enum sec_cmode c_mode)
710416d8220SZaibo Xu {
711ae6ce7b1SKai Ye 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
712ae6ce7b1SKai Ye 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
713ae6ce7b1SKai Ye 	int ret;
714ae6ce7b1SKai Ye 
715ae6ce7b1SKai Ye 	ret = verify_skcipher_des3_key(tfm, key);
716ae6ce7b1SKai Ye 	if (ret)
717ae6ce7b1SKai Ye 		return ret;
718ae6ce7b1SKai Ye 
719416d8220SZaibo Xu 	switch (keylen) {
720416d8220SZaibo Xu 	case SEC_DES3_2KEY_SIZE:
721416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_2KEY;
722416d8220SZaibo Xu 		break;
723416d8220SZaibo Xu 	case SEC_DES3_3KEY_SIZE:
724416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_3KEY;
725416d8220SZaibo Xu 		break;
726416d8220SZaibo Xu 	default:
727416d8220SZaibo Xu 		return -EINVAL;
728416d8220SZaibo Xu 	}
729416d8220SZaibo Xu 
730416d8220SZaibo Xu 	return 0;
731416d8220SZaibo Xu }
732416d8220SZaibo Xu 
733416d8220SZaibo Xu static int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx,
734416d8220SZaibo Xu 				       const u32 keylen,
735416d8220SZaibo Xu 				       const enum sec_cmode c_mode)
736416d8220SZaibo Xu {
737416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
738416d8220SZaibo Xu 		switch (keylen) {
739416d8220SZaibo Xu 		case SEC_XTS_MIN_KEY_SIZE:
740416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_128BIT;
741416d8220SZaibo Xu 			break;
7425652d55aSKai Ye 		case SEC_XTS_MID_KEY_SIZE:
7435652d55aSKai Ye 			c_ctx->fallback = true;
7445652d55aSKai Ye 			break;
745416d8220SZaibo Xu 		case SEC_XTS_MAX_KEY_SIZE:
746416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_256BIT;
747416d8220SZaibo Xu 			break;
748416d8220SZaibo Xu 		default:
749416d8220SZaibo Xu 			pr_err("hisi_sec2: xts mode key error!\n");
750416d8220SZaibo Xu 			return -EINVAL;
751416d8220SZaibo Xu 		}
752416d8220SZaibo Xu 	} else {
753adc3f65aSKai Ye 		if (c_ctx->c_alg == SEC_CALG_SM4 &&
754adc3f65aSKai Ye 		    keylen != AES_KEYSIZE_128) {
755adc3f65aSKai Ye 			pr_err("hisi_sec2: sm4 key error!\n");
756adc3f65aSKai Ye 			return -EINVAL;
757adc3f65aSKai Ye 		} else {
758416d8220SZaibo Xu 			switch (keylen) {
759416d8220SZaibo Xu 			case AES_KEYSIZE_128:
760416d8220SZaibo Xu 				c_ctx->c_key_len = SEC_CKEY_128BIT;
761416d8220SZaibo Xu 				break;
762416d8220SZaibo Xu 			case AES_KEYSIZE_192:
763416d8220SZaibo Xu 				c_ctx->c_key_len = SEC_CKEY_192BIT;
764416d8220SZaibo Xu 				break;
765416d8220SZaibo Xu 			case AES_KEYSIZE_256:
766416d8220SZaibo Xu 				c_ctx->c_key_len = SEC_CKEY_256BIT;
767416d8220SZaibo Xu 				break;
768416d8220SZaibo Xu 			default:
769416d8220SZaibo Xu 				pr_err("hisi_sec2: aes key error!\n");
770416d8220SZaibo Xu 				return -EINVAL;
771416d8220SZaibo Xu 			}
772416d8220SZaibo Xu 		}
773adc3f65aSKai Ye 	}
774416d8220SZaibo Xu 
775416d8220SZaibo Xu 	return 0;
776416d8220SZaibo Xu }
777416d8220SZaibo Xu 
778416d8220SZaibo Xu static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
779416d8220SZaibo Xu 			       const u32 keylen, const enum sec_calg c_alg,
780416d8220SZaibo Xu 			       const enum sec_cmode c_mode)
781416d8220SZaibo Xu {
782416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
783416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
784a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
785416d8220SZaibo Xu 	int ret;
786416d8220SZaibo Xu 
787416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
788416d8220SZaibo Xu 		ret = xts_verify_key(tfm, key, keylen);
789416d8220SZaibo Xu 		if (ret) {
790a44dce50SLongfang Liu 			dev_err(dev, "xts mode key err!\n");
791416d8220SZaibo Xu 			return ret;
792416d8220SZaibo Xu 		}
793416d8220SZaibo Xu 	}
794416d8220SZaibo Xu 
795416d8220SZaibo Xu 	c_ctx->c_alg  = c_alg;
796416d8220SZaibo Xu 	c_ctx->c_mode = c_mode;
797416d8220SZaibo Xu 
798416d8220SZaibo Xu 	switch (c_alg) {
799416d8220SZaibo Xu 	case SEC_CALG_3DES:
800ae6ce7b1SKai Ye 		ret = sec_skcipher_3des_setkey(tfm, key, keylen, c_mode);
801416d8220SZaibo Xu 		break;
802416d8220SZaibo Xu 	case SEC_CALG_AES:
803416d8220SZaibo Xu 	case SEC_CALG_SM4:
804416d8220SZaibo Xu 		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
805416d8220SZaibo Xu 		break;
806416d8220SZaibo Xu 	default:
807416d8220SZaibo Xu 		return -EINVAL;
808416d8220SZaibo Xu 	}
809416d8220SZaibo Xu 
810416d8220SZaibo Xu 	if (ret) {
811a44dce50SLongfang Liu 		dev_err(dev, "set sec key err!\n");
812416d8220SZaibo Xu 		return ret;
813416d8220SZaibo Xu 	}
814416d8220SZaibo Xu 
815416d8220SZaibo Xu 	memcpy(c_ctx->c_key, key, keylen);
816e764d81dSKai Ye 	if (c_ctx->fallback && c_ctx->fbtfm) {
8175652d55aSKai Ye 		ret = crypto_sync_skcipher_setkey(c_ctx->fbtfm, key, keylen);
8185652d55aSKai Ye 		if (ret) {
8195652d55aSKai Ye 			dev_err(dev, "failed to set fallback skcipher key!\n");
8205652d55aSKai Ye 			return ret;
8215652d55aSKai Ye 		}
8225652d55aSKai Ye 	}
823416d8220SZaibo Xu 	return 0;
824416d8220SZaibo Xu }
825416d8220SZaibo Xu 
826416d8220SZaibo Xu #define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode)			\
827416d8220SZaibo Xu static int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\
828416d8220SZaibo Xu 	u32 keylen)							\
829416d8220SZaibo Xu {									\
830416d8220SZaibo Xu 	return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode);	\
831416d8220SZaibo Xu }
832416d8220SZaibo Xu 
833416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB)
834416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC)
835416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS)
8367b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(aes_ofb, SEC_CALG_AES, SEC_CMODE_OFB)
8377b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(aes_cfb, SEC_CALG_AES, SEC_CMODE_CFB)
8387b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(aes_ctr, SEC_CALG_AES, SEC_CMODE_CTR)
839416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB)
840416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC)
841416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS)
842416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC)
8437b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(sm4_ofb, SEC_CALG_SM4, SEC_CMODE_OFB)
8447b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(sm4_cfb, SEC_CALG_SM4, SEC_CMODE_CFB)
8457b44c0eeSKai Ye GEN_SEC_SETKEY_FUNC(sm4_ctr, SEC_CALG_SM4, SEC_CMODE_CTR)
846416d8220SZaibo Xu 
84774b58db8SLongfang Liu static int sec_cipher_pbuf_map(struct sec_ctx *ctx, struct sec_req *req,
84874b58db8SLongfang Liu 			struct scatterlist *src)
84974b58db8SLongfang Liu {
8506c46a329SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
8516c46a329SKai Ye 	struct aead_request *aead_req = a_req->aead_req;
85274b58db8SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
85374b58db8SLongfang Liu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
854a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
85574b58db8SLongfang Liu 	int copy_size, pbuf_length;
85674b58db8SLongfang Liu 	int req_id = req->req_id;
8576c46a329SKai Ye 	struct crypto_aead *tfm;
8586c46a329SKai Ye 	size_t authsize;
8596c46a329SKai Ye 	u8 *mac_offset;
86074b58db8SLongfang Liu 
86174b58db8SLongfang Liu 	if (ctx->alg_type == SEC_AEAD)
86274b58db8SLongfang Liu 		copy_size = aead_req->cryptlen + aead_req->assoclen;
86374b58db8SLongfang Liu 	else
86474b58db8SLongfang Liu 		copy_size = c_req->c_len;
86574b58db8SLongfang Liu 
86674b58db8SLongfang Liu 	pbuf_length = sg_copy_to_buffer(src, sg_nents(src),
8676c46a329SKai Ye 			qp_ctx->res[req_id].pbuf, copy_size);
86874b58db8SLongfang Liu 	if (unlikely(pbuf_length != copy_size)) {
86974b58db8SLongfang Liu 		dev_err(dev, "copy src data to pbuf error!\n");
87074b58db8SLongfang Liu 		return -EINVAL;
87174b58db8SLongfang Liu 	}
8726c46a329SKai Ye 	if (!c_req->encrypt && ctx->alg_type == SEC_AEAD) {
8736c46a329SKai Ye 		tfm = crypto_aead_reqtfm(aead_req);
8746c46a329SKai Ye 		authsize = crypto_aead_authsize(tfm);
8756c46a329SKai Ye 		mac_offset = qp_ctx->res[req_id].pbuf + copy_size - authsize;
8766c46a329SKai Ye 		memcpy(a_req->out_mac, mac_offset, authsize);
8776c46a329SKai Ye 	}
87874b58db8SLongfang Liu 
8799039878aSKai Ye 	req->in_dma = qp_ctx->res[req_id].pbuf_dma;
8809039878aSKai Ye 	c_req->c_out_dma = req->in_dma;
88174b58db8SLongfang Liu 
88274b58db8SLongfang Liu 	return 0;
88374b58db8SLongfang Liu }
88474b58db8SLongfang Liu 
88574b58db8SLongfang Liu static void sec_cipher_pbuf_unmap(struct sec_ctx *ctx, struct sec_req *req,
88674b58db8SLongfang Liu 			struct scatterlist *dst)
88774b58db8SLongfang Liu {
88874b58db8SLongfang Liu 	struct aead_request *aead_req = req->aead_req.aead_req;
88974b58db8SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
89074b58db8SLongfang Liu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
89174b58db8SLongfang Liu 	int copy_size, pbuf_length;
89274b58db8SLongfang Liu 	int req_id = req->req_id;
89374b58db8SLongfang Liu 
89474b58db8SLongfang Liu 	if (ctx->alg_type == SEC_AEAD)
89574b58db8SLongfang Liu 		copy_size = c_req->c_len + aead_req->assoclen;
89674b58db8SLongfang Liu 	else
89774b58db8SLongfang Liu 		copy_size = c_req->c_len;
89874b58db8SLongfang Liu 
89974b58db8SLongfang Liu 	pbuf_length = sg_copy_from_buffer(dst, sg_nents(dst),
900668f1ab7SKai Ye 			qp_ctx->res[req_id].pbuf, copy_size);
90174b58db8SLongfang Liu 	if (unlikely(pbuf_length != copy_size))
902668f1ab7SKai Ye 		dev_err(ctx->dev, "copy pbuf data to dst error!\n");
903668f1ab7SKai Ye }
904668f1ab7SKai Ye 
905668f1ab7SKai Ye static int sec_aead_mac_init(struct sec_aead_req *req)
906668f1ab7SKai Ye {
907668f1ab7SKai Ye 	struct aead_request *aead_req = req->aead_req;
908668f1ab7SKai Ye 	struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
909668f1ab7SKai Ye 	size_t authsize = crypto_aead_authsize(tfm);
910668f1ab7SKai Ye 	u8 *mac_out = req->out_mac;
911668f1ab7SKai Ye 	struct scatterlist *sgl = aead_req->src;
912668f1ab7SKai Ye 	size_t copy_size;
913668f1ab7SKai Ye 	off_t skip_size;
914668f1ab7SKai Ye 
915668f1ab7SKai Ye 	/* Copy input mac */
916668f1ab7SKai Ye 	skip_size = aead_req->assoclen + aead_req->cryptlen - authsize;
917668f1ab7SKai Ye 	copy_size = sg_pcopy_to_buffer(sgl, sg_nents(sgl), mac_out,
918668f1ab7SKai Ye 				       authsize, skip_size);
919668f1ab7SKai Ye 	if (unlikely(copy_size != authsize))
920668f1ab7SKai Ye 		return -EINVAL;
921668f1ab7SKai Ye 
922668f1ab7SKai Ye 	return 0;
92374b58db8SLongfang Liu }
92474b58db8SLongfang Liu 
9252514f559SLongfang Liu static int sec_cipher_map(struct sec_ctx *ctx, struct sec_req *req,
926416d8220SZaibo Xu 			  struct scatterlist *src, struct scatterlist *dst)
927416d8220SZaibo Xu {
928416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
9292514f559SLongfang Liu 	struct sec_aead_req *a_req = &req->aead_req;
930416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
9312514f559SLongfang Liu 	struct sec_alg_res *res = &qp_ctx->res[req->req_id];
932a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
93374b58db8SLongfang Liu 	int ret;
9342514f559SLongfang Liu 
93574b58db8SLongfang Liu 	if (req->use_pbuf) {
93674b58db8SLongfang Liu 		c_req->c_ivin = res->pbuf + SEC_PBUF_IV_OFFSET;
93774b58db8SLongfang Liu 		c_req->c_ivin_dma = res->pbuf_dma + SEC_PBUF_IV_OFFSET;
93874b58db8SLongfang Liu 		if (ctx->alg_type == SEC_AEAD) {
939c16a70c1SKai Ye 			a_req->a_ivin = res->a_ivin;
940c16a70c1SKai Ye 			a_req->a_ivin_dma = res->a_ivin_dma;
94174b58db8SLongfang Liu 			a_req->out_mac = res->pbuf + SEC_PBUF_MAC_OFFSET;
94274b58db8SLongfang Liu 			a_req->out_mac_dma = res->pbuf_dma +
94374b58db8SLongfang Liu 					SEC_PBUF_MAC_OFFSET;
94474b58db8SLongfang Liu 		}
945668f1ab7SKai Ye 		ret = sec_cipher_pbuf_map(ctx, req, src);
94674b58db8SLongfang Liu 
94774b58db8SLongfang Liu 		return ret;
94874b58db8SLongfang Liu 	}
9492514f559SLongfang Liu 	c_req->c_ivin = res->c_ivin;
9502514f559SLongfang Liu 	c_req->c_ivin_dma = res->c_ivin_dma;
9512514f559SLongfang Liu 	if (ctx->alg_type == SEC_AEAD) {
952c16a70c1SKai Ye 		a_req->a_ivin = res->a_ivin;
953c16a70c1SKai Ye 		a_req->a_ivin_dma = res->a_ivin_dma;
9542514f559SLongfang Liu 		a_req->out_mac = res->out_mac;
9552514f559SLongfang Liu 		a_req->out_mac_dma = res->out_mac_dma;
9562514f559SLongfang Liu 	}
957416d8220SZaibo Xu 
9589039878aSKai Ye 	req->in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src,
959416d8220SZaibo Xu 						qp_ctx->c_in_pool,
960416d8220SZaibo Xu 						req->req_id,
9619039878aSKai Ye 						&req->in_dma);
9629039878aSKai Ye 	if (IS_ERR(req->in)) {
963416d8220SZaibo Xu 		dev_err(dev, "fail to dma map input sgl buffers!\n");
9649039878aSKai Ye 		return PTR_ERR(req->in);
965416d8220SZaibo Xu 	}
966416d8220SZaibo Xu 
967668f1ab7SKai Ye 	if (!c_req->encrypt && ctx->alg_type == SEC_AEAD) {
968668f1ab7SKai Ye 		ret = sec_aead_mac_init(a_req);
969668f1ab7SKai Ye 		if (unlikely(ret)) {
970668f1ab7SKai Ye 			dev_err(dev, "fail to init mac data for ICV!\n");
971668f1ab7SKai Ye 			return ret;
972668f1ab7SKai Ye 		}
973668f1ab7SKai Ye 	}
9749039878aSKai Ye 
975416d8220SZaibo Xu 	if (dst == src) {
9769039878aSKai Ye 		c_req->c_out = req->in;
9779039878aSKai Ye 		c_req->c_out_dma = req->in_dma;
978416d8220SZaibo Xu 	} else {
979416d8220SZaibo Xu 		c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst,
980416d8220SZaibo Xu 							     qp_ctx->c_out_pool,
981416d8220SZaibo Xu 							     req->req_id,
982416d8220SZaibo Xu 							     &c_req->c_out_dma);
983416d8220SZaibo Xu 
984416d8220SZaibo Xu 		if (IS_ERR(c_req->c_out)) {
985416d8220SZaibo Xu 			dev_err(dev, "fail to dma map output sgl buffers!\n");
9869039878aSKai Ye 			hisi_acc_sg_buf_unmap(dev, src, req->in);
987416d8220SZaibo Xu 			return PTR_ERR(c_req->c_out);
988416d8220SZaibo Xu 		}
989416d8220SZaibo Xu 	}
990416d8220SZaibo Xu 
991416d8220SZaibo Xu 	return 0;
992416d8220SZaibo Xu }
993416d8220SZaibo Xu 
9942514f559SLongfang Liu static void sec_cipher_unmap(struct sec_ctx *ctx, struct sec_req *req,
995a181647cSZaibo Xu 			     struct scatterlist *src, struct scatterlist *dst)
996a181647cSZaibo Xu {
9972514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
998a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
999a181647cSZaibo Xu 
100074b58db8SLongfang Liu 	if (req->use_pbuf) {
100174b58db8SLongfang Liu 		sec_cipher_pbuf_unmap(ctx, req, dst);
100274b58db8SLongfang Liu 	} else {
10032514f559SLongfang Liu 		if (dst != src)
10049039878aSKai Ye 			hisi_acc_sg_buf_unmap(dev, src, req->in);
10052514f559SLongfang Liu 
10062514f559SLongfang Liu 		hisi_acc_sg_buf_unmap(dev, dst, c_req->c_out);
1007a181647cSZaibo Xu 	}
100874b58db8SLongfang Liu }
1009a181647cSZaibo Xu 
1010416d8220SZaibo Xu static int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
1011416d8220SZaibo Xu {
1012a181647cSZaibo Xu 	struct skcipher_request *sq = req->c_req.sk_req;
1013416d8220SZaibo Xu 
10142514f559SLongfang Liu 	return sec_cipher_map(ctx, req, sq->src, sq->dst);
1015416d8220SZaibo Xu }
1016416d8220SZaibo Xu 
1017416d8220SZaibo Xu static void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
1018416d8220SZaibo Xu {
10192514f559SLongfang Liu 	struct skcipher_request *sq = req->c_req.sk_req;
1020416d8220SZaibo Xu 
10212514f559SLongfang Liu 	sec_cipher_unmap(ctx, req, sq->src, sq->dst);
1022416d8220SZaibo Xu }
1023416d8220SZaibo Xu 
10242f072d75SZaibo Xu static int sec_aead_aes_set_key(struct sec_cipher_ctx *c_ctx,
10252f072d75SZaibo Xu 				struct crypto_authenc_keys *keys)
10262f072d75SZaibo Xu {
10272f072d75SZaibo Xu 	switch (keys->enckeylen) {
10282f072d75SZaibo Xu 	case AES_KEYSIZE_128:
10292f072d75SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_128BIT;
10302f072d75SZaibo Xu 		break;
10312f072d75SZaibo Xu 	case AES_KEYSIZE_192:
10322f072d75SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_192BIT;
10332f072d75SZaibo Xu 		break;
10342f072d75SZaibo Xu 	case AES_KEYSIZE_256:
10352f072d75SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_256BIT;
10362f072d75SZaibo Xu 		break;
10372f072d75SZaibo Xu 	default:
10382f072d75SZaibo Xu 		pr_err("hisi_sec2: aead aes key error!\n");
10392f072d75SZaibo Xu 		return -EINVAL;
10402f072d75SZaibo Xu 	}
10412f072d75SZaibo Xu 	memcpy(c_ctx->c_key, keys->enckey, keys->enckeylen);
10422f072d75SZaibo Xu 
10432f072d75SZaibo Xu 	return 0;
10442f072d75SZaibo Xu }
10452f072d75SZaibo Xu 
10462f072d75SZaibo Xu static int sec_aead_auth_set_key(struct sec_auth_ctx *ctx,
10472f072d75SZaibo Xu 				 struct crypto_authenc_keys *keys)
10482f072d75SZaibo Xu {
10492f072d75SZaibo Xu 	struct crypto_shash *hash_tfm = ctx->hash_tfm;
10505761498cSKai Ye 	int blocksize, digestsize, ret;
10512f072d75SZaibo Xu 
10522f072d75SZaibo Xu 	if (!keys->authkeylen) {
10532f072d75SZaibo Xu 		pr_err("hisi_sec2: aead auth key error!\n");
10542f072d75SZaibo Xu 		return -EINVAL;
10552f072d75SZaibo Xu 	}
10562f072d75SZaibo Xu 
10572f072d75SZaibo Xu 	blocksize = crypto_shash_blocksize(hash_tfm);
10585761498cSKai Ye 	digestsize = crypto_shash_digestsize(hash_tfm);
10592f072d75SZaibo Xu 	if (keys->authkeylen > blocksize) {
106061c38e3aSEric Biggers 		ret = crypto_shash_tfm_digest(hash_tfm, keys->authkey,
10612f072d75SZaibo Xu 					      keys->authkeylen, ctx->a_key);
10622f072d75SZaibo Xu 		if (ret) {
10632203d3f7SColin Ian King 			pr_err("hisi_sec2: aead auth digest error!\n");
10642f072d75SZaibo Xu 			return -EINVAL;
10652f072d75SZaibo Xu 		}
10665761498cSKai Ye 		ctx->a_key_len = digestsize;
10672f072d75SZaibo Xu 	} else {
10682f072d75SZaibo Xu 		memcpy(ctx->a_key, keys->authkey, keys->authkeylen);
10692f072d75SZaibo Xu 		ctx->a_key_len = keys->authkeylen;
10702f072d75SZaibo Xu 	}
10712f072d75SZaibo Xu 
10722f072d75SZaibo Xu 	return 0;
10732f072d75SZaibo Xu }
10742f072d75SZaibo Xu 
10756c46a329SKai Ye static int sec_aead_setauthsize(struct crypto_aead *aead, unsigned int authsize)
10766c46a329SKai Ye {
10776c46a329SKai Ye 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
10786c46a329SKai Ye 	struct sec_ctx *ctx = crypto_tfm_ctx(tfm);
10796c46a329SKai Ye 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
10806c46a329SKai Ye 
10816c46a329SKai Ye 	if (unlikely(a_ctx->fallback_aead_tfm))
10826c46a329SKai Ye 		return crypto_aead_setauthsize(a_ctx->fallback_aead_tfm, authsize);
10836c46a329SKai Ye 
10846c46a329SKai Ye 	return 0;
10856c46a329SKai Ye }
10866c46a329SKai Ye 
10876c46a329SKai Ye static int sec_aead_fallback_setkey(struct sec_auth_ctx *a_ctx,
10886c46a329SKai Ye 				    struct crypto_aead *tfm, const u8 *key,
10896c46a329SKai Ye 				    unsigned int keylen)
10906c46a329SKai Ye {
10916c46a329SKai Ye 	crypto_aead_clear_flags(a_ctx->fallback_aead_tfm, CRYPTO_TFM_REQ_MASK);
10926c46a329SKai Ye 	crypto_aead_set_flags(a_ctx->fallback_aead_tfm,
10936c46a329SKai Ye 			      crypto_aead_get_flags(tfm) & CRYPTO_TFM_REQ_MASK);
10946c46a329SKai Ye 	return crypto_aead_setkey(a_ctx->fallback_aead_tfm, key, keylen);
10956c46a329SKai Ye }
10966c46a329SKai Ye 
10972f072d75SZaibo Xu static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
10982f072d75SZaibo Xu 			   const u32 keylen, const enum sec_hash_alg a_alg,
10992f072d75SZaibo Xu 			   const enum sec_calg c_alg,
11002f072d75SZaibo Xu 			   const enum sec_mac_len mac_len,
11012f072d75SZaibo Xu 			   const enum sec_cmode c_mode)
11022f072d75SZaibo Xu {
11032f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
11042f072d75SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
11056c46a329SKai Ye 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
1106a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
11072f072d75SZaibo Xu 	struct crypto_authenc_keys keys;
11082f072d75SZaibo Xu 	int ret;
11092f072d75SZaibo Xu 
11102f072d75SZaibo Xu 	ctx->a_ctx.a_alg = a_alg;
11112f072d75SZaibo Xu 	ctx->c_ctx.c_alg = c_alg;
11122f072d75SZaibo Xu 	ctx->a_ctx.mac_len = mac_len;
11132f072d75SZaibo Xu 	c_ctx->c_mode = c_mode;
11142f072d75SZaibo Xu 
1115c16a70c1SKai Ye 	if (c_mode == SEC_CMODE_CCM || c_mode == SEC_CMODE_GCM) {
1116c16a70c1SKai Ye 		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
1117c16a70c1SKai Ye 		if (ret) {
1118c16a70c1SKai Ye 			dev_err(dev, "set sec aes ccm cipher key err!\n");
1119c16a70c1SKai Ye 			return ret;
1120c16a70c1SKai Ye 		}
1121c16a70c1SKai Ye 		memcpy(c_ctx->c_key, key, keylen);
1122c16a70c1SKai Ye 
11236c46a329SKai Ye 		if (unlikely(a_ctx->fallback_aead_tfm)) {
11246c46a329SKai Ye 			ret = sec_aead_fallback_setkey(a_ctx, tfm, key, keylen);
11256c46a329SKai Ye 			if (ret)
11266c46a329SKai Ye 				return ret;
11276c46a329SKai Ye 		}
11286c46a329SKai Ye 
1129c16a70c1SKai Ye 		return 0;
1130c16a70c1SKai Ye 	}
1131c16a70c1SKai Ye 
11322f072d75SZaibo Xu 	if (crypto_authenc_extractkeys(&keys, key, keylen))
11332f072d75SZaibo Xu 		goto bad_key;
11342f072d75SZaibo Xu 
11352f072d75SZaibo Xu 	ret = sec_aead_aes_set_key(c_ctx, &keys);
11362f072d75SZaibo Xu 	if (ret) {
1137a44dce50SLongfang Liu 		dev_err(dev, "set sec cipher key err!\n");
11382f072d75SZaibo Xu 		goto bad_key;
11392f072d75SZaibo Xu 	}
11402f072d75SZaibo Xu 
11412f072d75SZaibo Xu 	ret = sec_aead_auth_set_key(&ctx->a_ctx, &keys);
11422f072d75SZaibo Xu 	if (ret) {
1143a44dce50SLongfang Liu 		dev_err(dev, "set sec auth key err!\n");
11442f072d75SZaibo Xu 		goto bad_key;
11452f072d75SZaibo Xu 	}
11462f072d75SZaibo Xu 
1147adc3f65aSKai Ye 	if ((ctx->a_ctx.mac_len & SEC_SQE_LEN_RATE_MASK)  ||
1148adc3f65aSKai Ye 	    (ctx->a_ctx.a_key_len & SEC_SQE_LEN_RATE_MASK)) {
1149adc3f65aSKai Ye 		dev_err(dev, "MAC or AUTH key length error!\n");
1150adc3f65aSKai Ye 		goto bad_key;
1151adc3f65aSKai Ye 	}
1152adc3f65aSKai Ye 
11532f072d75SZaibo Xu 	return 0;
1154633e507fSLongfang Liu 
11552f072d75SZaibo Xu bad_key:
11562f072d75SZaibo Xu 	memzero_explicit(&keys, sizeof(struct crypto_authenc_keys));
11572f072d75SZaibo Xu 	return -EINVAL;
11582f072d75SZaibo Xu }
11592f072d75SZaibo Xu 
11602f072d75SZaibo Xu 
11612f072d75SZaibo Xu #define GEN_SEC_AEAD_SETKEY_FUNC(name, aalg, calg, maclen, cmode)	\
11622f072d75SZaibo Xu static int sec_setkey_##name(struct crypto_aead *tfm, const u8 *key,	\
11632f072d75SZaibo Xu 	u32 keylen)							\
11642f072d75SZaibo Xu {									\
11652f072d75SZaibo Xu 	return sec_aead_setkey(tfm, key, keylen, aalg, calg, maclen, cmode);\
11662f072d75SZaibo Xu }
11672f072d75SZaibo Xu 
11682f072d75SZaibo Xu GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha1, SEC_A_HMAC_SHA1,
11692f072d75SZaibo Xu 			 SEC_CALG_AES, SEC_HMAC_SHA1_MAC, SEC_CMODE_CBC)
11702f072d75SZaibo Xu GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha256, SEC_A_HMAC_SHA256,
11712f072d75SZaibo Xu 			 SEC_CALG_AES, SEC_HMAC_SHA256_MAC, SEC_CMODE_CBC)
11722f072d75SZaibo Xu GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha512, SEC_A_HMAC_SHA512,
11732f072d75SZaibo Xu 			 SEC_CALG_AES, SEC_HMAC_SHA512_MAC, SEC_CMODE_CBC)
1174c16a70c1SKai Ye GEN_SEC_AEAD_SETKEY_FUNC(aes_ccm, 0, SEC_CALG_AES,
1175c16a70c1SKai Ye 			 SEC_HMAC_CCM_MAC, SEC_CMODE_CCM)
1176c16a70c1SKai Ye GEN_SEC_AEAD_SETKEY_FUNC(aes_gcm, 0, SEC_CALG_AES,
1177c16a70c1SKai Ye 			 SEC_HMAC_GCM_MAC, SEC_CMODE_GCM)
1178c16a70c1SKai Ye GEN_SEC_AEAD_SETKEY_FUNC(sm4_ccm, 0, SEC_CALG_SM4,
1179c16a70c1SKai Ye 			 SEC_HMAC_CCM_MAC, SEC_CMODE_CCM)
1180c16a70c1SKai Ye GEN_SEC_AEAD_SETKEY_FUNC(sm4_gcm, 0, SEC_CALG_SM4,
1181c16a70c1SKai Ye 			 SEC_HMAC_GCM_MAC, SEC_CMODE_GCM)
11822f072d75SZaibo Xu 
11832f072d75SZaibo Xu static int sec_aead_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
11842f072d75SZaibo Xu {
11852f072d75SZaibo Xu 	struct aead_request *aq = req->aead_req.aead_req;
11862f072d75SZaibo Xu 
11872514f559SLongfang Liu 	return sec_cipher_map(ctx, req, aq->src, aq->dst);
11882f072d75SZaibo Xu }
11892f072d75SZaibo Xu 
11902f072d75SZaibo Xu static void sec_aead_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
11912f072d75SZaibo Xu {
11922f072d75SZaibo Xu 	struct aead_request *aq = req->aead_req.aead_req;
11932f072d75SZaibo Xu 
11942514f559SLongfang Liu 	sec_cipher_unmap(ctx, req, aq->src, aq->dst);
11952f072d75SZaibo Xu }
11962f072d75SZaibo Xu 
1197416d8220SZaibo Xu static int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req)
1198416d8220SZaibo Xu {
1199416d8220SZaibo Xu 	int ret;
1200416d8220SZaibo Xu 
1201416d8220SZaibo Xu 	ret = ctx->req_op->buf_map(ctx, req);
1202b9c8d897SZaibo Xu 	if (unlikely(ret))
1203416d8220SZaibo Xu 		return ret;
1204416d8220SZaibo Xu 
1205416d8220SZaibo Xu 	ctx->req_op->do_transfer(ctx, req);
1206416d8220SZaibo Xu 
1207416d8220SZaibo Xu 	ret = ctx->req_op->bd_fill(ctx, req);
1208b9c8d897SZaibo Xu 	if (unlikely(ret))
1209416d8220SZaibo Xu 		goto unmap_req_buf;
1210416d8220SZaibo Xu 
1211416d8220SZaibo Xu 	return ret;
1212416d8220SZaibo Xu 
1213416d8220SZaibo Xu unmap_req_buf:
1214416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
1215416d8220SZaibo Xu 	return ret;
1216416d8220SZaibo Xu }
1217416d8220SZaibo Xu 
1218416d8220SZaibo Xu static void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req)
1219416d8220SZaibo Xu {
1220416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
1221416d8220SZaibo Xu }
1222416d8220SZaibo Xu 
1223416d8220SZaibo Xu static void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
1224416d8220SZaibo Xu {
1225416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
12262514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
1227416d8220SZaibo Xu 
12282514f559SLongfang Liu 	memcpy(c_req->c_ivin, sk_req->iv, ctx->c_ctx.ivsize);
1229416d8220SZaibo Xu }
1230416d8220SZaibo Xu 
1231416d8220SZaibo Xu static int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
1232416d8220SZaibo Xu {
1233416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
1234416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
1235416d8220SZaibo Xu 	struct sec_sqe *sec_sqe = &req->sec_sqe;
1236416d8220SZaibo Xu 	u8 scene, sa_type, da_type;
1237416d8220SZaibo Xu 	u8 bd_type, cipher;
12387c7d902aSZaibo Xu 	u8 de = 0;
1239416d8220SZaibo Xu 
1240416d8220SZaibo Xu 	memset(sec_sqe, 0, sizeof(struct sec_sqe));
1241416d8220SZaibo Xu 
1242416d8220SZaibo Xu 	sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
12432514f559SLongfang Liu 	sec_sqe->type2.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
12449039878aSKai Ye 	sec_sqe->type2.data_src_addr = cpu_to_le64(req->in_dma);
1245416d8220SZaibo Xu 	sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma);
1246416d8220SZaibo Xu 
1247416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) <<
1248416d8220SZaibo Xu 						SEC_CMODE_OFFSET);
1249416d8220SZaibo Xu 	sec_sqe->type2.c_alg = c_ctx->c_alg;
1250416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
1251416d8220SZaibo Xu 						SEC_CKEY_OFFSET);
1252416d8220SZaibo Xu 
1253416d8220SZaibo Xu 	bd_type = SEC_BD_TYPE2;
1254416d8220SZaibo Xu 	if (c_req->encrypt)
1255416d8220SZaibo Xu 		cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET;
1256416d8220SZaibo Xu 	else
1257416d8220SZaibo Xu 		cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET;
1258416d8220SZaibo Xu 	sec_sqe->type_cipher_auth = bd_type | cipher;
1259416d8220SZaibo Xu 
1260adc3f65aSKai Ye 	/* Set destination and source address type */
1261adc3f65aSKai Ye 	if (req->use_pbuf) {
126274b58db8SLongfang Liu 		sa_type = SEC_PBUF << SEC_SRC_SGL_OFFSET;
1263adc3f65aSKai Ye 		da_type = SEC_PBUF << SEC_DST_SGL_OFFSET;
1264adc3f65aSKai Ye 	} else {
1265416d8220SZaibo Xu 		sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET;
1266adc3f65aSKai Ye 		da_type = SEC_SGL << SEC_DST_SGL_OFFSET;
1267adc3f65aSKai Ye 	}
1268adc3f65aSKai Ye 
1269adc3f65aSKai Ye 	sec_sqe->sdm_addr_type |= da_type;
1270416d8220SZaibo Xu 	scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET;
12719039878aSKai Ye 	if (req->in_dma != c_req->c_out_dma)
1272416d8220SZaibo Xu 		de = 0x1 << SEC_DE_OFFSET;
1273416d8220SZaibo Xu 
1274416d8220SZaibo Xu 	sec_sqe->sds_sa_type = (de | scene | sa_type);
1275416d8220SZaibo Xu 
1276416d8220SZaibo Xu 	sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len);
1277416d8220SZaibo Xu 	sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id);
1278416d8220SZaibo Xu 
1279416d8220SZaibo Xu 	return 0;
1280416d8220SZaibo Xu }
1281416d8220SZaibo Xu 
1282adc3f65aSKai Ye static int sec_skcipher_bd_fill_v3(struct sec_ctx *ctx, struct sec_req *req)
1283adc3f65aSKai Ye {
1284adc3f65aSKai Ye 	struct sec_sqe3 *sec_sqe3 = &req->sec_sqe3;
1285adc3f65aSKai Ye 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
1286adc3f65aSKai Ye 	struct sec_cipher_req *c_req = &req->c_req;
1287adc3f65aSKai Ye 	u32 bd_param = 0;
1288adc3f65aSKai Ye 	u16 cipher;
1289adc3f65aSKai Ye 
1290adc3f65aSKai Ye 	memset(sec_sqe3, 0, sizeof(struct sec_sqe3));
1291adc3f65aSKai Ye 
1292adc3f65aSKai Ye 	sec_sqe3->c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
1293adc3f65aSKai Ye 	sec_sqe3->no_scene.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
12949039878aSKai Ye 	sec_sqe3->data_src_addr = cpu_to_le64(req->in_dma);
1295adc3f65aSKai Ye 	sec_sqe3->data_dst_addr = cpu_to_le64(c_req->c_out_dma);
1296adc3f65aSKai Ye 
1297adc3f65aSKai Ye 	sec_sqe3->c_mode_alg = ((u8)c_ctx->c_alg << SEC_CALG_OFFSET_V3) |
1298adc3f65aSKai Ye 						c_ctx->c_mode;
1299adc3f65aSKai Ye 	sec_sqe3->c_icv_key |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
1300adc3f65aSKai Ye 						SEC_CKEY_OFFSET_V3);
1301adc3f65aSKai Ye 
1302adc3f65aSKai Ye 	if (c_req->encrypt)
1303adc3f65aSKai Ye 		cipher = SEC_CIPHER_ENC;
1304adc3f65aSKai Ye 	else
1305adc3f65aSKai Ye 		cipher = SEC_CIPHER_DEC;
1306adc3f65aSKai Ye 	sec_sqe3->c_icv_key |= cpu_to_le16(cipher);
1307adc3f65aSKai Ye 
1308566f060fSKai Ye 	/* Set the CTR counter mode is 128bit rollover */
1309566f060fSKai Ye 	sec_sqe3->auth_mac_key = cpu_to_le32((u32)SEC_CTR_CNT_ROLLOVER <<
1310566f060fSKai Ye 					SEC_CTR_CNT_OFFSET);
1311566f060fSKai Ye 
1312adc3f65aSKai Ye 	if (req->use_pbuf) {
1313adc3f65aSKai Ye 		bd_param |= SEC_PBUF << SEC_SRC_SGL_OFFSET_V3;
1314adc3f65aSKai Ye 		bd_param |= SEC_PBUF << SEC_DST_SGL_OFFSET_V3;
1315adc3f65aSKai Ye 	} else {
1316adc3f65aSKai Ye 		bd_param |= SEC_SGL << SEC_SRC_SGL_OFFSET_V3;
1317adc3f65aSKai Ye 		bd_param |= SEC_SGL << SEC_DST_SGL_OFFSET_V3;
1318adc3f65aSKai Ye 	}
1319adc3f65aSKai Ye 
1320adc3f65aSKai Ye 	bd_param |= SEC_COMM_SCENE << SEC_SCENE_OFFSET_V3;
13219039878aSKai Ye 	if (req->in_dma != c_req->c_out_dma)
1322adc3f65aSKai Ye 		bd_param |= 0x1 << SEC_DE_OFFSET_V3;
1323adc3f65aSKai Ye 
1324adc3f65aSKai Ye 	bd_param |= SEC_BD_TYPE3;
1325adc3f65aSKai Ye 	sec_sqe3->bd_param = cpu_to_le32(bd_param);
1326adc3f65aSKai Ye 
1327adc3f65aSKai Ye 	sec_sqe3->c_len_ivin |= cpu_to_le32(c_req->c_len);
1328adc3f65aSKai Ye 	sec_sqe3->tag = cpu_to_le64(req);
1329adc3f65aSKai Ye 
1330adc3f65aSKai Ye 	return 0;
1331adc3f65aSKai Ye }
1332adc3f65aSKai Ye 
13337b44c0eeSKai Ye /* increment counter (128-bit int) */
13347b44c0eeSKai Ye static void ctr_iv_inc(__u8 *counter, __u8 bits, __u32 nums)
13357b44c0eeSKai Ye {
13367b44c0eeSKai Ye 	do {
13377b44c0eeSKai Ye 		--bits;
13387b44c0eeSKai Ye 		nums += counter[bits];
13397b44c0eeSKai Ye 		counter[bits] = nums & BITS_MASK;
13407b44c0eeSKai Ye 		nums >>= BYTE_BITS;
13417b44c0eeSKai Ye 	} while (bits && nums);
13427b44c0eeSKai Ye }
13437b44c0eeSKai Ye 
13442f072d75SZaibo Xu static void sec_update_iv(struct sec_req *req, enum sec_alg_type alg_type)
1345416d8220SZaibo Xu {
13462f072d75SZaibo Xu 	struct aead_request *aead_req = req->aead_req.aead_req;
1347416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
1348416d8220SZaibo Xu 	u32 iv_size = req->ctx->c_ctx.ivsize;
1349416d8220SZaibo Xu 	struct scatterlist *sgl;
13502f072d75SZaibo Xu 	unsigned int cryptlen;
1351416d8220SZaibo Xu 	size_t sz;
13522f072d75SZaibo Xu 	u8 *iv;
1353416d8220SZaibo Xu 
1354416d8220SZaibo Xu 	if (req->c_req.encrypt)
13552f072d75SZaibo Xu 		sgl = alg_type == SEC_SKCIPHER ? sk_req->dst : aead_req->dst;
1356416d8220SZaibo Xu 	else
13572f072d75SZaibo Xu 		sgl = alg_type == SEC_SKCIPHER ? sk_req->src : aead_req->src;
1358416d8220SZaibo Xu 
13592f072d75SZaibo Xu 	if (alg_type == SEC_SKCIPHER) {
13602f072d75SZaibo Xu 		iv = sk_req->iv;
13612f072d75SZaibo Xu 		cryptlen = sk_req->cryptlen;
13622f072d75SZaibo Xu 	} else {
13632f072d75SZaibo Xu 		iv = aead_req->iv;
13642f072d75SZaibo Xu 		cryptlen = aead_req->cryptlen;
13652f072d75SZaibo Xu 	}
13662f072d75SZaibo Xu 
13677b44c0eeSKai Ye 	if (req->ctx->c_ctx.c_mode == SEC_CMODE_CBC) {
13682f072d75SZaibo Xu 		sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), iv, iv_size,
13692f072d75SZaibo Xu 					cryptlen - iv_size);
1370b9c8d897SZaibo Xu 		if (unlikely(sz != iv_size))
1371a44dce50SLongfang Liu 			dev_err(req->ctx->dev, "copy output iv error!\n");
13727b44c0eeSKai Ye 	} else {
13737b44c0eeSKai Ye 		sz = cryptlen / iv_size;
13747b44c0eeSKai Ye 		if (cryptlen % iv_size)
13757b44c0eeSKai Ye 			sz += 1;
13767b44c0eeSKai Ye 		ctr_iv_inc(iv, iv_size, sz);
13777b44c0eeSKai Ye 	}
1378416d8220SZaibo Xu }
1379416d8220SZaibo Xu 
13809597efc3SKai Ye static struct sec_req *sec_back_req_clear(struct sec_ctx *ctx,
13819597efc3SKai Ye 				struct sec_qp_ctx *qp_ctx)
13829597efc3SKai Ye {
13839597efc3SKai Ye 	struct sec_req *backlog_req = NULL;
13849597efc3SKai Ye 
1385*02884a4fSZhengchao Shao 	spin_lock_bh(&qp_ctx->req_lock);
13869597efc3SKai Ye 	if (ctx->fake_req_limit >=
13879597efc3SKai Ye 	    atomic_read(&qp_ctx->qp->qp_status.used) &&
13889597efc3SKai Ye 	    !list_empty(&qp_ctx->backlog)) {
13899597efc3SKai Ye 		backlog_req = list_first_entry(&qp_ctx->backlog,
13909597efc3SKai Ye 				typeof(*backlog_req), backlog_head);
13919597efc3SKai Ye 		list_del(&backlog_req->backlog_head);
13929597efc3SKai Ye 	}
1393*02884a4fSZhengchao Shao 	spin_unlock_bh(&qp_ctx->req_lock);
13949597efc3SKai Ye 
13959597efc3SKai Ye 	return backlog_req;
13969597efc3SKai Ye }
13979597efc3SKai Ye 
1398310ea0acSZaibo Xu static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req,
1399310ea0acSZaibo Xu 				  int err)
1400416d8220SZaibo Xu {
1401416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
1402416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
14039597efc3SKai Ye 	struct skcipher_request *backlog_sk_req;
14049597efc3SKai Ye 	struct sec_req *backlog_req;
1405416d8220SZaibo Xu 
1406416d8220SZaibo Xu 	sec_free_req_id(req);
1407416d8220SZaibo Xu 
14087b44c0eeSKai Ye 	/* IV output at encrypto of CBC/CTR mode */
14097b44c0eeSKai Ye 	if (!err && (ctx->c_ctx.c_mode == SEC_CMODE_CBC ||
14107b44c0eeSKai Ye 	    ctx->c_ctx.c_mode == SEC_CMODE_CTR) && req->c_req.encrypt)
14112f072d75SZaibo Xu 		sec_update_iv(req, SEC_SKCIPHER);
1412416d8220SZaibo Xu 
14139597efc3SKai Ye 	while (1) {
14149597efc3SKai Ye 		backlog_req = sec_back_req_clear(ctx, qp_ctx);
14159597efc3SKai Ye 		if (!backlog_req)
14169597efc3SKai Ye 			break;
14179597efc3SKai Ye 
14189597efc3SKai Ye 		backlog_sk_req = backlog_req->c_req.sk_req;
14199597efc3SKai Ye 		backlog_sk_req->base.complete(&backlog_sk_req->base,
14209597efc3SKai Ye 						-EINPROGRESS);
14219597efc3SKai Ye 		atomic64_inc(&ctx->sec->debug.dfx.recv_busy_cnt);
14229597efc3SKai Ye 	}
14239597efc3SKai Ye 
1424310ea0acSZaibo Xu 	sk_req->base.complete(&sk_req->base, err);
1425416d8220SZaibo Xu }
1426416d8220SZaibo Xu 
1427c16a70c1SKai Ye static void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req)
14282f072d75SZaibo Xu {
14292f072d75SZaibo Xu 	struct aead_request *aead_req = req->aead_req.aead_req;
14302514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
1431c16a70c1SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
1432c16a70c1SKai Ye 	size_t authsize = ctx->a_ctx.mac_len;
1433c16a70c1SKai Ye 	u32 data_size = aead_req->cryptlen;
1434c16a70c1SKai Ye 	u8 flage = 0;
1435c16a70c1SKai Ye 	u8 cm, cl;
1436c16a70c1SKai Ye 
1437c16a70c1SKai Ye 	/* the specification has been checked in aead_iv_demension_check() */
1438c16a70c1SKai Ye 	cl = c_req->c_ivin[0] + 1;
1439c16a70c1SKai Ye 	c_req->c_ivin[ctx->c_ctx.ivsize - cl] = 0x00;
1440c16a70c1SKai Ye 	memset(&c_req->c_ivin[ctx->c_ctx.ivsize - cl], 0, cl);
1441c16a70c1SKai Ye 	c_req->c_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE1] = IV_CTR_INIT;
1442c16a70c1SKai Ye 
1443c16a70c1SKai Ye 	/* the last 3bit is L' */
1444c16a70c1SKai Ye 	flage |= c_req->c_ivin[0] & IV_CL_MASK;
1445c16a70c1SKai Ye 
1446c16a70c1SKai Ye 	/* the M' is bit3~bit5, the Flags is bit6 */
1447c16a70c1SKai Ye 	cm = (authsize - IV_CM_CAL_NUM) / IV_CM_CAL_NUM;
1448c16a70c1SKai Ye 	flage |= cm << IV_CM_OFFSET;
1449c16a70c1SKai Ye 	if (aead_req->assoclen)
1450c16a70c1SKai Ye 		flage |= 0x01 << IV_FLAGS_OFFSET;
1451c16a70c1SKai Ye 
1452c16a70c1SKai Ye 	memcpy(a_req->a_ivin, c_req->c_ivin, ctx->c_ctx.ivsize);
1453c16a70c1SKai Ye 	a_req->a_ivin[0] = flage;
1454c16a70c1SKai Ye 
1455c16a70c1SKai Ye 	/*
1456c16a70c1SKai Ye 	 * the last 32bit is counter's initial number,
1457c16a70c1SKai Ye 	 * but the nonce uses the first 16bit
1458c16a70c1SKai Ye 	 * the tail 16bit fill with the cipher length
1459c16a70c1SKai Ye 	 */
1460c16a70c1SKai Ye 	if (!c_req->encrypt)
1461c16a70c1SKai Ye 		data_size = aead_req->cryptlen - authsize;
1462c16a70c1SKai Ye 
1463c16a70c1SKai Ye 	a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE1] =
1464c16a70c1SKai Ye 			data_size & IV_LAST_BYTE_MASK;
1465c16a70c1SKai Ye 	data_size >>= IV_BYTE_OFFSET;
1466c16a70c1SKai Ye 	a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE2] =
1467c16a70c1SKai Ye 			data_size & IV_LAST_BYTE_MASK;
1468c16a70c1SKai Ye }
1469c16a70c1SKai Ye 
1470c16a70c1SKai Ye static void sec_aead_set_iv(struct sec_ctx *ctx, struct sec_req *req)
1471c16a70c1SKai Ye {
1472c16a70c1SKai Ye 	struct aead_request *aead_req = req->aead_req.aead_req;
1473c16a70c1SKai Ye 	struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
1474c16a70c1SKai Ye 	size_t authsize = crypto_aead_authsize(tfm);
1475c16a70c1SKai Ye 	struct sec_cipher_req *c_req = &req->c_req;
1476c16a70c1SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
14772f072d75SZaibo Xu 
14782514f559SLongfang Liu 	memcpy(c_req->c_ivin, aead_req->iv, ctx->c_ctx.ivsize);
1479c16a70c1SKai Ye 
1480c16a70c1SKai Ye 	if (ctx->c_ctx.c_mode == SEC_CMODE_CCM) {
1481c16a70c1SKai Ye 		/*
1482c16a70c1SKai Ye 		 * CCM 16Byte Cipher_IV: {1B_Flage,13B_IV,2B_counter},
1483c16a70c1SKai Ye 		 * the  counter must set to 0x01
1484c16a70c1SKai Ye 		 */
1485c16a70c1SKai Ye 		ctx->a_ctx.mac_len = authsize;
1486c16a70c1SKai Ye 		/* CCM 16Byte Auth_IV: {1B_AFlage,13B_IV,2B_Ptext_length} */
1487c16a70c1SKai Ye 		set_aead_auth_iv(ctx, req);
1488c16a70c1SKai Ye 	}
1489c16a70c1SKai Ye 
1490c16a70c1SKai Ye 	/* GCM 12Byte Cipher_IV == Auth_IV */
1491c16a70c1SKai Ye 	if (ctx->c_ctx.c_mode == SEC_CMODE_GCM) {
1492c16a70c1SKai Ye 		ctx->a_ctx.mac_len = authsize;
1493c16a70c1SKai Ye 		memcpy(a_req->a_ivin, c_req->c_ivin, SEC_AIV_SIZE);
1494c16a70c1SKai Ye 	}
1495c16a70c1SKai Ye }
1496c16a70c1SKai Ye 
1497c16a70c1SKai Ye static void sec_auth_bd_fill_xcm(struct sec_auth_ctx *ctx, int dir,
1498c16a70c1SKai Ye 				 struct sec_req *req, struct sec_sqe *sec_sqe)
1499c16a70c1SKai Ye {
1500c16a70c1SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
1501c16a70c1SKai Ye 	struct aead_request *aq = a_req->aead_req;
1502c16a70c1SKai Ye 
1503c16a70c1SKai Ye 	/* C_ICV_Len is MAC size, 0x4 ~ 0x10 */
1504c16a70c1SKai Ye 	sec_sqe->type2.icvw_kmode |= cpu_to_le16((u16)ctx->mac_len);
1505c16a70c1SKai Ye 
1506c16a70c1SKai Ye 	/* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */
1507c16a70c1SKai Ye 	sec_sqe->type2.a_key_addr = sec_sqe->type2.c_key_addr;
1508c16a70c1SKai Ye 	sec_sqe->type2.a_ivin_addr = cpu_to_le64(a_req->a_ivin_dma);
1509c16a70c1SKai Ye 	sec_sqe->type_cipher_auth |= SEC_NO_AUTH << SEC_AUTH_OFFSET;
1510c16a70c1SKai Ye 
1511c16a70c1SKai Ye 	if (dir)
1512c16a70c1SKai Ye 		sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH;
1513c16a70c1SKai Ye 	else
1514c16a70c1SKai Ye 		sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER;
1515c16a70c1SKai Ye 
1516c16a70c1SKai Ye 	sec_sqe->type2.alen_ivllen = cpu_to_le32(aq->assoclen);
1517c16a70c1SKai Ye 	sec_sqe->type2.auth_src_offset = cpu_to_le16(0x0);
1518c16a70c1SKai Ye 	sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
1519c16a70c1SKai Ye 
1520c16a70c1SKai Ye 	sec_sqe->type2.mac_addr = cpu_to_le64(a_req->out_mac_dma);
1521c16a70c1SKai Ye }
1522c16a70c1SKai Ye 
1523c16a70c1SKai Ye static void sec_auth_bd_fill_xcm_v3(struct sec_auth_ctx *ctx, int dir,
1524c16a70c1SKai Ye 				    struct sec_req *req, struct sec_sqe3 *sqe3)
1525c16a70c1SKai Ye {
1526c16a70c1SKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
1527c16a70c1SKai Ye 	struct aead_request *aq = a_req->aead_req;
1528c16a70c1SKai Ye 
1529c16a70c1SKai Ye 	/* C_ICV_Len is MAC size, 0x4 ~ 0x10 */
1530c16a70c1SKai Ye 	sqe3->c_icv_key |= cpu_to_le16((u16)ctx->mac_len << SEC_MAC_OFFSET_V3);
1531c16a70c1SKai Ye 
1532c16a70c1SKai Ye 	/* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */
1533c16a70c1SKai Ye 	sqe3->a_key_addr = sqe3->c_key_addr;
1534c16a70c1SKai Ye 	sqe3->auth_ivin.a_ivin_addr = cpu_to_le64(a_req->a_ivin_dma);
1535c16a70c1SKai Ye 	sqe3->auth_mac_key |= SEC_NO_AUTH;
1536c16a70c1SKai Ye 
1537c16a70c1SKai Ye 	if (dir)
1538c16a70c1SKai Ye 		sqe3->huk_iv_seq &= SEC_CIPHER_AUTH_V3;
1539c16a70c1SKai Ye 	else
1540c16a70c1SKai Ye 		sqe3->huk_iv_seq |= SEC_AUTH_CIPHER_V3;
1541c16a70c1SKai Ye 
1542c16a70c1SKai Ye 	sqe3->a_len_key = cpu_to_le32(aq->assoclen);
1543c16a70c1SKai Ye 	sqe3->auth_src_offset = cpu_to_le16(0x0);
1544c16a70c1SKai Ye 	sqe3->cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
1545c16a70c1SKai Ye 	sqe3->mac_addr = cpu_to_le64(a_req->out_mac_dma);
15462f072d75SZaibo Xu }
15472f072d75SZaibo Xu 
15482f072d75SZaibo Xu static void sec_auth_bd_fill_ex(struct sec_auth_ctx *ctx, int dir,
15492f072d75SZaibo Xu 			       struct sec_req *req, struct sec_sqe *sec_sqe)
15502f072d75SZaibo Xu {
15512f072d75SZaibo Xu 	struct sec_aead_req *a_req = &req->aead_req;
15522f072d75SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
15532f072d75SZaibo Xu 	struct aead_request *aq = a_req->aead_req;
15542f072d75SZaibo Xu 
15552f072d75SZaibo Xu 	sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma);
15562f072d75SZaibo Xu 
15572f072d75SZaibo Xu 	sec_sqe->type2.mac_key_alg =
15582f072d75SZaibo Xu 			cpu_to_le32(ctx->mac_len / SEC_SQE_LEN_RATE);
15592f072d75SZaibo Xu 
15602f072d75SZaibo Xu 	sec_sqe->type2.mac_key_alg |=
15612f072d75SZaibo Xu 			cpu_to_le32((u32)((ctx->a_key_len) /
15622f072d75SZaibo Xu 			SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET);
15632f072d75SZaibo Xu 
15642f072d75SZaibo Xu 	sec_sqe->type2.mac_key_alg |=
15652f072d75SZaibo Xu 			cpu_to_le32((u32)(ctx->a_alg) << SEC_AEAD_ALG_OFFSET);
15662f072d75SZaibo Xu 
1567668f1ab7SKai Ye 	if (dir) {
15682f072d75SZaibo Xu 		sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE1 << SEC_AUTH_OFFSET;
15692f072d75SZaibo Xu 		sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH;
1570668f1ab7SKai Ye 	} else {
1571668f1ab7SKai Ye 		sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE2 << SEC_AUTH_OFFSET;
15722f072d75SZaibo Xu 		sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER;
1573668f1ab7SKai Ye 	}
15742f072d75SZaibo Xu 	sec_sqe->type2.alen_ivllen = cpu_to_le32(c_req->c_len + aq->assoclen);
15752f072d75SZaibo Xu 
15762f072d75SZaibo Xu 	sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
15772f072d75SZaibo Xu 
15782514f559SLongfang Liu 	sec_sqe->type2.mac_addr = cpu_to_le64(a_req->out_mac_dma);
15792f072d75SZaibo Xu }
15802f072d75SZaibo Xu 
15812f072d75SZaibo Xu static int sec_aead_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
15822f072d75SZaibo Xu {
15832f072d75SZaibo Xu 	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
15842f072d75SZaibo Xu 	struct sec_sqe *sec_sqe = &req->sec_sqe;
15852f072d75SZaibo Xu 	int ret;
15862f072d75SZaibo Xu 
15872f072d75SZaibo Xu 	ret = sec_skcipher_bd_fill(ctx, req);
15882f072d75SZaibo Xu 	if (unlikely(ret)) {
1589a44dce50SLongfang Liu 		dev_err(ctx->dev, "skcipher bd fill is error!\n");
15902f072d75SZaibo Xu 		return ret;
15912f072d75SZaibo Xu 	}
15922f072d75SZaibo Xu 
1593c16a70c1SKai Ye 	if (ctx->c_ctx.c_mode == SEC_CMODE_CCM ||
1594c16a70c1SKai Ye 	    ctx->c_ctx.c_mode == SEC_CMODE_GCM)
1595c16a70c1SKai Ye 		sec_auth_bd_fill_xcm(auth_ctx, req->c_req.encrypt, req, sec_sqe);
1596c16a70c1SKai Ye 	else
15972f072d75SZaibo Xu 		sec_auth_bd_fill_ex(auth_ctx, req->c_req.encrypt, req, sec_sqe);
15982f072d75SZaibo Xu 
15992f072d75SZaibo Xu 	return 0;
16002f072d75SZaibo Xu }
16012f072d75SZaibo Xu 
1602adc3f65aSKai Ye static void sec_auth_bd_fill_ex_v3(struct sec_auth_ctx *ctx, int dir,
1603adc3f65aSKai Ye 				   struct sec_req *req, struct sec_sqe3 *sqe3)
1604adc3f65aSKai Ye {
1605adc3f65aSKai Ye 	struct sec_aead_req *a_req = &req->aead_req;
1606adc3f65aSKai Ye 	struct sec_cipher_req *c_req = &req->c_req;
1607adc3f65aSKai Ye 	struct aead_request *aq = a_req->aead_req;
1608adc3f65aSKai Ye 
1609adc3f65aSKai Ye 	sqe3->a_key_addr = cpu_to_le64(ctx->a_key_dma);
1610adc3f65aSKai Ye 
1611adc3f65aSKai Ye 	sqe3->auth_mac_key |=
1612adc3f65aSKai Ye 			cpu_to_le32((u32)(ctx->mac_len /
1613adc3f65aSKai Ye 			SEC_SQE_LEN_RATE) << SEC_MAC_OFFSET_V3);
1614adc3f65aSKai Ye 
1615adc3f65aSKai Ye 	sqe3->auth_mac_key |=
1616adc3f65aSKai Ye 			cpu_to_le32((u32)(ctx->a_key_len /
1617adc3f65aSKai Ye 			SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET_V3);
1618adc3f65aSKai Ye 
1619adc3f65aSKai Ye 	sqe3->auth_mac_key |=
1620adc3f65aSKai Ye 			cpu_to_le32((u32)(ctx->a_alg) << SEC_AUTH_ALG_OFFSET_V3);
1621adc3f65aSKai Ye 
1622adc3f65aSKai Ye 	if (dir) {
1623adc3f65aSKai Ye 		sqe3->auth_mac_key |= cpu_to_le32((u32)SEC_AUTH_TYPE1);
1624adc3f65aSKai Ye 		sqe3->huk_iv_seq &= SEC_CIPHER_AUTH_V3;
1625adc3f65aSKai Ye 	} else {
162660ef3ddeSKai Ye 		sqe3->auth_mac_key |= cpu_to_le32((u32)SEC_AUTH_TYPE2);
1627adc3f65aSKai Ye 		sqe3->huk_iv_seq |= SEC_AUTH_CIPHER_V3;
1628adc3f65aSKai Ye 	}
1629adc3f65aSKai Ye 	sqe3->a_len_key = cpu_to_le32(c_req->c_len + aq->assoclen);
1630adc3f65aSKai Ye 
1631adc3f65aSKai Ye 	sqe3->cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
1632adc3f65aSKai Ye 
1633adc3f65aSKai Ye 	sqe3->mac_addr = cpu_to_le64(a_req->out_mac_dma);
1634adc3f65aSKai Ye }
1635adc3f65aSKai Ye 
1636adc3f65aSKai Ye static int sec_aead_bd_fill_v3(struct sec_ctx *ctx, struct sec_req *req)
1637adc3f65aSKai Ye {
1638adc3f65aSKai Ye 	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
1639adc3f65aSKai Ye 	struct sec_sqe3 *sec_sqe3 = &req->sec_sqe3;
1640adc3f65aSKai Ye 	int ret;
1641adc3f65aSKai Ye 
1642adc3f65aSKai Ye 	ret = sec_skcipher_bd_fill_v3(ctx, req);
1643adc3f65aSKai Ye 	if (unlikely(ret)) {
1644adc3f65aSKai Ye 		dev_err(ctx->dev, "skcipher bd3 fill is error!\n");
1645adc3f65aSKai Ye 		return ret;
1646adc3f65aSKai Ye 	}
1647adc3f65aSKai Ye 
1648c16a70c1SKai Ye 	if (ctx->c_ctx.c_mode == SEC_CMODE_CCM ||
1649c16a70c1SKai Ye 	    ctx->c_ctx.c_mode == SEC_CMODE_GCM)
1650c16a70c1SKai Ye 		sec_auth_bd_fill_xcm_v3(auth_ctx, req->c_req.encrypt,
1651c16a70c1SKai Ye 					req, sec_sqe3);
1652c16a70c1SKai Ye 	else
1653c16a70c1SKai Ye 		sec_auth_bd_fill_ex_v3(auth_ctx, req->c_req.encrypt,
1654c16a70c1SKai Ye 				       req, sec_sqe3);
1655adc3f65aSKai Ye 
1656adc3f65aSKai Ye 	return 0;
1657adc3f65aSKai Ye }
1658adc3f65aSKai Ye 
16592f072d75SZaibo Xu static void sec_aead_callback(struct sec_ctx *c, struct sec_req *req, int err)
16602f072d75SZaibo Xu {
16612f072d75SZaibo Xu 	struct aead_request *a_req = req->aead_req.aead_req;
16622f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
16632514f559SLongfang Liu 	struct sec_aead_req *aead_req = &req->aead_req;
16642f072d75SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
16652f072d75SZaibo Xu 	size_t authsize = crypto_aead_authsize(tfm);
16662f072d75SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
16679597efc3SKai Ye 	struct aead_request *backlog_aead_req;
16689597efc3SKai Ye 	struct sec_req *backlog_req;
16692f072d75SZaibo Xu 	size_t sz;
16702f072d75SZaibo Xu 
16712f072d75SZaibo Xu 	if (!err && c->c_ctx.c_mode == SEC_CMODE_CBC && c_req->encrypt)
16722f072d75SZaibo Xu 		sec_update_iv(req, SEC_AEAD);
16732f072d75SZaibo Xu 
16742f072d75SZaibo Xu 	/* Copy output mac */
16752f072d75SZaibo Xu 	if (!err && c_req->encrypt) {
16762f072d75SZaibo Xu 		struct scatterlist *sgl = a_req->dst;
16772f072d75SZaibo Xu 
16782f072d75SZaibo Xu 		sz = sg_pcopy_from_buffer(sgl, sg_nents(sgl),
16792514f559SLongfang Liu 					  aead_req->out_mac,
16802f072d75SZaibo Xu 					  authsize, a_req->cryptlen +
16812f072d75SZaibo Xu 					  a_req->assoclen);
16822f072d75SZaibo Xu 
16832f072d75SZaibo Xu 		if (unlikely(sz != authsize)) {
1684a44dce50SLongfang Liu 			dev_err(c->dev, "copy out mac err!\n");
16852f072d75SZaibo Xu 			err = -EINVAL;
16862f072d75SZaibo Xu 		}
16872f072d75SZaibo Xu 	}
16882f072d75SZaibo Xu 
16892f072d75SZaibo Xu 	sec_free_req_id(req);
16902f072d75SZaibo Xu 
16919597efc3SKai Ye 	while (1) {
16929597efc3SKai Ye 		backlog_req = sec_back_req_clear(c, qp_ctx);
16939597efc3SKai Ye 		if (!backlog_req)
16949597efc3SKai Ye 			break;
16959597efc3SKai Ye 
16969597efc3SKai Ye 		backlog_aead_req = backlog_req->aead_req.aead_req;
16979597efc3SKai Ye 		backlog_aead_req->base.complete(&backlog_aead_req->base,
16989597efc3SKai Ye 						-EINPROGRESS);
16999597efc3SKai Ye 		atomic64_inc(&c->sec->debug.dfx.recv_busy_cnt);
17009597efc3SKai Ye 	}
17012f072d75SZaibo Xu 
17022f072d75SZaibo Xu 	a_req->base.complete(&a_req->base, err);
17032f072d75SZaibo Xu }
17042f072d75SZaibo Xu 
1705416d8220SZaibo Xu static void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req)
1706416d8220SZaibo Xu {
1707416d8220SZaibo Xu 	sec_free_req_id(req);
1708a181647cSZaibo Xu 	sec_free_queue_id(ctx, req);
1709416d8220SZaibo Xu }
1710416d8220SZaibo Xu 
1711416d8220SZaibo Xu static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
1712416d8220SZaibo Xu {
1713416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
17147c7d902aSZaibo Xu 	int queue_id;
1715416d8220SZaibo Xu 
1716416d8220SZaibo Xu 	/* To load balance */
1717a181647cSZaibo Xu 	queue_id = sec_alloc_queue_id(ctx, req);
1718a181647cSZaibo Xu 	qp_ctx = &ctx->qp_ctx[queue_id];
1719416d8220SZaibo Xu 
1720416d8220SZaibo Xu 	req->req_id = sec_alloc_req_id(req, qp_ctx);
1721b9c8d897SZaibo Xu 	if (unlikely(req->req_id < 0)) {
1722a181647cSZaibo Xu 		sec_free_queue_id(ctx, req);
1723416d8220SZaibo Xu 		return req->req_id;
1724416d8220SZaibo Xu 	}
1725416d8220SZaibo Xu 
17267c7d902aSZaibo Xu 	return 0;
1727416d8220SZaibo Xu }
1728416d8220SZaibo Xu 
1729416d8220SZaibo Xu static int sec_process(struct sec_ctx *ctx, struct sec_req *req)
1730416d8220SZaibo Xu {
17312514f559SLongfang Liu 	struct sec_cipher_req *c_req = &req->c_req;
1732416d8220SZaibo Xu 	int ret;
1733416d8220SZaibo Xu 
1734416d8220SZaibo Xu 	ret = sec_request_init(ctx, req);
1735b9c8d897SZaibo Xu 	if (unlikely(ret))
1736416d8220SZaibo Xu 		return ret;
1737416d8220SZaibo Xu 
1738416d8220SZaibo Xu 	ret = sec_request_transfer(ctx, req);
1739b9c8d897SZaibo Xu 	if (unlikely(ret))
1740416d8220SZaibo Xu 		goto err_uninit_req;
1741416d8220SZaibo Xu 
1742416d8220SZaibo Xu 	/* Output IV as decrypto */
17437b44c0eeSKai Ye 	if (!req->c_req.encrypt && (ctx->c_ctx.c_mode == SEC_CMODE_CBC ||
17447b44c0eeSKai Ye 	    ctx->c_ctx.c_mode == SEC_CMODE_CTR))
17452f072d75SZaibo Xu 		sec_update_iv(req, ctx->alg_type);
1746416d8220SZaibo Xu 
1747416d8220SZaibo Xu 	ret = ctx->req_op->bd_send(ctx, req);
17489597efc3SKai Ye 	if (unlikely((ret != -EBUSY && ret != -EINPROGRESS) ||
17499597efc3SKai Ye 		(ret == -EBUSY && !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG)))) {
1750a44dce50SLongfang Liu 		dev_err_ratelimited(ctx->dev, "send sec request failed!\n");
1751416d8220SZaibo Xu 		goto err_send_req;
1752416d8220SZaibo Xu 	}
1753416d8220SZaibo Xu 
1754416d8220SZaibo Xu 	return ret;
1755416d8220SZaibo Xu 
1756416d8220SZaibo Xu err_send_req:
1757416d8220SZaibo Xu 	/* As failing, restore the IV from user */
17582f072d75SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) {
17592f072d75SZaibo Xu 		if (ctx->alg_type == SEC_SKCIPHER)
17602514f559SLongfang Liu 			memcpy(req->c_req.sk_req->iv, c_req->c_ivin,
1761416d8220SZaibo Xu 			       ctx->c_ctx.ivsize);
17622f072d75SZaibo Xu 		else
17632514f559SLongfang Liu 			memcpy(req->aead_req.aead_req->iv, c_req->c_ivin,
17642f072d75SZaibo Xu 			       ctx->c_ctx.ivsize);
17652f072d75SZaibo Xu 	}
1766416d8220SZaibo Xu 
1767416d8220SZaibo Xu 	sec_request_untransfer(ctx, req);
1768416d8220SZaibo Xu err_uninit_req:
1769416d8220SZaibo Xu 	sec_request_uninit(ctx, req);
1770416d8220SZaibo Xu 	return ret;
1771416d8220SZaibo Xu }
1772416d8220SZaibo Xu 
1773a181647cSZaibo Xu static const struct sec_req_op sec_skcipher_req_ops = {
1774416d8220SZaibo Xu 	.buf_map	= sec_skcipher_sgl_map,
1775416d8220SZaibo Xu 	.buf_unmap	= sec_skcipher_sgl_unmap,
1776416d8220SZaibo Xu 	.do_transfer	= sec_skcipher_copy_iv,
1777416d8220SZaibo Xu 	.bd_fill	= sec_skcipher_bd_fill,
1778416d8220SZaibo Xu 	.bd_send	= sec_bd_send,
1779416d8220SZaibo Xu 	.callback	= sec_skcipher_callback,
1780416d8220SZaibo Xu 	.process	= sec_process,
1781416d8220SZaibo Xu };
1782416d8220SZaibo Xu 
17832f072d75SZaibo Xu static const struct sec_req_op sec_aead_req_ops = {
17842f072d75SZaibo Xu 	.buf_map	= sec_aead_sgl_map,
17852f072d75SZaibo Xu 	.buf_unmap	= sec_aead_sgl_unmap,
1786c16a70c1SKai Ye 	.do_transfer	= sec_aead_set_iv,
17872f072d75SZaibo Xu 	.bd_fill	= sec_aead_bd_fill,
17882f072d75SZaibo Xu 	.bd_send	= sec_bd_send,
17892f072d75SZaibo Xu 	.callback	= sec_aead_callback,
17902f072d75SZaibo Xu 	.process	= sec_process,
17912f072d75SZaibo Xu };
17922f072d75SZaibo Xu 
1793adc3f65aSKai Ye static const struct sec_req_op sec_skcipher_req_ops_v3 = {
1794adc3f65aSKai Ye 	.buf_map	= sec_skcipher_sgl_map,
1795adc3f65aSKai Ye 	.buf_unmap	= sec_skcipher_sgl_unmap,
1796adc3f65aSKai Ye 	.do_transfer	= sec_skcipher_copy_iv,
1797adc3f65aSKai Ye 	.bd_fill	= sec_skcipher_bd_fill_v3,
1798adc3f65aSKai Ye 	.bd_send	= sec_bd_send,
1799adc3f65aSKai Ye 	.callback	= sec_skcipher_callback,
1800adc3f65aSKai Ye 	.process	= sec_process,
1801adc3f65aSKai Ye };
1802adc3f65aSKai Ye 
1803adc3f65aSKai Ye static const struct sec_req_op sec_aead_req_ops_v3 = {
1804adc3f65aSKai Ye 	.buf_map	= sec_aead_sgl_map,
1805adc3f65aSKai Ye 	.buf_unmap	= sec_aead_sgl_unmap,
1806c16a70c1SKai Ye 	.do_transfer	= sec_aead_set_iv,
1807adc3f65aSKai Ye 	.bd_fill	= sec_aead_bd_fill_v3,
1808adc3f65aSKai Ye 	.bd_send	= sec_bd_send,
1809adc3f65aSKai Ye 	.callback	= sec_aead_callback,
1810adc3f65aSKai Ye 	.process	= sec_process,
1811adc3f65aSKai Ye };
1812adc3f65aSKai Ye 
1813416d8220SZaibo Xu static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
1814416d8220SZaibo Xu {
1815416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
1816adc3f65aSKai Ye 	int ret;
1817416d8220SZaibo Xu 
1818adc3f65aSKai Ye 	ret = sec_skcipher_init(tfm);
1819adc3f65aSKai Ye 	if (ret)
1820adc3f65aSKai Ye 		return ret;
1821adc3f65aSKai Ye 
1822adc3f65aSKai Ye 	if (ctx->sec->qm.ver < QM_HW_V3) {
1823adc3f65aSKai Ye 		ctx->type_supported = SEC_BD_TYPE2;
1824a181647cSZaibo Xu 		ctx->req_op = &sec_skcipher_req_ops;
1825adc3f65aSKai Ye 	} else {
1826adc3f65aSKai Ye 		ctx->type_supported = SEC_BD_TYPE3;
1827adc3f65aSKai Ye 		ctx->req_op = &sec_skcipher_req_ops_v3;
1828adc3f65aSKai Ye 	}
1829416d8220SZaibo Xu 
1830adc3f65aSKai Ye 	return ret;
1831416d8220SZaibo Xu }
1832416d8220SZaibo Xu 
1833416d8220SZaibo Xu static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm)
1834416d8220SZaibo Xu {
1835a181647cSZaibo Xu 	sec_skcipher_uninit(tfm);
1836416d8220SZaibo Xu }
1837416d8220SZaibo Xu 
18382f072d75SZaibo Xu static int sec_aead_init(struct crypto_aead *tfm)
18392f072d75SZaibo Xu {
18402f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
18412f072d75SZaibo Xu 	int ret;
18422f072d75SZaibo Xu 
18432f072d75SZaibo Xu 	crypto_aead_set_reqsize(tfm, sizeof(struct sec_req));
18442f072d75SZaibo Xu 	ctx->alg_type = SEC_AEAD;
18452f072d75SZaibo Xu 	ctx->c_ctx.ivsize = crypto_aead_ivsize(tfm);
1846c16a70c1SKai Ye 	if (ctx->c_ctx.ivsize < SEC_AIV_SIZE ||
1847c16a70c1SKai Ye 	    ctx->c_ctx.ivsize > SEC_IV_SIZE) {
1848c16a70c1SKai Ye 		pr_err("get error aead iv size!\n");
18492f072d75SZaibo Xu 		return -EINVAL;
18502f072d75SZaibo Xu 	}
18512f072d75SZaibo Xu 
18522f072d75SZaibo Xu 	ret = sec_ctx_base_init(ctx);
18532f072d75SZaibo Xu 	if (ret)
18542f072d75SZaibo Xu 		return ret;
1855adc3f65aSKai Ye 	if (ctx->sec->qm.ver < QM_HW_V3) {
1856adc3f65aSKai Ye 		ctx->type_supported = SEC_BD_TYPE2;
1857adc3f65aSKai Ye 		ctx->req_op = &sec_aead_req_ops;
1858adc3f65aSKai Ye 	} else {
1859adc3f65aSKai Ye 		ctx->type_supported = SEC_BD_TYPE3;
1860adc3f65aSKai Ye 		ctx->req_op = &sec_aead_req_ops_v3;
1861adc3f65aSKai Ye 	}
18622f072d75SZaibo Xu 
18632f072d75SZaibo Xu 	ret = sec_auth_init(ctx);
18642f072d75SZaibo Xu 	if (ret)
18652f072d75SZaibo Xu 		goto err_auth_init;
18662f072d75SZaibo Xu 
18672f072d75SZaibo Xu 	ret = sec_cipher_init(ctx);
18682f072d75SZaibo Xu 	if (ret)
18692f072d75SZaibo Xu 		goto err_cipher_init;
18702f072d75SZaibo Xu 
18712f072d75SZaibo Xu 	return ret;
18722f072d75SZaibo Xu 
18732f072d75SZaibo Xu err_cipher_init:
18742f072d75SZaibo Xu 	sec_auth_uninit(ctx);
18752f072d75SZaibo Xu err_auth_init:
18762f072d75SZaibo Xu 	sec_ctx_base_uninit(ctx);
18772f072d75SZaibo Xu 	return ret;
18782f072d75SZaibo Xu }
18792f072d75SZaibo Xu 
18802f072d75SZaibo Xu static void sec_aead_exit(struct crypto_aead *tfm)
18812f072d75SZaibo Xu {
18822f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
18832f072d75SZaibo Xu 
18842f072d75SZaibo Xu 	sec_cipher_uninit(ctx);
18852f072d75SZaibo Xu 	sec_auth_uninit(ctx);
18862f072d75SZaibo Xu 	sec_ctx_base_uninit(ctx);
18872f072d75SZaibo Xu }
18882f072d75SZaibo Xu 
18892f072d75SZaibo Xu static int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name)
18902f072d75SZaibo Xu {
18912f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
18922f072d75SZaibo Xu 	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
18932f072d75SZaibo Xu 	int ret;
18942f072d75SZaibo Xu 
18952f072d75SZaibo Xu 	ret = sec_aead_init(tfm);
18962f072d75SZaibo Xu 	if (ret) {
18972f072d75SZaibo Xu 		pr_err("hisi_sec2: aead init error!\n");
18982f072d75SZaibo Xu 		return ret;
18992f072d75SZaibo Xu 	}
19002f072d75SZaibo Xu 
19012f072d75SZaibo Xu 	auth_ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
19022f072d75SZaibo Xu 	if (IS_ERR(auth_ctx->hash_tfm)) {
1903a44dce50SLongfang Liu 		dev_err(ctx->dev, "aead alloc shash error!\n");
19042f072d75SZaibo Xu 		sec_aead_exit(tfm);
19052f072d75SZaibo Xu 		return PTR_ERR(auth_ctx->hash_tfm);
19062f072d75SZaibo Xu 	}
19072f072d75SZaibo Xu 
19082f072d75SZaibo Xu 	return 0;
19092f072d75SZaibo Xu }
19102f072d75SZaibo Xu 
19112f072d75SZaibo Xu static void sec_aead_ctx_exit(struct crypto_aead *tfm)
19122f072d75SZaibo Xu {
19132f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
19142f072d75SZaibo Xu 
19152f072d75SZaibo Xu 	crypto_free_shash(ctx->a_ctx.hash_tfm);
19162f072d75SZaibo Xu 	sec_aead_exit(tfm);
19172f072d75SZaibo Xu }
19182f072d75SZaibo Xu 
1919c16a70c1SKai Ye static int sec_aead_xcm_ctx_init(struct crypto_aead *tfm)
1920c16a70c1SKai Ye {
19216c46a329SKai Ye 	struct aead_alg *alg = crypto_aead_alg(tfm);
1922c16a70c1SKai Ye 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
19236c46a329SKai Ye 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
19246c46a329SKai Ye 	const char *aead_name = alg->base.cra_name;
1925c16a70c1SKai Ye 	int ret;
1926c16a70c1SKai Ye 
1927c16a70c1SKai Ye 	ret = sec_aead_init(tfm);
1928c16a70c1SKai Ye 	if (ret) {
1929c16a70c1SKai Ye 		dev_err(ctx->dev, "hisi_sec2: aead xcm init error!\n");
1930c16a70c1SKai Ye 		return ret;
1931c16a70c1SKai Ye 	}
1932c16a70c1SKai Ye 
19336c46a329SKai Ye 	a_ctx->fallback_aead_tfm = crypto_alloc_aead(aead_name, 0,
19346c46a329SKai Ye 						     CRYPTO_ALG_NEED_FALLBACK |
19356c46a329SKai Ye 						     CRYPTO_ALG_ASYNC);
19366c46a329SKai Ye 	if (IS_ERR(a_ctx->fallback_aead_tfm)) {
19376c46a329SKai Ye 		dev_err(ctx->dev, "aead driver alloc fallback tfm error!\n");
19386c46a329SKai Ye 		sec_aead_exit(tfm);
19396c46a329SKai Ye 		return PTR_ERR(a_ctx->fallback_aead_tfm);
19406c46a329SKai Ye 	}
19416c46a329SKai Ye 	a_ctx->fallback = false;
19426c46a329SKai Ye 
1943c16a70c1SKai Ye 	return 0;
1944c16a70c1SKai Ye }
1945c16a70c1SKai Ye 
1946c16a70c1SKai Ye static void sec_aead_xcm_ctx_exit(struct crypto_aead *tfm)
1947c16a70c1SKai Ye {
19486c46a329SKai Ye 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
19496c46a329SKai Ye 
19506c46a329SKai Ye 	crypto_free_aead(ctx->a_ctx.fallback_aead_tfm);
1951c16a70c1SKai Ye 	sec_aead_exit(tfm);
1952c16a70c1SKai Ye }
1953c16a70c1SKai Ye 
19542f072d75SZaibo Xu static int sec_aead_sha1_ctx_init(struct crypto_aead *tfm)
19552f072d75SZaibo Xu {
19562f072d75SZaibo Xu 	return sec_aead_ctx_init(tfm, "sha1");
19572f072d75SZaibo Xu }
19582f072d75SZaibo Xu 
19592f072d75SZaibo Xu static int sec_aead_sha256_ctx_init(struct crypto_aead *tfm)
19602f072d75SZaibo Xu {
19612f072d75SZaibo Xu 	return sec_aead_ctx_init(tfm, "sha256");
19622f072d75SZaibo Xu }
19632f072d75SZaibo Xu 
19642f072d75SZaibo Xu static int sec_aead_sha512_ctx_init(struct crypto_aead *tfm)
19652f072d75SZaibo Xu {
19662f072d75SZaibo Xu 	return sec_aead_ctx_init(tfm, "sha512");
19672f072d75SZaibo Xu }
19682f072d75SZaibo Xu 
1969059c5342SLongfang Liu 
1970059c5342SLongfang Liu static int sec_skcipher_cryptlen_ckeck(struct sec_ctx *ctx,
1971059c5342SLongfang Liu 	struct sec_req *sreq)
1972059c5342SLongfang Liu {
1973059c5342SLongfang Liu 	u32 cryptlen = sreq->c_req.sk_req->cryptlen;
1974059c5342SLongfang Liu 	struct device *dev = ctx->dev;
1975059c5342SLongfang Liu 	u8 c_mode = ctx->c_ctx.c_mode;
1976059c5342SLongfang Liu 	int ret = 0;
1977059c5342SLongfang Liu 
1978059c5342SLongfang Liu 	switch (c_mode) {
1979059c5342SLongfang Liu 	case SEC_CMODE_XTS:
1980059c5342SLongfang Liu 		if (unlikely(cryptlen < AES_BLOCK_SIZE)) {
1981059c5342SLongfang Liu 			dev_err(dev, "skcipher XTS mode input length error!\n");
1982059c5342SLongfang Liu 			ret = -EINVAL;
1983059c5342SLongfang Liu 		}
1984059c5342SLongfang Liu 		break;
1985059c5342SLongfang Liu 	case SEC_CMODE_ECB:
1986059c5342SLongfang Liu 	case SEC_CMODE_CBC:
1987059c5342SLongfang Liu 		if (unlikely(cryptlen & (AES_BLOCK_SIZE - 1))) {
1988059c5342SLongfang Liu 			dev_err(dev, "skcipher AES input length error!\n");
1989059c5342SLongfang Liu 			ret = -EINVAL;
1990059c5342SLongfang Liu 		}
1991059c5342SLongfang Liu 		break;
19927b44c0eeSKai Ye 	case SEC_CMODE_CFB:
19937b44c0eeSKai Ye 	case SEC_CMODE_OFB:
19947b44c0eeSKai Ye 	case SEC_CMODE_CTR:
19957b44c0eeSKai Ye 		if (unlikely(ctx->sec->qm.ver < QM_HW_V3)) {
19967b44c0eeSKai Ye 			dev_err(dev, "skcipher HW version error!\n");
19977b44c0eeSKai Ye 			ret = -EINVAL;
19987b44c0eeSKai Ye 		}
19997b44c0eeSKai Ye 		break;
2000059c5342SLongfang Liu 	default:
2001059c5342SLongfang Liu 		ret = -EINVAL;
2002059c5342SLongfang Liu 	}
2003059c5342SLongfang Liu 
2004059c5342SLongfang Liu 	return ret;
2005059c5342SLongfang Liu }
2006059c5342SLongfang Liu 
2007d6de2a59SZaibo Xu static int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
2008416d8220SZaibo Xu {
2009d6de2a59SZaibo Xu 	struct skcipher_request *sk_req = sreq->c_req.sk_req;
2010a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
2011d6de2a59SZaibo Xu 	u8 c_alg = ctx->c_ctx.c_alg;
2012416d8220SZaibo Xu 
20137b44c0eeSKai Ye 	if (unlikely(!sk_req->src || !sk_req->dst ||
20147b44c0eeSKai Ye 		     sk_req->cryptlen > MAX_INPUT_DATA_LEN)) {
2015416d8220SZaibo Xu 		dev_err(dev, "skcipher input param error!\n");
2016416d8220SZaibo Xu 		return -EINVAL;
2017416d8220SZaibo Xu 	}
2018d6de2a59SZaibo Xu 	sreq->c_req.c_len = sk_req->cryptlen;
201974b58db8SLongfang Liu 
202074b58db8SLongfang Liu 	if (ctx->pbuf_supported && sk_req->cryptlen <= SEC_PBUF_SZ)
202174b58db8SLongfang Liu 		sreq->use_pbuf = true;
202274b58db8SLongfang Liu 	else
202374b58db8SLongfang Liu 		sreq->use_pbuf = false;
202474b58db8SLongfang Liu 
2025416d8220SZaibo Xu 	if (c_alg == SEC_CALG_3DES) {
2026b9c8d897SZaibo Xu 		if (unlikely(sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1))) {
2027416d8220SZaibo Xu 			dev_err(dev, "skcipher 3des input length error!\n");
2028416d8220SZaibo Xu 			return -EINVAL;
2029416d8220SZaibo Xu 		}
2030416d8220SZaibo Xu 		return 0;
2031416d8220SZaibo Xu 	} else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) {
2032059c5342SLongfang Liu 		return sec_skcipher_cryptlen_ckeck(ctx, sreq);
2033416d8220SZaibo Xu 	}
2034059c5342SLongfang Liu 
2035416d8220SZaibo Xu 	dev_err(dev, "skcipher algorithm error!\n");
2036633e507fSLongfang Liu 
2037416d8220SZaibo Xu 	return -EINVAL;
2038416d8220SZaibo Xu }
2039416d8220SZaibo Xu 
20405652d55aSKai Ye static int sec_skcipher_soft_crypto(struct sec_ctx *ctx,
20415652d55aSKai Ye 				    struct skcipher_request *sreq, bool encrypt)
20425652d55aSKai Ye {
20435652d55aSKai Ye 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
2044e764d81dSKai Ye 	SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, c_ctx->fbtfm);
20455652d55aSKai Ye 	struct device *dev = ctx->dev;
20465652d55aSKai Ye 	int ret;
20475652d55aSKai Ye 
20485652d55aSKai Ye 	if (!c_ctx->fbtfm) {
2049e764d81dSKai Ye 		dev_err_ratelimited(dev, "the soft tfm isn't supported in the current system.\n");
20505652d55aSKai Ye 		return -EINVAL;
20515652d55aSKai Ye 	}
20525652d55aSKai Ye 
20535652d55aSKai Ye 	skcipher_request_set_sync_tfm(subreq, c_ctx->fbtfm);
20545652d55aSKai Ye 
20555652d55aSKai Ye 	/* software need sync mode to do crypto */
20565652d55aSKai Ye 	skcipher_request_set_callback(subreq, sreq->base.flags,
20575652d55aSKai Ye 				      NULL, NULL);
20585652d55aSKai Ye 	skcipher_request_set_crypt(subreq, sreq->src, sreq->dst,
20595652d55aSKai Ye 				   sreq->cryptlen, sreq->iv);
20605652d55aSKai Ye 	if (encrypt)
20615652d55aSKai Ye 		ret = crypto_skcipher_encrypt(subreq);
20625652d55aSKai Ye 	else
20635652d55aSKai Ye 		ret = crypto_skcipher_decrypt(subreq);
20645652d55aSKai Ye 
20655652d55aSKai Ye 	skcipher_request_zero(subreq);
20665652d55aSKai Ye 
20675652d55aSKai Ye 	return ret;
20685652d55aSKai Ye }
20695652d55aSKai Ye 
2070416d8220SZaibo Xu static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt)
2071416d8220SZaibo Xu {
2072416d8220SZaibo Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req);
2073416d8220SZaibo Xu 	struct sec_req *req = skcipher_request_ctx(sk_req);
2074416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
2075416d8220SZaibo Xu 	int ret;
2076416d8220SZaibo Xu 
20775652d55aSKai Ye 	if (!sk_req->cryptlen) {
20785652d55aSKai Ye 		if (ctx->c_ctx.c_mode == SEC_CMODE_XTS)
20795652d55aSKai Ye 			return -EINVAL;
2080416d8220SZaibo Xu 		return 0;
20815652d55aSKai Ye 	}
2082416d8220SZaibo Xu 
20839597efc3SKai Ye 	req->flag = sk_req->base.flags;
2084416d8220SZaibo Xu 	req->c_req.sk_req = sk_req;
2085416d8220SZaibo Xu 	req->c_req.encrypt = encrypt;
2086416d8220SZaibo Xu 	req->ctx = ctx;
2087416d8220SZaibo Xu 
2088d6de2a59SZaibo Xu 	ret = sec_skcipher_param_check(ctx, req);
2089d6de2a59SZaibo Xu 	if (unlikely(ret))
2090d6de2a59SZaibo Xu 		return -EINVAL;
2091d6de2a59SZaibo Xu 
20925652d55aSKai Ye 	if (unlikely(ctx->c_ctx.fallback))
20935652d55aSKai Ye 		return sec_skcipher_soft_crypto(ctx, sk_req, encrypt);
20945652d55aSKai Ye 
2095416d8220SZaibo Xu 	return ctx->req_op->process(ctx, req);
2096416d8220SZaibo Xu }
2097416d8220SZaibo Xu 
2098416d8220SZaibo Xu static int sec_skcipher_encrypt(struct skcipher_request *sk_req)
2099416d8220SZaibo Xu {
2100416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, true);
2101416d8220SZaibo Xu }
2102416d8220SZaibo Xu 
2103416d8220SZaibo Xu static int sec_skcipher_decrypt(struct skcipher_request *sk_req)
2104416d8220SZaibo Xu {
2105416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, false);
2106416d8220SZaibo Xu }
2107416d8220SZaibo Xu 
2108416d8220SZaibo Xu #define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \
2109416d8220SZaibo Xu 	sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\
2110416d8220SZaibo Xu {\
2111416d8220SZaibo Xu 	.base = {\
2112416d8220SZaibo Xu 		.cra_name = sec_cra_name,\
2113416d8220SZaibo Xu 		.cra_driver_name = "hisi_sec_"sec_cra_name,\
2114416d8220SZaibo Xu 		.cra_priority = SEC_PRIORITY,\
21155652d55aSKai Ye 		.cra_flags = CRYPTO_ALG_ASYNC |\
21165652d55aSKai Ye 		 CRYPTO_ALG_NEED_FALLBACK,\
2117416d8220SZaibo Xu 		.cra_blocksize = blk_size,\
2118416d8220SZaibo Xu 		.cra_ctxsize = sizeof(struct sec_ctx),\
2119416d8220SZaibo Xu 		.cra_module = THIS_MODULE,\
2120416d8220SZaibo Xu 	},\
2121416d8220SZaibo Xu 	.init = ctx_init,\
2122416d8220SZaibo Xu 	.exit = ctx_exit,\
2123416d8220SZaibo Xu 	.setkey = sec_set_key,\
2124416d8220SZaibo Xu 	.decrypt = sec_skcipher_decrypt,\
2125416d8220SZaibo Xu 	.encrypt = sec_skcipher_encrypt,\
2126416d8220SZaibo Xu 	.min_keysize = sec_min_key_size,\
2127416d8220SZaibo Xu 	.max_keysize = sec_max_key_size,\
2128416d8220SZaibo Xu 	.ivsize = iv_size,\
2129416d8220SZaibo Xu },
2130416d8220SZaibo Xu 
2131416d8220SZaibo Xu #define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \
2132416d8220SZaibo Xu 	max_key_size, blk_size, iv_size) \
2133416d8220SZaibo Xu 	SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \
2134416d8220SZaibo Xu 	sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size)
2135416d8220SZaibo Xu 
2136a181647cSZaibo Xu static struct skcipher_alg sec_skciphers[] = {
2137416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb,
2138416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
2139416d8220SZaibo Xu 			 AES_BLOCK_SIZE, 0)
2140416d8220SZaibo Xu 
2141416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc,
2142416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
2143416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
2144416d8220SZaibo Xu 
2145416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts,
2146416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE,
2147416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
2148416d8220SZaibo Xu 
2149416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb,
21506161f40cSKai Ye 			 SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE,
2151416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, 0)
2152416d8220SZaibo Xu 
2153416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc,
21546161f40cSKai Ye 			 SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE,
2155416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE)
2156416d8220SZaibo Xu 
2157416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,
2158416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE,
2159416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
2160416d8220SZaibo Xu 
2161416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc,
2162416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
2163416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
2164416d8220SZaibo Xu };
2165416d8220SZaibo Xu 
21667b44c0eeSKai Ye static struct skcipher_alg sec_skciphers_v3[] = {
21677b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("ofb(aes)", sec_setkey_aes_ofb,
21687b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
21697b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
21707b44c0eeSKai Ye 
21717b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("cfb(aes)", sec_setkey_aes_cfb,
21727b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
21737b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
21747b44c0eeSKai Ye 
21757b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("ctr(aes)", sec_setkey_aes_ctr,
21767b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
21777b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
21787b44c0eeSKai Ye 
21797b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("ofb(sm4)", sec_setkey_sm4_ofb,
21807b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
21817b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
21827b44c0eeSKai Ye 
21837b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("cfb(sm4)", sec_setkey_sm4_cfb,
21847b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
21857b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
21867b44c0eeSKai Ye 
21877b44c0eeSKai Ye 	SEC_SKCIPHER_ALG("ctr(sm4)", sec_setkey_sm4_ctr,
21887b44c0eeSKai Ye 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
21897b44c0eeSKai Ye 			 SEC_MIN_BLOCK_SZ, AES_BLOCK_SIZE)
21907b44c0eeSKai Ye };
21917b44c0eeSKai Ye 
2192c16a70c1SKai Ye static int aead_iv_demension_check(struct aead_request *aead_req)
2193c16a70c1SKai Ye {
2194c16a70c1SKai Ye 	u8 cl;
2195c16a70c1SKai Ye 
2196c16a70c1SKai Ye 	cl = aead_req->iv[0] + 1;
2197c16a70c1SKai Ye 	if (cl < IV_CL_MIN || cl > IV_CL_MAX)
2198c16a70c1SKai Ye 		return -EINVAL;
2199c16a70c1SKai Ye 
2200c16a70c1SKai Ye 	if (cl < IV_CL_MID && aead_req->cryptlen >> (BYTE_BITS * cl))
2201c16a70c1SKai Ye 		return -EOVERFLOW;
2202c16a70c1SKai Ye 
2203c16a70c1SKai Ye 	return 0;
2204c16a70c1SKai Ye }
2205c16a70c1SKai Ye 
2206c16a70c1SKai Ye static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq)
2207c16a70c1SKai Ye {
2208c16a70c1SKai Ye 	struct aead_request *req = sreq->aead_req.aead_req;
2209c16a70c1SKai Ye 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
2210c16a70c1SKai Ye 	size_t authsize = crypto_aead_authsize(tfm);
2211c16a70c1SKai Ye 	u8 c_mode = ctx->c_ctx.c_mode;
2212c16a70c1SKai Ye 	struct device *dev = ctx->dev;
2213c16a70c1SKai Ye 	int ret;
2214c16a70c1SKai Ye 
2215c16a70c1SKai Ye 	if (unlikely(req->cryptlen + req->assoclen > MAX_INPUT_DATA_LEN ||
2216c16a70c1SKai Ye 	    req->assoclen > SEC_MAX_AAD_LEN)) {
2217c16a70c1SKai Ye 		dev_err(dev, "aead input spec error!\n");
2218c16a70c1SKai Ye 		return -EINVAL;
2219c16a70c1SKai Ye 	}
2220c16a70c1SKai Ye 
2221c16a70c1SKai Ye 	if (unlikely((c_mode == SEC_CMODE_GCM && authsize < DES_BLOCK_SIZE) ||
2222c16a70c1SKai Ye 	   (c_mode == SEC_CMODE_CCM && (authsize < MIN_MAC_LEN ||
2223c16a70c1SKai Ye 		authsize & MAC_LEN_MASK)))) {
2224c16a70c1SKai Ye 		dev_err(dev, "aead input mac length error!\n");
2225c16a70c1SKai Ye 		return -EINVAL;
2226c16a70c1SKai Ye 	}
2227c16a70c1SKai Ye 
2228c16a70c1SKai Ye 	if (c_mode == SEC_CMODE_CCM) {
22295e340558SKai Ye 		if (unlikely(req->assoclen > SEC_MAX_CCM_AAD_LEN)) {
22305e340558SKai Ye 			dev_err_ratelimited(dev, "CCM input aad parameter is too long!\n");
22315e340558SKai Ye 			return -EINVAL;
22325e340558SKai Ye 		}
2233c16a70c1SKai Ye 		ret = aead_iv_demension_check(req);
2234c16a70c1SKai Ye 		if (ret) {
2235c16a70c1SKai Ye 			dev_err(dev, "aead input iv param error!\n");
2236c16a70c1SKai Ye 			return ret;
2237c16a70c1SKai Ye 		}
2238c16a70c1SKai Ye 	}
2239c16a70c1SKai Ye 
2240c16a70c1SKai Ye 	if (sreq->c_req.encrypt)
2241c16a70c1SKai Ye 		sreq->c_req.c_len = req->cryptlen;
2242c16a70c1SKai Ye 	else
2243c16a70c1SKai Ye 		sreq->c_req.c_len = req->cryptlen - authsize;
2244c16a70c1SKai Ye 	if (c_mode == SEC_CMODE_CBC) {
2245c16a70c1SKai Ye 		if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) {
2246c16a70c1SKai Ye 			dev_err(dev, "aead crypto length error!\n");
2247c16a70c1SKai Ye 			return -EINVAL;
2248c16a70c1SKai Ye 		}
2249c16a70c1SKai Ye 	}
2250c16a70c1SKai Ye 
2251c16a70c1SKai Ye 	return 0;
2252c16a70c1SKai Ye }
2253c16a70c1SKai Ye 
22542f072d75SZaibo Xu static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
22552f072d75SZaibo Xu {
22562f072d75SZaibo Xu 	struct aead_request *req = sreq->aead_req.aead_req;
22572f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
22582f072d75SZaibo Xu 	size_t authsize = crypto_aead_authsize(tfm);
2259a44dce50SLongfang Liu 	struct device *dev = ctx->dev;
2260a44dce50SLongfang Liu 	u8 c_alg = ctx->c_ctx.c_alg;
22612f072d75SZaibo Xu 
2262c16a70c1SKai Ye 	if (unlikely(!req->src || !req->dst)) {
2263a44dce50SLongfang Liu 		dev_err(dev, "aead input param error!\n");
22642f072d75SZaibo Xu 		return -EINVAL;
22652f072d75SZaibo Xu 	}
22662f072d75SZaibo Xu 
2267c16a70c1SKai Ye 	if (ctx->sec->qm.ver == QM_HW_V2) {
2268c16a70c1SKai Ye 		if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt &&
2269c16a70c1SKai Ye 		    req->cryptlen <= authsize))) {
22706c46a329SKai Ye 			ctx->a_ctx.fallback = true;
2271c16a70c1SKai Ye 			return -EINVAL;
2272c16a70c1SKai Ye 		}
2273c16a70c1SKai Ye 	}
2274c16a70c1SKai Ye 
2275c16a70c1SKai Ye 	/* Support AES or SM4 */
2276c16a70c1SKai Ye 	if (unlikely(c_alg != SEC_CALG_AES && c_alg != SEC_CALG_SM4)) {
2277c16a70c1SKai Ye 		dev_err(dev, "aead crypto alg error!\n");
2278c16a70c1SKai Ye 		return -EINVAL;
2279c16a70c1SKai Ye 	}
2280c16a70c1SKai Ye 
2281c16a70c1SKai Ye 	if (unlikely(sec_aead_spec_check(ctx, sreq)))
2282c16a70c1SKai Ye 		return -EINVAL;
2283c16a70c1SKai Ye 
228474b58db8SLongfang Liu 	if (ctx->pbuf_supported && (req->cryptlen + req->assoclen) <=
228574b58db8SLongfang Liu 		SEC_PBUF_SZ)
228674b58db8SLongfang Liu 		sreq->use_pbuf = true;
228774b58db8SLongfang Liu 	else
228874b58db8SLongfang Liu 		sreq->use_pbuf = false;
228974b58db8SLongfang Liu 
22902f072d75SZaibo Xu 	return 0;
22912f072d75SZaibo Xu }
22922f072d75SZaibo Xu 
22936c46a329SKai Ye static int sec_aead_soft_crypto(struct sec_ctx *ctx,
22946c46a329SKai Ye 				struct aead_request *aead_req,
22956c46a329SKai Ye 				bool encrypt)
22966c46a329SKai Ye {
22976c46a329SKai Ye 	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
22986c46a329SKai Ye 	struct device *dev = ctx->dev;
22990a2a464fSKai Ye 	struct aead_request *subreq;
23000a2a464fSKai Ye 	int ret;
23016c46a329SKai Ye 
23026c46a329SKai Ye 	/* Kunpeng920 aead mode not support input 0 size */
23036c46a329SKai Ye 	if (!a_ctx->fallback_aead_tfm) {
230484c2c729SColin Ian King 		dev_err(dev, "aead fallback tfm is NULL!\n");
23056c46a329SKai Ye 		return -EINVAL;
23066c46a329SKai Ye 	}
23076c46a329SKai Ye 
23080a2a464fSKai Ye 	subreq = aead_request_alloc(a_ctx->fallback_aead_tfm, GFP_KERNEL);
23090a2a464fSKai Ye 	if (!subreq)
23100a2a464fSKai Ye 		return -ENOMEM;
23110a2a464fSKai Ye 
23126c46a329SKai Ye 	aead_request_set_tfm(subreq, a_ctx->fallback_aead_tfm);
23136c46a329SKai Ye 	aead_request_set_callback(subreq, aead_req->base.flags,
23146c46a329SKai Ye 				  aead_req->base.complete, aead_req->base.data);
23156c46a329SKai Ye 	aead_request_set_crypt(subreq, aead_req->src, aead_req->dst,
23166c46a329SKai Ye 			       aead_req->cryptlen, aead_req->iv);
23176c46a329SKai Ye 	aead_request_set_ad(subreq, aead_req->assoclen);
23186c46a329SKai Ye 
23190a2a464fSKai Ye 	if (encrypt)
23200a2a464fSKai Ye 		ret = crypto_aead_encrypt(subreq);
23210a2a464fSKai Ye 	else
23220a2a464fSKai Ye 		ret = crypto_aead_decrypt(subreq);
23230a2a464fSKai Ye 	aead_request_free(subreq);
23240a2a464fSKai Ye 
23250a2a464fSKai Ye 	return ret;
23266c46a329SKai Ye }
23276c46a329SKai Ye 
23282f072d75SZaibo Xu static int sec_aead_crypto(struct aead_request *a_req, bool encrypt)
23292f072d75SZaibo Xu {
23302f072d75SZaibo Xu 	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
23312f072d75SZaibo Xu 	struct sec_req *req = aead_request_ctx(a_req);
23322f072d75SZaibo Xu 	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
23332f072d75SZaibo Xu 	int ret;
23342f072d75SZaibo Xu 
23359597efc3SKai Ye 	req->flag = a_req->base.flags;
23362f072d75SZaibo Xu 	req->aead_req.aead_req = a_req;
23372f072d75SZaibo Xu 	req->c_req.encrypt = encrypt;
23382f072d75SZaibo Xu 	req->ctx = ctx;
23392f072d75SZaibo Xu 
23402f072d75SZaibo Xu 	ret = sec_aead_param_check(ctx, req);
23416c46a329SKai Ye 	if (unlikely(ret)) {
23426c46a329SKai Ye 		if (ctx->a_ctx.fallback)
23436c46a329SKai Ye 			return sec_aead_soft_crypto(ctx, a_req, encrypt);
23442f072d75SZaibo Xu 		return -EINVAL;
23456c46a329SKai Ye 	}
23462f072d75SZaibo Xu 
23472f072d75SZaibo Xu 	return ctx->req_op->process(ctx, req);
23482f072d75SZaibo Xu }
23492f072d75SZaibo Xu 
23502f072d75SZaibo Xu static int sec_aead_encrypt(struct aead_request *a_req)
23512f072d75SZaibo Xu {
23522f072d75SZaibo Xu 	return sec_aead_crypto(a_req, true);
23532f072d75SZaibo Xu }
23542f072d75SZaibo Xu 
23552f072d75SZaibo Xu static int sec_aead_decrypt(struct aead_request *a_req)
23562f072d75SZaibo Xu {
23572f072d75SZaibo Xu 	return sec_aead_crypto(a_req, false);
23582f072d75SZaibo Xu }
23592f072d75SZaibo Xu 
2360c16a70c1SKai Ye #define SEC_AEAD_ALG(sec_cra_name, sec_set_key, ctx_init,\
23612f072d75SZaibo Xu 			 ctx_exit, blk_size, iv_size, max_authsize)\
23622f072d75SZaibo Xu {\
23632f072d75SZaibo Xu 	.base = {\
23642f072d75SZaibo Xu 		.cra_name = sec_cra_name,\
23652f072d75SZaibo Xu 		.cra_driver_name = "hisi_sec_"sec_cra_name,\
23662f072d75SZaibo Xu 		.cra_priority = SEC_PRIORITY,\
23676c46a329SKai Ye 		.cra_flags = CRYPTO_ALG_ASYNC |\
23686c46a329SKai Ye 		 CRYPTO_ALG_NEED_FALLBACK,\
23692f072d75SZaibo Xu 		.cra_blocksize = blk_size,\
23702f072d75SZaibo Xu 		.cra_ctxsize = sizeof(struct sec_ctx),\
23712f072d75SZaibo Xu 		.cra_module = THIS_MODULE,\
23722f072d75SZaibo Xu 	},\
23732f072d75SZaibo Xu 	.init = ctx_init,\
23742f072d75SZaibo Xu 	.exit = ctx_exit,\
23752f072d75SZaibo Xu 	.setkey = sec_set_key,\
23766c46a329SKai Ye 	.setauthsize = sec_aead_setauthsize,\
23772f072d75SZaibo Xu 	.decrypt = sec_aead_decrypt,\
23782f072d75SZaibo Xu 	.encrypt = sec_aead_encrypt,\
23792f072d75SZaibo Xu 	.ivsize = iv_size,\
23802f072d75SZaibo Xu 	.maxauthsize = max_authsize,\
23812f072d75SZaibo Xu }
23822f072d75SZaibo Xu 
23832f072d75SZaibo Xu static struct aead_alg sec_aeads[] = {
23842f072d75SZaibo Xu 	SEC_AEAD_ALG("authenc(hmac(sha1),cbc(aes))",
23852f072d75SZaibo Xu 		     sec_setkey_aes_cbc_sha1, sec_aead_sha1_ctx_init,
2386c16a70c1SKai Ye 		     sec_aead_ctx_exit, AES_BLOCK_SIZE,
2387c16a70c1SKai Ye 		     AES_BLOCK_SIZE, SHA1_DIGEST_SIZE),
23882f072d75SZaibo Xu 
23892f072d75SZaibo Xu 	SEC_AEAD_ALG("authenc(hmac(sha256),cbc(aes))",
23902f072d75SZaibo Xu 		     sec_setkey_aes_cbc_sha256, sec_aead_sha256_ctx_init,
2391c16a70c1SKai Ye 		     sec_aead_ctx_exit, AES_BLOCK_SIZE,
2392c16a70c1SKai Ye 		     AES_BLOCK_SIZE, SHA256_DIGEST_SIZE),
23932f072d75SZaibo Xu 
23942f072d75SZaibo Xu 	SEC_AEAD_ALG("authenc(hmac(sha512),cbc(aes))",
23952f072d75SZaibo Xu 		     sec_setkey_aes_cbc_sha512, sec_aead_sha512_ctx_init,
2396c16a70c1SKai Ye 		     sec_aead_ctx_exit, AES_BLOCK_SIZE,
2397c16a70c1SKai Ye 		     AES_BLOCK_SIZE, SHA512_DIGEST_SIZE),
2398c16a70c1SKai Ye 
2399c16a70c1SKai Ye 	SEC_AEAD_ALG("ccm(aes)", sec_setkey_aes_ccm, sec_aead_xcm_ctx_init,
2400c16a70c1SKai Ye 		     sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ,
2401c16a70c1SKai Ye 		     AES_BLOCK_SIZE, AES_BLOCK_SIZE),
2402c16a70c1SKai Ye 
2403c16a70c1SKai Ye 	SEC_AEAD_ALG("gcm(aes)", sec_setkey_aes_gcm, sec_aead_xcm_ctx_init,
2404c16a70c1SKai Ye 		     sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ,
2405c16a70c1SKai Ye 		     SEC_AIV_SIZE, AES_BLOCK_SIZE)
2406c16a70c1SKai Ye };
2407c16a70c1SKai Ye 
2408c16a70c1SKai Ye static struct aead_alg sec_aeads_v3[] = {
2409c16a70c1SKai Ye 	SEC_AEAD_ALG("ccm(sm4)", sec_setkey_sm4_ccm, sec_aead_xcm_ctx_init,
2410c16a70c1SKai Ye 		     sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ,
2411c16a70c1SKai Ye 		     AES_BLOCK_SIZE, AES_BLOCK_SIZE),
2412c16a70c1SKai Ye 
2413c16a70c1SKai Ye 	SEC_AEAD_ALG("gcm(sm4)", sec_setkey_sm4_gcm, sec_aead_xcm_ctx_init,
2414c16a70c1SKai Ye 		     sec_aead_xcm_ctx_exit, SEC_MIN_BLOCK_SZ,
2415c16a70c1SKai Ye 		     SEC_AIV_SIZE, AES_BLOCK_SIZE)
24162f072d75SZaibo Xu };
24172f072d75SZaibo Xu 
24188123455aSMeng Yu int sec_register_to_crypto(struct hisi_qm *qm)
2419416d8220SZaibo Xu {
24203d29e98dSYang Shen 	int ret;
2421416d8220SZaibo Xu 
2422416d8220SZaibo Xu 	/* To avoid repeat register */
2423a181647cSZaibo Xu 	ret = crypto_register_skciphers(sec_skciphers,
2424a181647cSZaibo Xu 					ARRAY_SIZE(sec_skciphers));
24252f072d75SZaibo Xu 	if (ret)
24262f072d75SZaibo Xu 		return ret;
24272f072d75SZaibo Xu 
24287b44c0eeSKai Ye 	if (qm->ver > QM_HW_V2) {
24297b44c0eeSKai Ye 		ret = crypto_register_skciphers(sec_skciphers_v3,
24307b44c0eeSKai Ye 						ARRAY_SIZE(sec_skciphers_v3));
24317b44c0eeSKai Ye 		if (ret)
24327b44c0eeSKai Ye 			goto reg_skcipher_fail;
24337b44c0eeSKai Ye 	}
2434c16a70c1SKai Ye 
24352f072d75SZaibo Xu 	ret = crypto_register_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
24362f072d75SZaibo Xu 	if (ret)
24377b44c0eeSKai Ye 		goto reg_aead_fail;
2438c16a70c1SKai Ye 	if (qm->ver > QM_HW_V2) {
2439c16a70c1SKai Ye 		ret = crypto_register_aeads(sec_aeads_v3, ARRAY_SIZE(sec_aeads_v3));
2440c16a70c1SKai Ye 		if (ret)
2441c16a70c1SKai Ye 			goto reg_aead_v3_fail;
2442c16a70c1SKai Ye 	}
24437b44c0eeSKai Ye 	return ret;
24447b44c0eeSKai Ye 
2445c16a70c1SKai Ye reg_aead_v3_fail:
2446c16a70c1SKai Ye 	crypto_unregister_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
24477b44c0eeSKai Ye reg_aead_fail:
24487b44c0eeSKai Ye 	if (qm->ver > QM_HW_V2)
24497b44c0eeSKai Ye 		crypto_unregister_skciphers(sec_skciphers_v3,
24507b44c0eeSKai Ye 					    ARRAY_SIZE(sec_skciphers_v3));
24517b44c0eeSKai Ye reg_skcipher_fail:
24523d29e98dSYang Shen 	crypto_unregister_skciphers(sec_skciphers,
24533d29e98dSYang Shen 				    ARRAY_SIZE(sec_skciphers));
2454416d8220SZaibo Xu 	return ret;
2455416d8220SZaibo Xu }
2456416d8220SZaibo Xu 
24578123455aSMeng Yu void sec_unregister_from_crypto(struct hisi_qm *qm)
2458416d8220SZaibo Xu {
24597b44c0eeSKai Ye 	if (qm->ver > QM_HW_V2)
2460c16a70c1SKai Ye 		crypto_unregister_aeads(sec_aeads_v3,
2461c16a70c1SKai Ye 					ARRAY_SIZE(sec_aeads_v3));
2462c16a70c1SKai Ye 	crypto_unregister_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
2463c16a70c1SKai Ye 
2464c16a70c1SKai Ye 	if (qm->ver > QM_HW_V2)
24657b44c0eeSKai Ye 		crypto_unregister_skciphers(sec_skciphers_v3,
24667b44c0eeSKai Ye 					    ARRAY_SIZE(sec_skciphers_v3));
2467a181647cSZaibo Xu 	crypto_unregister_skciphers(sec_skciphers,
2468a181647cSZaibo Xu 				    ARRAY_SIZE(sec_skciphers));
24692f072d75SZaibo Xu }
2470