xref: /optee_os/core/drivers/crypto/hisilicon/sec_authenc.c (revision 0c05871e02644e1f1f326d8c961eb8ab27e7e6dd)
1*0c05871eSleisen // SPDX-License-Identifier: BSD-2-Clause
2*0c05871eSleisen /*
3*0c05871eSleisen  * Copyright 2022-2024 HiSilicon Limited.
4*0c05871eSleisen  * Kunpeng hardware accelerator sec authenc algorithm implementation.
5*0c05871eSleisen  */
6*0c05871eSleisen 
7*0c05871eSleisen #include <crypto/crypto_impl.h>
8*0c05871eSleisen #include <drvcrypt.h>
9*0c05871eSleisen #include <drvcrypt_authenc.h>
10*0c05871eSleisen #include <initcall.h>
11*0c05871eSleisen #include <tee_api_types.h>
12*0c05871eSleisen #include <trace.h>
13*0c05871eSleisen #include <utee_defines.h>
14*0c05871eSleisen 
15*0c05871eSleisen #include "sec_authenc.h"
16*0c05871eSleisen #include "sec_cipher.h"
17*0c05871eSleisen #include "sec_hash.h"
18*0c05871eSleisen #include "sec_main.h"
19*0c05871eSleisen 
sec_aead_bd_fill(void * bd,void * msg)20*0c05871eSleisen static enum hisi_drv_status sec_aead_bd_fill(void *bd, void *msg)
21*0c05871eSleisen {
22*0c05871eSleisen 	struct authenc_ctx *ae_ctx = msg;
23*0c05871eSleisen 	struct hisi_sec_sqe *sqe = bd;
24*0c05871eSleisen 	uint8_t scene = 0;
25*0c05871eSleisen 	uint8_t de = 0;
26*0c05871eSleisen 
27*0c05871eSleisen 	sqe->type_auth_cipher = BD_TYPE2 | SHIFT_U32(NO_AUTH, SEC_AUTH_OFFSET);
28*0c05871eSleisen 	scene = SHIFT_U32(SCENE_NOTHING, SEC_SCENE_OFFSET);
29*0c05871eSleisen 	de = SHIFT_U32(DATA_DST_ADDR_ENABLE, SEC_DE_OFFSET);
30*0c05871eSleisen 	sqe->sds_sa_type = de | scene;
31*0c05871eSleisen 	sqe->type2.cipher_src_offset = ae_ctx->aad.length;
32*0c05871eSleisen 	sqe->type2.icvw_kmode = SHIFT_U32(ae_ctx->c_key_len, SEC_CKEY_OFFSET) |
33*0c05871eSleisen 				SHIFT_U32(ae_ctx->mode, SEC_CMODE_OFFSET) |
34*0c05871eSleisen 				ae_ctx->tag_len;
35*0c05871eSleisen 	sqe->type2.clen_ivhlen = ae_ctx->payload_len;
36*0c05871eSleisen 	sqe->type2.alen_ivllen = ae_ctx->aad.length;
37*0c05871eSleisen 	sqe->type2.c_alg = ae_ctx->algo;
38*0c05871eSleisen 
39*0c05871eSleisen 	if (ae_ctx->encrypt) {
40*0c05871eSleisen 		sqe->type_auth_cipher |= SHIFT_U32(CIPHER_ENCRYPT,
41*0c05871eSleisen 						   SEC_CIPHER_OFFSET);
42*0c05871eSleisen 		sqe->sds_sa_type |= SEC_CIPHER_THEN_DIGEST;
43*0c05871eSleisen 	} else {
44*0c05871eSleisen 		sqe->type_auth_cipher |= SHIFT_U32(CIPHER_DECRYPT,
45*0c05871eSleisen 						   SEC_CIPHER_OFFSET);
46*0c05871eSleisen 		sqe->sds_sa_type |= SEC_DIGEST_THEN_CIPHER;
47*0c05871eSleisen 	}
48*0c05871eSleisen 
49*0c05871eSleisen 	sqe->type2.data_dst_addr = ae_ctx->dst_dma;
50*0c05871eSleisen 	sqe->type2.data_src_addr = ae_ctx->src_dma;
51*0c05871eSleisen 	sqe->type2.c_ivin_addr = ae_ctx->civ_dma;
52*0c05871eSleisen 	sqe->type2.c_key_addr = ae_ctx->key_dma;
53*0c05871eSleisen 	sqe->type2.mac_addr = ae_ctx->tag_dma;
54*0c05871eSleisen 	sqe->type2.a_ivin_addr = ae_ctx->aiv_dma;
55*0c05871eSleisen 
56*0c05871eSleisen 	return HISI_QM_DRVCRYPT_NO_ERR;
57*0c05871eSleisen }
58*0c05871eSleisen 
sec_aead_bd_parse(void * bd,void * msg)59*0c05871eSleisen static enum hisi_drv_status sec_aead_bd_parse(void *bd, void *msg)
60*0c05871eSleisen {
61*0c05871eSleisen 	struct hisi_sec_sqe *sqe = bd;
62*0c05871eSleisen 	struct authenc_ctx *ctx = msg;
63*0c05871eSleisen 	uint16_t done = 0;
64*0c05871eSleisen 
65*0c05871eSleisen 	ctx->result = SEC_GET_FIELD(sqe->type2.done_flag, SEC_ICV_MASK, 1);
66*0c05871eSleisen 	done = SEC_GET_FIELD(sqe->type2.done_flag, SEC_DONE_MASK, 0);
67*0c05871eSleisen 	if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) {
68*0c05871eSleisen 		EMSG("SEC BD2 fail! done=%#"PRIx16", etype=%#"PRIx8,
69*0c05871eSleisen 		     done, sqe->type2.error_type);
70*0c05871eSleisen 		return HISI_QM_DRVCRYPT_IN_EPARA;
71*0c05871eSleisen 	}
72*0c05871eSleisen 
73*0c05871eSleisen 	return HISI_QM_DRVCRYPT_NO_ERR;
74*0c05871eSleisen }
75*0c05871eSleisen 
sec_aead_bd3_fill(void * bd,void * msg)76*0c05871eSleisen static enum hisi_drv_status sec_aead_bd3_fill(void *bd, void *msg)
77*0c05871eSleisen {
78*0c05871eSleisen 	struct authenc_ctx *ae_ctx = msg;
79*0c05871eSleisen 	struct hisi_sec_bd3_sqe *sqe = bd;
80*0c05871eSleisen 
81*0c05871eSleisen 	sqe->bd_param = BD_TYPE3 | SHIFT_U32(SCENE_NOTHING,
82*0c05871eSleisen 					     SEC_SCENE_OFFSET_V3) |
83*0c05871eSleisen 			SHIFT_U32(DATA_DST_ADDR_ENABLE, SEC_DE_OFFSET_V3);
84*0c05871eSleisen 	sqe->auth_mac_key = NO_AUTH;
85*0c05871eSleisen 	sqe->cipher_src_offset = ae_ctx->aad.length;
86*0c05871eSleisen 	sqe->c_icv_key = SHIFT_U32(ae_ctx->c_key_len, SEC_CKEY_OFFSET_V3) |
87*0c05871eSleisen 			 SHIFT_U32(ae_ctx->tag_len, SEC_ICV_LEN_OFFSET_V3);
88*0c05871eSleisen 	sqe->c_len_ivin = ae_ctx->payload_len;
89*0c05871eSleisen 
90*0c05871eSleisen 	sqe->a_len_key = ae_ctx->aad.length;
91*0c05871eSleisen 	sqe->c_mode_alg = ae_ctx->mode |
92*0c05871eSleisen 			  SHIFT_U32(ae_ctx->algo, SEC_CALG_OFFSET_V3);
93*0c05871eSleisen 
94*0c05871eSleisen 	if (ae_ctx->encrypt) {
95*0c05871eSleisen 		sqe->c_icv_key |= CIPHER_ENCRYPT;
96*0c05871eSleisen 		sqe->huk_iv_seq = SHIFT_U32(SEC_CIPHER_THEN_DIGEST,
97*0c05871eSleisen 					    SEC_SEQ_OFFSET_V3);
98*0c05871eSleisen 	} else {
99*0c05871eSleisen 		sqe->c_icv_key |= CIPHER_DECRYPT;
100*0c05871eSleisen 		sqe->huk_iv_seq = SHIFT_U32(SEC_DIGEST_THEN_CIPHER,
101*0c05871eSleisen 					    SEC_SEQ_OFFSET_V3);
102*0c05871eSleisen 	}
103*0c05871eSleisen 
104*0c05871eSleisen 	sqe->no_scene.c_ivin_addr = ae_ctx->civ_dma;
105*0c05871eSleisen 	sqe->data_dst_addr = ae_ctx->dst_dma;
106*0c05871eSleisen 	sqe->data_src_addr = ae_ctx->src_dma;
107*0c05871eSleisen 	sqe->c_key_addr = ae_ctx->key_dma;
108*0c05871eSleisen 	sqe->mac_addr = ae_ctx->tag_dma;
109*0c05871eSleisen 	sqe->a_ivin_addr = ae_ctx->aiv_dma;
110*0c05871eSleisen 
111*0c05871eSleisen 	return HISI_QM_DRVCRYPT_NO_ERR;
112*0c05871eSleisen }
113*0c05871eSleisen 
sec_aead_bd3_parse(void * bd,void * msg)114*0c05871eSleisen static enum hisi_drv_status sec_aead_bd3_parse(void *bd, void *msg)
115*0c05871eSleisen {
116*0c05871eSleisen 	struct hisi_sec_bd3_sqe *sqe = bd;
117*0c05871eSleisen 	struct authenc_ctx *ctx = msg;
118*0c05871eSleisen 	uint16_t done = 0;
119*0c05871eSleisen 
120*0c05871eSleisen 	ctx->result = SEC_GET_FIELD(sqe->done_flag, SEC_ICV_MASK, 1);
121*0c05871eSleisen 	done = SEC_GET_FIELD(sqe->done_flag, SEC_DONE_MASK, 0);
122*0c05871eSleisen 	if (done != SEC_HW_TASK_DONE || sqe->error_type) {
123*0c05871eSleisen 		EMSG("SEC BD3 fail! done=%#"PRIx16", etype=%#"PRIx8,
124*0c05871eSleisen 		     done, sqe->error_type);
125*0c05871eSleisen 		return HISI_QM_DRVCRYPT_IN_EPARA;
126*0c05871eSleisen 	}
127*0c05871eSleisen 
128*0c05871eSleisen 	return HISI_QM_DRVCRYPT_NO_ERR;
129*0c05871eSleisen }
130*0c05871eSleisen 
sec_do_aead_task(struct hisi_qp * qp,void * msg)131*0c05871eSleisen static TEE_Result sec_do_aead_task(struct hisi_qp *qp, void *msg)
132*0c05871eSleisen {
133*0c05871eSleisen 	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
134*0c05871eSleisen 
135*0c05871eSleisen 	ret = hisi_qp_send(qp, msg);
136*0c05871eSleisen 	if (ret) {
137*0c05871eSleisen 		EMSG("Fail to send task, ret=%d", ret);
138*0c05871eSleisen 		return TEE_ERROR_BAD_STATE;
139*0c05871eSleisen 	}
140*0c05871eSleisen 
141*0c05871eSleisen 	ret = hisi_qp_recv_sync(qp, msg);
142*0c05871eSleisen 	if (ret) {
143*0c05871eSleisen 		EMSG("Recv task error, ret=%d", ret);
144*0c05871eSleisen 		return TEE_ERROR_BAD_STATE;
145*0c05871eSleisen 	}
146*0c05871eSleisen 
147*0c05871eSleisen 	return TEE_SUCCESS;
148*0c05871eSleisen }
149*0c05871eSleisen 
authenc_algo_check(uint32_t algo)150*0c05871eSleisen static TEE_Result authenc_algo_check(uint32_t algo)
151*0c05871eSleisen {
152*0c05871eSleisen 	switch (algo) {
153*0c05871eSleisen 	case TEE_ALG_AES_GCM:
154*0c05871eSleisen 	case TEE_ALG_AES_CCM:
155*0c05871eSleisen 		return TEE_SUCCESS;
156*0c05871eSleisen 	default:
157*0c05871eSleisen 		return TEE_ERROR_NOT_IMPLEMENTED;
158*0c05871eSleisen 	}
159*0c05871eSleisen }
160*0c05871eSleisen 
crypto_set_alg(uint32_t alg)161*0c05871eSleisen static uint8_t crypto_set_alg(uint32_t alg)
162*0c05871eSleisen {
163*0c05871eSleisen 	switch (alg) {
164*0c05871eSleisen 	case TEE_MAIN_ALGO_AES:
165*0c05871eSleisen 		return C_ALG_AES;
166*0c05871eSleisen 	default:
167*0c05871eSleisen 		return 0;
168*0c05871eSleisen 	}
169*0c05871eSleisen }
170*0c05871eSleisen 
crypto_set_mode(uint32_t mode)171*0c05871eSleisen static uint8_t crypto_set_mode(uint32_t mode)
172*0c05871eSleisen {
173*0c05871eSleisen 	switch (mode) {
174*0c05871eSleisen 	case TEE_CHAIN_MODE_CCM:
175*0c05871eSleisen 		return C_MODE_CCM;
176*0c05871eSleisen 	case TEE_CHAIN_MODE_GCM:
177*0c05871eSleisen 		return C_MODE_GCM;
178*0c05871eSleisen 	default:
179*0c05871eSleisen 		return 0;
180*0c05871eSleisen 	}
181*0c05871eSleisen }
182*0c05871eSleisen 
sec_authenc_ctx_allocate(void ** ctx,uint32_t algo)183*0c05871eSleisen static TEE_Result sec_authenc_ctx_allocate(void **ctx, uint32_t algo)
184*0c05871eSleisen {
185*0c05871eSleisen 	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
186*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = NULL;
187*0c05871eSleisen 	TEE_Result ret = TEE_SUCCESS;
188*0c05871eSleisen 
189*0c05871eSleisen 	if (!ctx) {
190*0c05871eSleisen 		EMSG("ctx is NULL");
191*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
192*0c05871eSleisen 	}
193*0c05871eSleisen 
194*0c05871eSleisen 	ret = authenc_algo_check(algo);
195*0c05871eSleisen 	if (ret)
196*0c05871eSleisen 		return ret;
197*0c05871eSleisen 
198*0c05871eSleisen 	ae_drv_ctx = calloc(1, sizeof(struct authenc_ctx));
199*0c05871eSleisen 	if (!ae_drv_ctx) {
200*0c05871eSleisen 		EMSG("Fail to calloc ae_drv_ctx");
201*0c05871eSleisen 		return TEE_ERROR_OUT_OF_MEMORY;
202*0c05871eSleisen 	}
203*0c05871eSleisen 
204*0c05871eSleisen 	ae_drv_ctx->algo = crypto_set_alg(TEE_ALG_GET_MAIN_ALG(algo));
205*0c05871eSleisen 	ae_drv_ctx->mode = crypto_set_mode(TEE_ALG_GET_CHAIN_MODE(algo));
206*0c05871eSleisen 
207*0c05871eSleisen 	ret = crypto_aes_gcm_alloc_ctx(&ae_soft_ctx);
208*0c05871eSleisen 	if (ret) {
209*0c05871eSleisen 		EMSG("soft ctx is NULL");
210*0c05871eSleisen 		goto free_ctx;
211*0c05871eSleisen 	}
212*0c05871eSleisen 
213*0c05871eSleisen 	ae_drv_ctx->ae_soft_ctx = ae_soft_ctx;
214*0c05871eSleisen 	ae_drv_ctx->is_hw_supported = true;
215*0c05871eSleisen 
216*0c05871eSleisen 	ae_drv_ctx->qp = sec_create_qp(HISI_QM_CHANNEL_TYPE0);
217*0c05871eSleisen 	if (!ae_drv_ctx->qp) {
218*0c05871eSleisen 		ret = TEE_ERROR_BUSY;
219*0c05871eSleisen 		goto free_soft_ctx;
220*0c05871eSleisen 	}
221*0c05871eSleisen 
222*0c05871eSleisen 	if (ae_drv_ctx->qp->qm->version == HISI_QM_HW_V2) {
223*0c05871eSleisen 		ae_drv_ctx->qp->fill_sqe = sec_aead_bd_fill;
224*0c05871eSleisen 		ae_drv_ctx->qp->parse_sqe = sec_aead_bd_parse;
225*0c05871eSleisen 	} else {
226*0c05871eSleisen 		ae_drv_ctx->qp->fill_sqe = sec_aead_bd3_fill;
227*0c05871eSleisen 		ae_drv_ctx->qp->parse_sqe = sec_aead_bd3_parse;
228*0c05871eSleisen 	}
229*0c05871eSleisen 
230*0c05871eSleisen 	*ctx = ae_drv_ctx;
231*0c05871eSleisen 
232*0c05871eSleisen 	return TEE_SUCCESS;
233*0c05871eSleisen 
234*0c05871eSleisen free_soft_ctx:
235*0c05871eSleisen 	ae_soft_ctx->ops->free_ctx(ae_soft_ctx);
236*0c05871eSleisen free_ctx:
237*0c05871eSleisen 	free(ae_drv_ctx);
238*0c05871eSleisen 	return ret;
239*0c05871eSleisen }
240*0c05871eSleisen 
sec_authenc_ctx_free(void * ctx)241*0c05871eSleisen static void sec_authenc_ctx_free(void *ctx)
242*0c05871eSleisen {
243*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = ctx;
244*0c05871eSleisen 
245*0c05871eSleisen 	if (!ae_drv_ctx)
246*0c05871eSleisen 		return;
247*0c05871eSleisen 
248*0c05871eSleisen 	ae_drv_ctx->ae_soft_ctx->ops->free_ctx(ae_drv_ctx->ae_soft_ctx);
249*0c05871eSleisen 
250*0c05871eSleisen 	hisi_qm_release_qp(ae_drv_ctx->qp);
251*0c05871eSleisen 	memzero_explicit(ae_drv_ctx->key, ae_drv_ctx->key_len);
252*0c05871eSleisen 
253*0c05871eSleisen 	if (ae_drv_ctx->src.data) {
254*0c05871eSleisen 		free(ae_drv_ctx->src.data);
255*0c05871eSleisen 		ae_drv_ctx->src.data = NULL;
256*0c05871eSleisen 	}
257*0c05871eSleisen 
258*0c05871eSleisen 	if (ae_drv_ctx->dst.data) {
259*0c05871eSleisen 		free(ae_drv_ctx->dst.data);
260*0c05871eSleisen 		ae_drv_ctx->dst.data = NULL;
261*0c05871eSleisen 	}
262*0c05871eSleisen 
263*0c05871eSleisen 	free(ae_drv_ctx);
264*0c05871eSleisen }
265*0c05871eSleisen 
authenc_init_params_check(struct drvcrypt_authenc_init * dinit)266*0c05871eSleisen static TEE_Result authenc_init_params_check(struct drvcrypt_authenc_init *dinit)
267*0c05871eSleisen {
268*0c05871eSleisen 	if (!dinit) {
269*0c05871eSleisen 		EMSG("dinit is NULL");
270*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
271*0c05871eSleisen 	}
272*0c05871eSleisen 
273*0c05871eSleisen 	if (!dinit->ctx) {
274*0c05871eSleisen 		EMSG("ctx is NULL");
275*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
276*0c05871eSleisen 	}
277*0c05871eSleisen 
278*0c05871eSleisen 	if (!dinit->key.length || !dinit->key.data) {
279*0c05871eSleisen 		EMSG("key is NULL");
280*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
281*0c05871eSleisen 	}
282*0c05871eSleisen 
283*0c05871eSleisen 	if (!dinit->nonce.data || !dinit->nonce.length) {
284*0c05871eSleisen 		EMSG("iv is NULL");
285*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
286*0c05871eSleisen 	}
287*0c05871eSleisen 
288*0c05871eSleisen 	return TEE_SUCCESS;
289*0c05871eSleisen }
290*0c05871eSleisen 
is_hw_supported(struct drvcrypt_authenc_init * dinit)291*0c05871eSleisen static bool is_hw_supported(struct drvcrypt_authenc_init *dinit)
292*0c05871eSleisen {
293*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = dinit->ctx;
294*0c05871eSleisen 
295*0c05871eSleisen 	if (ae_drv_ctx->mode == C_MODE_GCM) {
296*0c05871eSleisen 		if (dinit->nonce.length != GCM_IV_SIZE)
297*0c05871eSleisen 			return false;
298*0c05871eSleisen 
299*0c05871eSleisen 		if (dinit->aad_len > MAX_GCM_AAD_SIZE) {
300*0c05871eSleisen 			EMSG("Invalid aad len");
301*0c05871eSleisen 			return false;
302*0c05871eSleisen 		}
303*0c05871eSleisen 
304*0c05871eSleisen 		if (dinit->tag_len < SEC_MIN_GCM_TAG_LEN ||
305*0c05871eSleisen 		    dinit->tag_len > SEC_MAX_TAG_LEN) {
306*0c05871eSleisen 			EMSG("Invalid tag len");
307*0c05871eSleisen 			return false;
308*0c05871eSleisen 		}
309*0c05871eSleisen 	} else {
310*0c05871eSleisen 		if (dinit->nonce.length < MIN_CCM_NONCE_SIZE ||
311*0c05871eSleisen 		    dinit->nonce.length > MAX_CCM_NONCE_SIZE) {
312*0c05871eSleisen 			EMSG("Invalid nonce len");
313*0c05871eSleisen 			return false;
314*0c05871eSleisen 		}
315*0c05871eSleisen 
316*0c05871eSleisen 		if (dinit->aad_len > MAX_CCM_AAD_SIZE) {
317*0c05871eSleisen 			EMSG("Invalid aad len");
318*0c05871eSleisen 			return false;
319*0c05871eSleisen 		}
320*0c05871eSleisen 
321*0c05871eSleisen 		if (dinit->tag_len < SEC_MIN_CCM_TAG_LEN ||
322*0c05871eSleisen 		    dinit->tag_len > SEC_MAX_TAG_LEN ||
323*0c05871eSleisen 		    dinit->tag_len % TAG_ALIGN) {
324*0c05871eSleisen 			EMSG("Invalid tag len");
325*0c05871eSleisen 			return false;
326*0c05871eSleisen 		}
327*0c05871eSleisen 	}
328*0c05871eSleisen 
329*0c05871eSleisen 	if (dinit->payload_len + dinit->aad_len > SEC_MAX_AEAD_LENGTH ||
330*0c05871eSleisen 	    (ae_drv_ctx->qp->qm->version == HISI_QM_HW_V2 &&
331*0c05871eSleisen 	    dinit->payload_len == 0)) {
332*0c05871eSleisen 		EMSG("Invalid src len");
333*0c05871eSleisen 		return false;
334*0c05871eSleisen 	}
335*0c05871eSleisen 
336*0c05871eSleisen 	return true;
337*0c05871eSleisen }
338*0c05871eSleisen 
sec_aead_set_key(struct drvcrypt_authenc_init * dinit)339*0c05871eSleisen static TEE_Result sec_aead_set_key(struct drvcrypt_authenc_init *dinit)
340*0c05871eSleisen {
341*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = dinit->ctx;
342*0c05871eSleisen 
343*0c05871eSleisen 	ae_drv_ctx->key_len = dinit->key.length;
344*0c05871eSleisen 
345*0c05871eSleisen 	switch (ae_drv_ctx->key_len) {
346*0c05871eSleisen 	case AES_KEYSIZE_128:
347*0c05871eSleisen 		ae_drv_ctx->c_key_len = CKEY_LEN_128_BIT;
348*0c05871eSleisen 		break;
349*0c05871eSleisen 	case AES_KEYSIZE_192:
350*0c05871eSleisen 		ae_drv_ctx->c_key_len = CKEY_LEN_192_BIT;
351*0c05871eSleisen 		break;
352*0c05871eSleisen 	case AES_KEYSIZE_256:
353*0c05871eSleisen 		ae_drv_ctx->c_key_len = CKEY_LEN_256_BIT;
354*0c05871eSleisen 		break;
355*0c05871eSleisen 	default:
356*0c05871eSleisen 		EMSG("Invalid AES key size");
357*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
358*0c05871eSleisen 	}
359*0c05871eSleisen 
360*0c05871eSleisen 	memcpy(ae_drv_ctx->key, dinit->key.data, dinit->key.length);
361*0c05871eSleisen 
362*0c05871eSleisen 	return TEE_SUCCESS;
363*0c05871eSleisen }
364*0c05871eSleisen 
sec_aead_set_iv(struct drvcrypt_authenc_init * dinit)365*0c05871eSleisen static TEE_Result sec_aead_set_iv(struct drvcrypt_authenc_init *dinit)
366*0c05871eSleisen {
367*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = dinit->ctx;
368*0c05871eSleisen 	uint32_t data_size = dinit->payload_len;
369*0c05871eSleisen 	uint8_t adata = 0;
370*0c05871eSleisen 	uint8_t flags = 0;
371*0c05871eSleisen 	uint8_t cm = 0;
372*0c05871eSleisen 	uint8_t cl = 0;
373*0c05871eSleisen 
374*0c05871eSleisen 	ae_drv_ctx->civ_len = MAX_IV_SIZE;
375*0c05871eSleisen 	if (ae_drv_ctx->mode == C_MODE_GCM) {
376*0c05871eSleisen 		ae_drv_ctx->civ_len = dinit->nonce.length;
377*0c05871eSleisen 		memcpy(ae_drv_ctx->civ, dinit->nonce.data, dinit->nonce.length);
378*0c05871eSleisen 		return TEE_SUCCESS;
379*0c05871eSleisen 	}
380*0c05871eSleisen 
381*0c05871eSleisen 	if (dinit->aad_len)
382*0c05871eSleisen 		adata = AAD_NOT_NULL;
383*0c05871eSleisen 
384*0c05871eSleisen 	cm = ((dinit->tag_len - IV_CM_CAL_NUM) / IV_CM_CAL_NUM) & IV_CL_MASK;
385*0c05871eSleisen 	cl = IV_CL_CAL_NUM - dinit->nonce.length;
386*0c05871eSleisen 	flags = cl | SHIFT_U32(cm, IV_CM_OFFSET) |
387*0c05871eSleisen 		SHIFT_U32(adata, IV_FLAGS_OFFSET);
388*0c05871eSleisen 
389*0c05871eSleisen 	memcpy(ae_drv_ctx->civ + NONCE_OFFSET, dinit->nonce.data,
390*0c05871eSleisen 	       dinit->nonce.length);
391*0c05871eSleisen 	memcpy(ae_drv_ctx->aiv + NONCE_OFFSET, dinit->nonce.data,
392*0c05871eSleisen 	       dinit->nonce.length);
393*0c05871eSleisen 
394*0c05871eSleisen 	ae_drv_ctx->aiv[0] = flags;
395*0c05871eSleisen 	ae_drv_ctx->aiv[IV_LAST_BYTE1] = data_size & IV_LAST_BYTE_MASK;
396*0c05871eSleisen 	data_size >>= IV_BYTE_OFFSET;
397*0c05871eSleisen 	ae_drv_ctx->aiv[IV_LAST_BYTE2] = data_size & IV_LAST_BYTE_MASK;
398*0c05871eSleisen 	data_size >>= IV_BYTE_OFFSET;
399*0c05871eSleisen 	ae_drv_ctx->aiv[IV_LAST_BYTE3] = data_size & IV_LAST_BYTE_MASK;
400*0c05871eSleisen 
401*0c05871eSleisen 	ae_drv_ctx->civ[0] = cl;
402*0c05871eSleisen 	ae_drv_ctx->civ[MAX_IV_SIZE - 1] = IV_CTR_INIT;
403*0c05871eSleisen 
404*0c05871eSleisen 	return TEE_SUCCESS;
405*0c05871eSleisen }
406*0c05871eSleisen 
sec_aead_get_dma(struct authenc_ctx * ae_drv_ctx)407*0c05871eSleisen static TEE_Result sec_aead_get_dma(struct authenc_ctx *ae_drv_ctx)
408*0c05871eSleisen {
409*0c05871eSleisen 	ae_drv_ctx->key_dma = virt_to_phys(ae_drv_ctx->key);
410*0c05871eSleisen 	ae_drv_ctx->civ_dma = virt_to_phys(ae_drv_ctx->civ);
411*0c05871eSleisen 	ae_drv_ctx->tag_dma = virt_to_phys(ae_drv_ctx->tag);
412*0c05871eSleisen 	ae_drv_ctx->src_dma = virt_to_phys(ae_drv_ctx->src.data);
413*0c05871eSleisen 	ae_drv_ctx->dst_dma = virt_to_phys(ae_drv_ctx->dst.data);
414*0c05871eSleisen 
415*0c05871eSleisen 	if (ae_drv_ctx->mode == C_MODE_GCM)
416*0c05871eSleisen 		return TEE_SUCCESS;
417*0c05871eSleisen 	ae_drv_ctx->aiv_dma = virt_to_phys(ae_drv_ctx->aiv);
418*0c05871eSleisen 
419*0c05871eSleisen 	return TEE_SUCCESS;
420*0c05871eSleisen }
421*0c05871eSleisen 
sec_aead_data_alloc(struct authenc_ctx * ae_drv_ctx)422*0c05871eSleisen static TEE_Result sec_aead_data_alloc(struct authenc_ctx *ae_drv_ctx)
423*0c05871eSleisen {
424*0c05871eSleisen 	ae_drv_ctx->src.length = ae_drv_ctx->payload_len +
425*0c05871eSleisen 				 ae_drv_ctx->aad.length;
426*0c05871eSleisen 	ae_drv_ctx->src.data = malloc(ae_drv_ctx->src.length);
427*0c05871eSleisen 	if (!ae_drv_ctx->src.data) {
428*0c05871eSleisen 		EMSG("Fail to malloc src");
429*0c05871eSleisen 		return TEE_ERROR_OUT_OF_MEMORY;
430*0c05871eSleisen 	}
431*0c05871eSleisen 
432*0c05871eSleisen 	ae_drv_ctx->dst.length = ae_drv_ctx->src.length;
433*0c05871eSleisen 	ae_drv_ctx->dst.data = malloc(ae_drv_ctx->dst.length);
434*0c05871eSleisen 	if (!ae_drv_ctx->dst.data) {
435*0c05871eSleisen 		EMSG("Fail to malloc dst");
436*0c05871eSleisen 		free(ae_drv_ctx->src.data);
437*0c05871eSleisen 		ae_drv_ctx->src.data = NULL;
438*0c05871eSleisen 		return TEE_ERROR_OUT_OF_MEMORY;
439*0c05871eSleisen 	}
440*0c05871eSleisen 
441*0c05871eSleisen 	return TEE_SUCCESS;
442*0c05871eSleisen }
443*0c05871eSleisen 
ae_soft_calc_init(struct authenc_ctx * ae_drv_ctx,struct drvcrypt_authenc_init * dinit)444*0c05871eSleisen static TEE_Result ae_soft_calc_init(struct authenc_ctx *ae_drv_ctx,
445*0c05871eSleisen 				    struct drvcrypt_authenc_init *dinit)
446*0c05871eSleisen {
447*0c05871eSleisen 	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
448*0c05871eSleisen 	TEE_Result ret = TEE_SUCCESS;
449*0c05871eSleisen 	TEE_OperationMode mode = 0;
450*0c05871eSleisen 
451*0c05871eSleisen 	if (ae_drv_ctx->algo == C_ALG_AES && ae_drv_ctx->mode == C_MODE_GCM) {
452*0c05871eSleisen 		ae_drv_ctx->is_hw_supported = false;
453*0c05871eSleisen 		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
454*0c05871eSleisen 		if (!dinit->encrypt)
455*0c05871eSleisen 			mode = 1;
456*0c05871eSleisen 		ret = ae_soft_ctx->ops->init(ae_soft_ctx, mode,
457*0c05871eSleisen 			dinit->key.data, dinit->key.length,
458*0c05871eSleisen 			dinit->nonce.data, dinit->nonce.length,
459*0c05871eSleisen 			dinit->tag_len, dinit->aad_len,
460*0c05871eSleisen 			dinit->payload_len);
461*0c05871eSleisen 		if (ret)
462*0c05871eSleisen 			EMSG("Fail to init by soft ctx");
463*0c05871eSleisen 
464*0c05871eSleisen 		return ret;
465*0c05871eSleisen 	}
466*0c05871eSleisen 
467*0c05871eSleisen 	return TEE_ERROR_NOT_IMPLEMENTED;
468*0c05871eSleisen }
469*0c05871eSleisen 
sec_authenc_initialize(struct drvcrypt_authenc_init * dinit)470*0c05871eSleisen static TEE_Result sec_authenc_initialize(struct drvcrypt_authenc_init *dinit)
471*0c05871eSleisen {
472*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = NULL;
473*0c05871eSleisen 	TEE_Result ret = TEE_SUCCESS;
474*0c05871eSleisen 	bool hw_support = false;
475*0c05871eSleisen 
476*0c05871eSleisen 	ret = authenc_init_params_check(dinit);
477*0c05871eSleisen 	if (ret)
478*0c05871eSleisen 		return ret;
479*0c05871eSleisen 
480*0c05871eSleisen 	ae_drv_ctx = dinit->ctx;
481*0c05871eSleisen 	hw_support = is_hw_supported(dinit);
482*0c05871eSleisen 	if (!hw_support)
483*0c05871eSleisen 		return ae_soft_calc_init(ae_drv_ctx, dinit);
484*0c05871eSleisen 
485*0c05871eSleisen 	ae_drv_ctx->encrypt = dinit->encrypt;
486*0c05871eSleisen 	ae_drv_ctx->payload_len = dinit->payload_len;
487*0c05871eSleisen 	ae_drv_ctx->aad.length = dinit->aad_len;
488*0c05871eSleisen 	ae_drv_ctx->tag_len = dinit->tag_len;
489*0c05871eSleisen 
490*0c05871eSleisen 	ret = sec_aead_set_key(dinit);
491*0c05871eSleisen 	if (ret)
492*0c05871eSleisen 		return ret;
493*0c05871eSleisen 
494*0c05871eSleisen 	ret = sec_aead_set_iv(dinit);
495*0c05871eSleisen 	if (ret)
496*0c05871eSleisen 		goto clean_key;
497*0c05871eSleisen 
498*0c05871eSleisen 	ret = sec_aead_data_alloc(ae_drv_ctx);
499*0c05871eSleisen 	if (ret)
500*0c05871eSleisen 		goto clean_key;
501*0c05871eSleisen 
502*0c05871eSleisen 	ret = sec_aead_get_dma(ae_drv_ctx);
503*0c05871eSleisen 	if (ret)
504*0c05871eSleisen 		goto free_data;
505*0c05871eSleisen 
506*0c05871eSleisen 	return TEE_SUCCESS;
507*0c05871eSleisen free_data:
508*0c05871eSleisen 	if (ae_drv_ctx->src.data) {
509*0c05871eSleisen 		free(ae_drv_ctx->src.data);
510*0c05871eSleisen 		ae_drv_ctx->src.data = NULL;
511*0c05871eSleisen 	}
512*0c05871eSleisen 	if (ae_drv_ctx->dst.data) {
513*0c05871eSleisen 		free(ae_drv_ctx->dst.data);
514*0c05871eSleisen 		ae_drv_ctx->src.data = NULL;
515*0c05871eSleisen 	}
516*0c05871eSleisen clean_key:
517*0c05871eSleisen 	memzero_explicit(ae_drv_ctx->key, sizeof(ae_drv_ctx->key));
518*0c05871eSleisen 	return ret;
519*0c05871eSleisen }
520*0c05871eSleisen 
521*0c05871eSleisen static TEE_Result
sec_authenc_update_aad(struct drvcrypt_authenc_update_aad * dupdate)522*0c05871eSleisen sec_authenc_update_aad(struct drvcrypt_authenc_update_aad *dupdate)
523*0c05871eSleisen {
524*0c05871eSleisen 	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
525*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = NULL;
526*0c05871eSleisen 	TEE_Result ret = TEE_SUCCESS;
527*0c05871eSleisen 
528*0c05871eSleisen 	if (!dupdate || !dupdate->ctx) {
529*0c05871eSleisen 		EMSG("Invalid input parameters");
530*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
531*0c05871eSleisen 	}
532*0c05871eSleisen 
533*0c05871eSleisen 	ae_drv_ctx = dupdate->ctx;
534*0c05871eSleisen 	if (!ae_drv_ctx->is_hw_supported) {
535*0c05871eSleisen 		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
536*0c05871eSleisen 		ret = ae_soft_ctx->ops->update_aad(ae_soft_ctx,
537*0c05871eSleisen 			dupdate->aad.data, dupdate->aad.length);
538*0c05871eSleisen 		if (ret)
539*0c05871eSleisen 			EMSG("Fail to update aad by soft ctx");
540*0c05871eSleisen 
541*0c05871eSleisen 		return ret;
542*0c05871eSleisen 	}
543*0c05871eSleisen 
544*0c05871eSleisen 	if (dupdate->aad.length + ae_drv_ctx->src_offset >
545*0c05871eSleisen 	    ae_drv_ctx->src.length) {
546*0c05871eSleisen 		EMSG("Invalid aad length");
547*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
548*0c05871eSleisen 	}
549*0c05871eSleisen 	/*
550*0c05871eSleisen 	 * Both aad and ptx need to be filled in the src field.
551*0c05871eSleisen 	 * Here, aad is placed in the header of the src field.
552*0c05871eSleisen 	 */
553*0c05871eSleisen 	memcpy(ae_drv_ctx->src.data + ae_drv_ctx->src_offset,
554*0c05871eSleisen 	       dupdate->aad.data, dupdate->aad.length);
555*0c05871eSleisen 	ae_drv_ctx->src_offset += dupdate->aad.length;
556*0c05871eSleisen 
557*0c05871eSleisen 	return TEE_SUCCESS;
558*0c05871eSleisen }
559*0c05871eSleisen 
update_params_check(struct drvcrypt_authenc_update_payload * d)560*0c05871eSleisen static TEE_Result update_params_check(struct drvcrypt_authenc_update_payload *d)
561*0c05871eSleisen {
562*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = NULL;
563*0c05871eSleisen 
564*0c05871eSleisen 	ae_drv_ctx = d->ctx;
565*0c05871eSleisen 	if (!ae_drv_ctx->src.data || !ae_drv_ctx->dst.data) {
566*0c05871eSleisen 		EMSG("Invalid input/output data");
567*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
568*0c05871eSleisen 	}
569*0c05871eSleisen 
570*0c05871eSleisen 	if (d->src.length + ae_drv_ctx->src_offset > ae_drv_ctx->src.length) {
571*0c05871eSleisen 		EMSG("Invalid update src length");
572*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
573*0c05871eSleisen 	}
574*0c05871eSleisen 
575*0c05871eSleisen 	if (d->dst.length + ae_drv_ctx->src_offset > ae_drv_ctx->dst.length) {
576*0c05871eSleisen 		EMSG("Invalid update dst length");
577*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
578*0c05871eSleisen 	}
579*0c05871eSleisen 
580*0c05871eSleisen 	return TEE_SUCCESS;
581*0c05871eSleisen }
582*0c05871eSleisen 
583*0c05871eSleisen static TEE_Result
sec_authenc_update_payload(struct drvcrypt_authenc_update_payload * d)584*0c05871eSleisen sec_authenc_update_payload(struct drvcrypt_authenc_update_payload *d)
585*0c05871eSleisen {
586*0c05871eSleisen 	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
587*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = NULL;
588*0c05871eSleisen 	TEE_Result ret = TEE_SUCCESS;
589*0c05871eSleisen 
590*0c05871eSleisen 	if (!d || !d->ctx) {
591*0c05871eSleisen 		EMSG("Invalid input parameters");
592*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
593*0c05871eSleisen 	}
594*0c05871eSleisen 
595*0c05871eSleisen 	ae_drv_ctx = d->ctx;
596*0c05871eSleisen 	if (!ae_drv_ctx->is_hw_supported) {
597*0c05871eSleisen 		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
598*0c05871eSleisen 		ret = ae_soft_ctx->ops->update_payload(ae_soft_ctx,
599*0c05871eSleisen 				(TEE_OperationMode)(d->encrypt == 0),
600*0c05871eSleisen 				d->src.data, d->src.length, d->dst.data);
601*0c05871eSleisen 		if (ret)
602*0c05871eSleisen 			EMSG("Fail to update payload by soft ctx");
603*0c05871eSleisen 
604*0c05871eSleisen 		return ret;
605*0c05871eSleisen 	}
606*0c05871eSleisen 
607*0c05871eSleisen 	ret = update_params_check(d);
608*0c05871eSleisen 	if (ret)
609*0c05871eSleisen 		return ret;
610*0c05871eSleisen 
611*0c05871eSleisen 	memcpy(ae_drv_ctx->src.data + ae_drv_ctx->src_offset,
612*0c05871eSleisen 	       d->src.data, d->src.length);
613*0c05871eSleisen 
614*0c05871eSleisen 	ret = sec_do_aead_task(ae_drv_ctx->qp, ae_drv_ctx);
615*0c05871eSleisen 	if (ret)
616*0c05871eSleisen 		return ret;
617*0c05871eSleisen 
618*0c05871eSleisen 	memcpy(d->dst.data, ae_drv_ctx->dst.data + ae_drv_ctx->src_offset,
619*0c05871eSleisen 	       d->dst.length);
620*0c05871eSleisen 	ae_drv_ctx->src_offset += d->src.length;
621*0c05871eSleisen 
622*0c05871eSleisen 	return TEE_SUCCESS;
623*0c05871eSleisen }
624*0c05871eSleisen 
final_params_check(struct drvcrypt_authenc_final * dfinal)625*0c05871eSleisen static TEE_Result final_params_check(struct drvcrypt_authenc_final *dfinal)
626*0c05871eSleisen {
627*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = dfinal->ctx;
628*0c05871eSleisen 
629*0c05871eSleisen 	if (!ae_drv_ctx->src.data || !ae_drv_ctx->dst.data) {
630*0c05871eSleisen 		EMSG("Invalid input/output data");
631*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
632*0c05871eSleisen 	}
633*0c05871eSleisen 
634*0c05871eSleisen 	if (dfinal->src.length + ae_drv_ctx->src_offset >
635*0c05871eSleisen 	    ae_drv_ctx->src.length) {
636*0c05871eSleisen 		EMSG("Invalid dfinal src length");
637*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
638*0c05871eSleisen 	}
639*0c05871eSleisen 
640*0c05871eSleisen 	if (dfinal->dst.length + ae_drv_ctx->src_offset >
641*0c05871eSleisen 	    ae_drv_ctx->dst.length) {
642*0c05871eSleisen 		EMSG("Invalid dfinal dst length");
643*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
644*0c05871eSleisen 	}
645*0c05871eSleisen 
646*0c05871eSleisen 	if (dfinal->tag.length > SEC_MAX_TAG_LEN) {
647*0c05871eSleisen 		EMSG("Invalid dfinal tag length");
648*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
649*0c05871eSleisen 	}
650*0c05871eSleisen 
651*0c05871eSleisen 	return TEE_SUCCESS;
652*0c05871eSleisen }
653*0c05871eSleisen 
sec_authenc_enc_final(struct drvcrypt_authenc_final * dfinal)654*0c05871eSleisen static TEE_Result sec_authenc_enc_final(struct drvcrypt_authenc_final *dfinal)
655*0c05871eSleisen {
656*0c05871eSleisen 	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
657*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = NULL;
658*0c05871eSleisen 	TEE_Result ret = TEE_SUCCESS;
659*0c05871eSleisen 
660*0c05871eSleisen 	if (!dfinal || !dfinal->ctx) {
661*0c05871eSleisen 		EMSG("Invalid input parameters");
662*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
663*0c05871eSleisen 	}
664*0c05871eSleisen 
665*0c05871eSleisen 	ae_drv_ctx = dfinal->ctx;
666*0c05871eSleisen 	if (!ae_drv_ctx->is_hw_supported) {
667*0c05871eSleisen 		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
668*0c05871eSleisen 		ret = ae_soft_ctx->ops->enc_final(ae_soft_ctx,
669*0c05871eSleisen 			dfinal->src.data, dfinal->src.length,
670*0c05871eSleisen 			dfinal->dst.data, dfinal->tag.data,
671*0c05871eSleisen 			&dfinal->tag.length);
672*0c05871eSleisen 		if (ret)
673*0c05871eSleisen 			EMSG("Fail to do enc final by soft ctx");
674*0c05871eSleisen 
675*0c05871eSleisen 		return ret;
676*0c05871eSleisen 	}
677*0c05871eSleisen 
678*0c05871eSleisen 	ret = final_params_check(dfinal);
679*0c05871eSleisen 	if (ret)
680*0c05871eSleisen 		return ret;
681*0c05871eSleisen 	memcpy(ae_drv_ctx->src.data + ae_drv_ctx->src_offset, dfinal->src.data,
682*0c05871eSleisen 	       dfinal->src.length);
683*0c05871eSleisen 
684*0c05871eSleisen 	ret = sec_do_aead_task(ae_drv_ctx->qp, ae_drv_ctx);
685*0c05871eSleisen 
686*0c05871eSleisen 	memcpy(dfinal->tag.data, ae_drv_ctx->tag, dfinal->tag.length);
687*0c05871eSleisen 	memcpy(dfinal->dst.data, ae_drv_ctx->dst.data + ae_drv_ctx->src_offset,
688*0c05871eSleisen 	       dfinal->dst.length);
689*0c05871eSleisen 
690*0c05871eSleisen 	return ret;
691*0c05871eSleisen }
692*0c05871eSleisen 
sec_authenc_dec_final(struct drvcrypt_authenc_final * dfinal)693*0c05871eSleisen static TEE_Result sec_authenc_dec_final(struct drvcrypt_authenc_final *dfinal)
694*0c05871eSleisen {
695*0c05871eSleisen 	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
696*0c05871eSleisen 	struct authenc_ctx *ae_drv_ctx = NULL;
697*0c05871eSleisen 	TEE_Result ret = TEE_SUCCESS;
698*0c05871eSleisen 
699*0c05871eSleisen 	if (!dfinal || !dfinal->ctx) {
700*0c05871eSleisen 		EMSG("Invalid input parameters");
701*0c05871eSleisen 		return TEE_ERROR_BAD_PARAMETERS;
702*0c05871eSleisen 	}
703*0c05871eSleisen 
704*0c05871eSleisen 	ae_drv_ctx = dfinal->ctx;
705*0c05871eSleisen 	if (!ae_drv_ctx->is_hw_supported) {
706*0c05871eSleisen 		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
707*0c05871eSleisen 		ret =  ae_soft_ctx->ops->dec_final(ae_soft_ctx,
708*0c05871eSleisen 			dfinal->src.data, dfinal->src.length,
709*0c05871eSleisen 			dfinal->dst.data, dfinal->tag.data,
710*0c05871eSleisen 			dfinal->tag.length);
711*0c05871eSleisen 		if (ret)
712*0c05871eSleisen 			EMSG("Fail to do dec final by soft ctx");
713*0c05871eSleisen 
714*0c05871eSleisen 		return ret;
715*0c05871eSleisen 	}
716*0c05871eSleisen 
717*0c05871eSleisen 	ret = final_params_check(dfinal);
718*0c05871eSleisen 	if (ret)
719*0c05871eSleisen 		return ret;
720*0c05871eSleisen 	memcpy(ae_drv_ctx->src.data + ae_drv_ctx->src_offset, dfinal->src.data,
721*0c05871eSleisen 	       dfinal->src.length);
722*0c05871eSleisen 	memcpy(ae_drv_ctx->tag, dfinal->tag.data, dfinal->tag.length);
723*0c05871eSleisen 
724*0c05871eSleisen 	ret = sec_do_aead_task(ae_drv_ctx->qp, ae_drv_ctx);
725*0c05871eSleisen 	if (ret)
726*0c05871eSleisen 		return ret;
727*0c05871eSleisen 
728*0c05871eSleisen 	memcpy(dfinal->dst.data, ae_drv_ctx->dst.data + ae_drv_ctx->src_offset,
729*0c05871eSleisen 	       dfinal->dst.length);
730*0c05871eSleisen 	if (ae_drv_ctx->result == SEC_TAG_ERR) {
731*0c05871eSleisen 		EMSG("Integrity check failed");
732*0c05871eSleisen 		return TEE_ERROR_BAD_STATE;
733*0c05871eSleisen 	}
734*0c05871eSleisen 
735*0c05871eSleisen 	return TEE_SUCCESS;
736*0c05871eSleisen }
737*0c05871eSleisen 
sec_authenc_do_final(void * ctx __unused)738*0c05871eSleisen static void sec_authenc_do_final(void *ctx __unused)
739*0c05871eSleisen {
740*0c05871eSleisen }
741*0c05871eSleisen 
sec_authenc_copy_state(void * dst_ctx,void * src_ctx)742*0c05871eSleisen static void sec_authenc_copy_state(void *dst_ctx, void *src_ctx)
743*0c05871eSleisen {
744*0c05871eSleisen 	struct authenc_ctx *dst = dst_ctx;
745*0c05871eSleisen 	struct authenc_ctx *src = src_ctx;
746*0c05871eSleisen 	TEE_Result ret = TEE_SUCCESS;
747*0c05871eSleisen 
748*0c05871eSleisen 	if (!src->is_hw_supported) {
749*0c05871eSleisen 		dst->is_hw_supported = false;
750*0c05871eSleisen 		src->ae_soft_ctx->ops->copy_state(dst->ae_soft_ctx,
751*0c05871eSleisen 						  src->ae_soft_ctx);
752*0c05871eSleisen 		return;
753*0c05871eSleisen 	}
754*0c05871eSleisen 
755*0c05871eSleisen 	dst->algo = src->algo;
756*0c05871eSleisen 	dst->mode = src->mode;
757*0c05871eSleisen 	dst->encrypt = src->encrypt;
758*0c05871eSleisen 	dst->key_len = src->key_len;
759*0c05871eSleisen 	dst->tag_len = src->tag_len;
760*0c05871eSleisen 	dst->c_key_len = src->c_key_len;
761*0c05871eSleisen 	dst->aad.length = src->aad.length;
762*0c05871eSleisen 	dst->src_offset = src->src_offset;
763*0c05871eSleisen 	dst->payload_len = src->payload_len;
764*0c05871eSleisen 	dst->is_hw_supported = src->is_hw_supported;
765*0c05871eSleisen 	memcpy(dst->key, src->key, src->key_len);
766*0c05871eSleisen 	memcpy(dst->civ, src->civ, src->civ_len);
767*0c05871eSleisen 	/* The len of aiv is always MAX_IV_SIZE */
768*0c05871eSleisen 	memcpy(dst->aiv, src->aiv, MAX_IV_SIZE);
769*0c05871eSleisen 	ret = sec_aead_data_alloc(dst);
770*0c05871eSleisen 	if (ret)
771*0c05871eSleisen 		return;
772*0c05871eSleisen 	memcpy(dst->src.data, src->src.data,
773*0c05871eSleisen 	       src->aad.length + src->payload_len);
774*0c05871eSleisen 	memcpy(dst->dst.data, src->dst.data,
775*0c05871eSleisen 	       src->aad.length + src->payload_len);
776*0c05871eSleisen 
777*0c05871eSleisen 	ret = sec_aead_get_dma(dst);
778*0c05871eSleisen 	if (ret) {
779*0c05871eSleisen 		memzero_explicit(dst->key, dst->key_len);
780*0c05871eSleisen 		free(dst->src.data);
781*0c05871eSleisen 		dst->src.data = NULL;
782*0c05871eSleisen 		free(dst->dst.data);
783*0c05871eSleisen 		dst->dst.data = NULL;
784*0c05871eSleisen 	}
785*0c05871eSleisen }
786*0c05871eSleisen 
787*0c05871eSleisen static struct drvcrypt_authenc driver_authenc = {
788*0c05871eSleisen 	.alloc_ctx = sec_authenc_ctx_allocate,
789*0c05871eSleisen 	.free_ctx = sec_authenc_ctx_free,
790*0c05871eSleisen 	.init = sec_authenc_initialize,
791*0c05871eSleisen 	.update_aad = sec_authenc_update_aad,
792*0c05871eSleisen 	.update_payload = sec_authenc_update_payload,
793*0c05871eSleisen 	.enc_final = sec_authenc_enc_final,
794*0c05871eSleisen 	.dec_final = sec_authenc_dec_final,
795*0c05871eSleisen 	.final = sec_authenc_do_final,
796*0c05871eSleisen 	.copy_state = sec_authenc_copy_state,
797*0c05871eSleisen };
798*0c05871eSleisen 
sec_authenc_init(void)799*0c05871eSleisen static TEE_Result sec_authenc_init(void)
800*0c05871eSleisen {
801*0c05871eSleisen 	TEE_Result ret = TEE_SUCCESS;
802*0c05871eSleisen 
803*0c05871eSleisen 	ret = drvcrypt_register_authenc(&driver_authenc);
804*0c05871eSleisen 	if (ret)
805*0c05871eSleisen 		EMSG("Sec authenc register to crypto fail ret=%#"PRIx32, ret);
806*0c05871eSleisen 
807*0c05871eSleisen 	return ret;
808*0c05871eSleisen }
809*0c05871eSleisen driver_init(sec_authenc_init);
810