xref: /optee_os/core/drivers/zynqmp_csu_aes.c (revision f354a5d8f98eb3bc8f3360eccd7405144266b5b4)
1f072eea4SJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-2-Clause
2f072eea4SJorge Ramirez-Ortiz /*
3f072eea4SJorge Ramirez-Ortiz  * Copyright (C) Foundries Ltd. 2021
4f072eea4SJorge Ramirez-Ortiz  * Author: Jorge Ramirez <jorge@foundries.io>
5f072eea4SJorge Ramirez-Ortiz  */
6f072eea4SJorge Ramirez-Ortiz #include <config.h>
7f072eea4SJorge Ramirez-Ortiz #include <drivers/zynqmp_csu.h>
8f072eea4SJorge Ramirez-Ortiz #include <drivers/zynqmp_csu_aes.h>
9f072eea4SJorge Ramirez-Ortiz #include <io.h>
10f072eea4SJorge Ramirez-Ortiz #include <kernel/boot.h>
11f072eea4SJorge Ramirez-Ortiz #include <kernel/delay.h>
12f072eea4SJorge Ramirez-Ortiz #include <kernel/dt.h>
13f072eea4SJorge Ramirez-Ortiz #include <libfdt.h>
14f072eea4SJorge Ramirez-Ortiz #include <malloc.h>
15f072eea4SJorge Ramirez-Ortiz #include <mm/core_memprot.h>
16f072eea4SJorge Ramirez-Ortiz #include <string.h>
17f072eea4SJorge Ramirez-Ortiz #include <tee/cache.h>
18f072eea4SJorge Ramirez-Ortiz 
19f072eea4SJorge Ramirez-Ortiz /* CSU AES registers */
20f072eea4SJorge Ramirez-Ortiz #define AES_STS_OFFSET			0x00
21f072eea4SJorge Ramirez-Ortiz #define AES_KEY_SRC_OFFSET		0x04
22f072eea4SJorge Ramirez-Ortiz #define AES_KEY_LOAD_OFFSET		0x08
23f072eea4SJorge Ramirez-Ortiz #define AES_START_MSG_OFFSET		0x0C
24f072eea4SJorge Ramirez-Ortiz #define AES_RESET_OFFSET		0x10
25f072eea4SJorge Ramirez-Ortiz #define AES_KEY_CLR_OFFSET		0x14
26f072eea4SJorge Ramirez-Ortiz #define AES_CFG_OFFSET			0x18
27f072eea4SJorge Ramirez-Ortiz 
28f072eea4SJorge Ramirez-Ortiz #define AES_KEY_LOAD			1
29f072eea4SJorge Ramirez-Ortiz #define AES_STS_AES_BUSY	        BIT(0)
30f072eea4SJorge Ramirez-Ortiz #define AES_STS_AES_KEY_ZEROED		BIT(8)
31f072eea4SJorge Ramirez-Ortiz #define AES_STS_KUP_ZEROED		BIT(9)
32f072eea4SJorge Ramirez-Ortiz #define AES_STS_KEY_INIT_DONE		BIT(4)
33f072eea4SJorge Ramirez-Ortiz #define AES_STS_GCM_TAG_OK		BIT(3)
34f072eea4SJorge Ramirez-Ortiz #define AES_START_MSG			1
35f072eea4SJorge Ramirez-Ortiz #define AES_CFG_ENC			1
36f072eea4SJorge Ramirez-Ortiz #define AES_CFG_DEC			0
37f072eea4SJorge Ramirez-Ortiz #define AES_RESET_SET			1
38f072eea4SJorge Ramirez-Ortiz #define AES_RESET_CLR			0
39f072eea4SJorge Ramirez-Ortiz #define AES_KEY_ZERO			BIT(0)
40f072eea4SJorge Ramirez-Ortiz #define AES_KUP_ZERO			BIT(1)
41f072eea4SJorge Ramirez-Ortiz 
42f072eea4SJorge Ramirez-Ortiz #define AES_TIMEOUT_USEC		2000000
43f072eea4SJorge Ramirez-Ortiz 
44f072eea4SJorge Ramirez-Ortiz enum aes_op { AES_DEC, AES_ENC };
45f072eea4SJorge Ramirez-Ortiz 
aes_wait(uint32_t event,bool set)46f072eea4SJorge Ramirez-Ortiz static TEE_Result aes_wait(uint32_t event, bool set)
47f072eea4SJorge Ramirez-Ortiz {
48f072eea4SJorge Ramirez-Ortiz 	vaddr_t aes = core_mmu_get_va(ZYNQMP_CSU_AES_BASE, MEM_AREA_IO_SEC,
49f072eea4SJorge Ramirez-Ortiz 				      ZYNQMP_CSU_AES_SIZE);
50f072eea4SJorge Ramirez-Ortiz 	uint64_t tref = timeout_init_us(AES_TIMEOUT_USEC);
51f072eea4SJorge Ramirez-Ortiz 	uint32_t status = 0;
52f072eea4SJorge Ramirez-Ortiz 
53f072eea4SJorge Ramirez-Ortiz 	if (!aes)
54f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
55f072eea4SJorge Ramirez-Ortiz 
56f072eea4SJorge Ramirez-Ortiz 	while (!timeout_elapsed(tref)) {
57f072eea4SJorge Ramirez-Ortiz 		status = io_read32(aes + AES_STS_OFFSET) & event;
58f072eea4SJorge Ramirez-Ortiz 		if ((set && status == event) || (!set && status != event))
59f072eea4SJorge Ramirez-Ortiz 			return TEE_SUCCESS;
60f072eea4SJorge Ramirez-Ortiz 	}
61f072eea4SJorge Ramirez-Ortiz 
62f072eea4SJorge Ramirez-Ortiz 	return TEE_ERROR_GENERIC;
63f072eea4SJorge Ramirez-Ortiz }
64f072eea4SJorge Ramirez-Ortiz 
aes_transfer_enc(const void * src,void * dst,size_t dst_len,void * tag,const void * iv)65f072eea4SJorge Ramirez-Ortiz static TEE_Result aes_transfer_enc(const void *src, void *dst, size_t dst_len,
66f072eea4SJorge Ramirez-Ortiz 				   void *tag, const void *iv)
67f072eea4SJorge Ramirez-Ortiz {
68f072eea4SJorge Ramirez-Ortiz 	void *p = (uint8_t *)dst + dst_len - ZYNQMP_GCM_TAG_SIZE;
69f072eea4SJorge Ramirez-Ortiz 	uint8_t iv_padded[ZYNQMP_CSUDMA_MIN_SIZE] __aligned_csudma = { 0 };
70f072eea4SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
71f072eea4SJorge Ramirez-Ortiz 
72f072eea4SJorge Ramirez-Ortiz 	if (dst_len < ZYNQMP_GCM_TAG_SIZE) {
73f072eea4SJorge Ramirez-Ortiz 		EMSG("Invalid length");
74f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
75f072eea4SJorge Ramirez-Ortiz 	}
76f072eea4SJorge Ramirez-Ortiz 
77f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_prepare();
78f072eea4SJorge Ramirez-Ortiz 	if (ret) {
79f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA can't initialize");
80f072eea4SJorge Ramirez-Ortiz 		return ret;
81f072eea4SJorge Ramirez-Ortiz 	}
82f072eea4SJorge Ramirez-Ortiz 
83f072eea4SJorge Ramirez-Ortiz 	/* Prepare destination */
84f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_DST_CHANNEL, dst, dst_len,
85f072eea4SJorge Ramirez-Ortiz 				     0);
86f072eea4SJorge Ramirez-Ortiz 	if (ret) {
87f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA transfer failed, invalid destination buffer");
88f072eea4SJorge Ramirez-Ortiz 		goto out;
89f072eea4SJorge Ramirez-Ortiz 	}
90f072eea4SJorge Ramirez-Ortiz 
91f072eea4SJorge Ramirez-Ortiz 	/* Inputs */
92f072eea4SJorge Ramirez-Ortiz 	memcpy(iv_padded, iv, ZYNQMP_GCM_IV_SIZE);
93f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL,
94f072eea4SJorge Ramirez-Ortiz 				     (void *)iv_padded, ZYNQMP_CSUDMA_MIN_SIZE,
95f072eea4SJorge Ramirez-Ortiz 				     0);
96f072eea4SJorge Ramirez-Ortiz 	if (ret) {
97f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA transfer failed, invalid IV buffer");
98f072eea4SJorge Ramirez-Ortiz 		goto out;
99f072eea4SJorge Ramirez-Ortiz 	}
100f072eea4SJorge Ramirez-Ortiz 
101f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL);
102f072eea4SJorge Ramirez-Ortiz 	if (ret) {
103f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA IV transfer timeout");
104f072eea4SJorge Ramirez-Ortiz 		goto out;
105f072eea4SJorge Ramirez-Ortiz 	}
106f072eea4SJorge Ramirez-Ortiz 
107f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL,
108f072eea4SJorge Ramirez-Ortiz 				     (void *)src, dst_len - ZYNQMP_GCM_TAG_SIZE,
109f072eea4SJorge Ramirez-Ortiz 				     ZYNQMP_CSUDMA_DONE);
110f072eea4SJorge Ramirez-Ortiz 	if (ret) {
111f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA transfer failed, invalid source buffer");
112f072eea4SJorge Ramirez-Ortiz 		goto out;
113f072eea4SJorge Ramirez-Ortiz 	}
114f072eea4SJorge Ramirez-Ortiz 
115f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL);
116f072eea4SJorge Ramirez-Ortiz 	if (ret) {
117f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA source transfer timeout");
118f072eea4SJorge Ramirez-Ortiz 		goto out;
119f072eea4SJorge Ramirez-Ortiz 	}
120f072eea4SJorge Ramirez-Ortiz 
121f072eea4SJorge Ramirez-Ortiz 	/* Wait for completion */
122f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_DST_CHANNEL);
123f072eea4SJorge Ramirez-Ortiz 	if (ret) {
124f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA destination transfer timeout");
125f072eea4SJorge Ramirez-Ortiz 		goto out;
126f072eea4SJorge Ramirez-Ortiz 	}
127f072eea4SJorge Ramirez-Ortiz 
128f072eea4SJorge Ramirez-Ortiz 	/* Transfer the GCM tag */
129f072eea4SJorge Ramirez-Ortiz 	memcpy(tag, p, ZYNQMP_GCM_TAG_SIZE);
130f072eea4SJorge Ramirez-Ortiz out:
131f072eea4SJorge Ramirez-Ortiz 	zynqmp_csudma_unprepare();
132f072eea4SJorge Ramirez-Ortiz 
133f072eea4SJorge Ramirez-Ortiz 	return ret;
134f072eea4SJorge Ramirez-Ortiz }
135f072eea4SJorge Ramirez-Ortiz 
aes_transfer_dec(const void * src,void * dst,size_t len,const void * tag,const void * iv)136f072eea4SJorge Ramirez-Ortiz static TEE_Result aes_transfer_dec(const void *src, void *dst, size_t len,
137f072eea4SJorge Ramirez-Ortiz 				   const void *tag, const void *iv)
138f072eea4SJorge Ramirez-Ortiz {
139f072eea4SJorge Ramirez-Ortiz 	uint8_t iv_padded[ZYNQMP_CSUDMA_MIN_SIZE] __aligned_csudma = { 0 };
140f072eea4SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
141f072eea4SJorge Ramirez-Ortiz 
142f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_prepare();
143f072eea4SJorge Ramirez-Ortiz 	if (ret) {
144f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA can't initialize");
145f072eea4SJorge Ramirez-Ortiz 		return ret;
146f072eea4SJorge Ramirez-Ortiz 	}
147f072eea4SJorge Ramirez-Ortiz 
148f072eea4SJorge Ramirez-Ortiz 	/* Prepare destination */
149f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_DST_CHANNEL, dst, len, 0);
150f072eea4SJorge Ramirez-Ortiz 	if (ret) {
151f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA transfer failed, invalid destination buffer");
152f072eea4SJorge Ramirez-Ortiz 		goto out;
153f072eea4SJorge Ramirez-Ortiz 	}
154f072eea4SJorge Ramirez-Ortiz 
155f072eea4SJorge Ramirez-Ortiz 	/* Inputs */
156f072eea4SJorge Ramirez-Ortiz 	memcpy(iv_padded, iv, ZYNQMP_GCM_IV_SIZE);
157f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL,
158f072eea4SJorge Ramirez-Ortiz 				     (void *)iv_padded, ZYNQMP_CSUDMA_MIN_SIZE,
159f072eea4SJorge Ramirez-Ortiz 				     0);
160f072eea4SJorge Ramirez-Ortiz 	if (ret) {
161f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA transfer failed, invalid IV buffer");
162f072eea4SJorge Ramirez-Ortiz 		goto out;
163f072eea4SJorge Ramirez-Ortiz 	}
164f072eea4SJorge Ramirez-Ortiz 
165f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL);
166f072eea4SJorge Ramirez-Ortiz 	if (ret) {
167f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA IV transfer timeout");
168f072eea4SJorge Ramirez-Ortiz 		goto out;
169f072eea4SJorge Ramirez-Ortiz 	}
170f072eea4SJorge Ramirez-Ortiz 
171f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, (void *)src,
172f072eea4SJorge Ramirez-Ortiz 				     len, ZYNQMP_CSUDMA_DONE);
173f072eea4SJorge Ramirez-Ortiz 	if (ret) {
174f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA transfer failed, invalid source buffer");
175f072eea4SJorge Ramirez-Ortiz 		goto out;
176f072eea4SJorge Ramirez-Ortiz 	}
177f072eea4SJorge Ramirez-Ortiz 
178f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL);
179f072eea4SJorge Ramirez-Ortiz 	if (ret) {
180f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA source transfer timeout");
181f072eea4SJorge Ramirez-Ortiz 		goto out;
182f072eea4SJorge Ramirez-Ortiz 	}
183f072eea4SJorge Ramirez-Ortiz 
184f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, (void *)tag,
185f072eea4SJorge Ramirez-Ortiz 				     ZYNQMP_GCM_TAG_SIZE, ZYNQMP_CSUDMA_DONE);
186f072eea4SJorge Ramirez-Ortiz 	if (ret) {
187f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA transfer failed, invalid tag buffer");
188f072eea4SJorge Ramirez-Ortiz 		goto out;
189f072eea4SJorge Ramirez-Ortiz 	}
190f072eea4SJorge Ramirez-Ortiz 
191f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL);
192f072eea4SJorge Ramirez-Ortiz 	if (ret) {
193f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA tag transfer timeout");
194f072eea4SJorge Ramirez-Ortiz 		goto out;
195f072eea4SJorge Ramirez-Ortiz 	}
196f072eea4SJorge Ramirez-Ortiz 
197f072eea4SJorge Ramirez-Ortiz 	/* Wait for completion*/
198f072eea4SJorge Ramirez-Ortiz 	ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_DST_CHANNEL);
199f072eea4SJorge Ramirez-Ortiz 	if (ret)
200f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA destination transfer timeout");
201f072eea4SJorge Ramirez-Ortiz out:
202f072eea4SJorge Ramirez-Ortiz 	zynqmp_csudma_unprepare();
203f072eea4SJorge Ramirez-Ortiz 
204f072eea4SJorge Ramirez-Ortiz 	return ret;
205f072eea4SJorge Ramirez-Ortiz }
206f072eea4SJorge Ramirez-Ortiz 
aes_prepare_op(enum aes_op op,enum zynqmp_csu_key key)207f072eea4SJorge Ramirez-Ortiz static TEE_Result aes_prepare_op(enum aes_op op, enum zynqmp_csu_key key)
208f072eea4SJorge Ramirez-Ortiz {
209f072eea4SJorge Ramirez-Ortiz 	vaddr_t aes = core_mmu_get_va(ZYNQMP_CSU_AES_BASE, MEM_AREA_IO_SEC,
210f072eea4SJorge Ramirez-Ortiz 				      ZYNQMP_CSU_AES_SIZE);
211f072eea4SJorge Ramirez-Ortiz 	vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE);
212f072eea4SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
213f072eea4SJorge Ramirez-Ortiz 
214f072eea4SJorge Ramirez-Ortiz 	if (!aes || !csu)
215f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
216f072eea4SJorge Ramirez-Ortiz 
217f072eea4SJorge Ramirez-Ortiz 	/* Connect DMA0 in/out to AES */
218f072eea4SJorge Ramirez-Ortiz 	io_write32(csu + ZYNQMP_CSU_SSS_CFG_OFFSET,
219f072eea4SJorge Ramirez-Ortiz 		   ZYNQMP_CSU_SSS_DMA0_STREAM_TO_AES);
220f072eea4SJorge Ramirez-Ortiz 
221f072eea4SJorge Ramirez-Ortiz 	/* Reset the AES */
222f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_RESET_OFFSET, AES_RESET_SET);
223f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_RESET_OFFSET, AES_RESET_CLR);
224f072eea4SJorge Ramirez-Ortiz 
225f072eea4SJorge Ramirez-Ortiz 	/* Load the key */
226f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_KEY_CLR_OFFSET, 0);
227f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_KEY_SRC_OFFSET, key);
228f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_KEY_LOAD_OFFSET, AES_KEY_LOAD);
229f072eea4SJorge Ramirez-Ortiz 	ret = aes_wait(AES_STS_KEY_INIT_DONE, true);
230f072eea4SJorge Ramirez-Ortiz 	if (ret) {
231f072eea4SJorge Ramirez-Ortiz 		EMSG("Timeout loading the key");
232f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
233f072eea4SJorge Ramirez-Ortiz 	}
234f072eea4SJorge Ramirez-Ortiz 
235f072eea4SJorge Ramirez-Ortiz 	/* Configure operation */
236f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_CFG_OFFSET,
237f072eea4SJorge Ramirez-Ortiz 		   op == AES_DEC ? AES_CFG_DEC : AES_CFG_ENC);
238f072eea4SJorge Ramirez-Ortiz 
239f072eea4SJorge Ramirez-Ortiz 	/* Prepare the CSU for the DMA */
240f072eea4SJorge Ramirez-Ortiz 	io_write32(csu + ZYNQMP_CSU_DMA_RESET_OFFSET, ZYNQMP_CSU_DMA_RESET_SET);
241f072eea4SJorge Ramirez-Ortiz 	io_write32(csu + ZYNQMP_CSU_DMA_RESET_OFFSET, ZYNQMP_CSU_DMA_RESET_CLR);
242f072eea4SJorge Ramirez-Ortiz 
243f072eea4SJorge Ramirez-Ortiz 	/* Start the message */
244f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_START_MSG_OFFSET, AES_START_MSG);
245f072eea4SJorge Ramirez-Ortiz 
246f072eea4SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
247f072eea4SJorge Ramirez-Ortiz }
248f072eea4SJorge Ramirez-Ortiz 
aes_done_op(enum aes_op op,TEE_Result ret)249f072eea4SJorge Ramirez-Ortiz static TEE_Result aes_done_op(enum aes_op op, TEE_Result ret)
250f072eea4SJorge Ramirez-Ortiz {
251f072eea4SJorge Ramirez-Ortiz 	vaddr_t aes = core_mmu_get_va(ZYNQMP_CSU_AES_BASE, MEM_AREA_IO_SEC,
252f072eea4SJorge Ramirez-Ortiz 				      ZYNQMP_CSU_AES_SIZE);
253f072eea4SJorge Ramirez-Ortiz 	uint32_t val = 0;
254f072eea4SJorge Ramirez-Ortiz 
255f072eea4SJorge Ramirez-Ortiz 	if (!aes)
256f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
257f072eea4SJorge Ramirez-Ortiz 
258f072eea4SJorge Ramirez-Ortiz 	if (!ret && op == AES_DEC) {
259f072eea4SJorge Ramirez-Ortiz 		/* on decompression we must validate the GCM tag */
260f072eea4SJorge Ramirez-Ortiz 		val = io_read32(aes + AES_STS_OFFSET) & AES_STS_GCM_TAG_OK;
261f072eea4SJorge Ramirez-Ortiz 		if (!val) {
262f072eea4SJorge Ramirez-Ortiz 			EMSG("AES-GCM tag mismatch");
263f072eea4SJorge Ramirez-Ortiz 			return TEE_ERROR_GENERIC;
264f072eea4SJorge Ramirez-Ortiz 		}
265f072eea4SJorge Ramirez-Ortiz 	}
266f072eea4SJorge Ramirez-Ortiz 
267f072eea4SJorge Ramirez-Ortiz 	val = io_read32(aes + AES_KEY_CLR_OFFSET);
268f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_KEY_CLR_OFFSET, val | AES_KEY_ZERO | AES_KUP_ZERO);
269f072eea4SJorge Ramirez-Ortiz 	if (aes_wait(AES_STS_AES_KEY_ZEROED | AES_STS_KUP_ZEROED, true))
270f072eea4SJorge Ramirez-Ortiz 		EMSG("Failed to clear the AES key");
271f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_KEY_CLR_OFFSET, val);
272f072eea4SJorge Ramirez-Ortiz 
273f072eea4SJorge Ramirez-Ortiz 	io_write32(aes + AES_RESET_OFFSET, AES_RESET_SET);
274f072eea4SJorge Ramirez-Ortiz 
275f072eea4SJorge Ramirez-Ortiz 	return ret;
276f072eea4SJorge Ramirez-Ortiz }
277f072eea4SJorge Ramirez-Ortiz 
zynqmp_csu_aes_decrypt_data(const void * src,size_t src_len,void * dst,size_t dst_len,const void * tag,size_t tag_len,const void * iv,size_t iv_len,enum zynqmp_csu_key key)278f072eea4SJorge Ramirez-Ortiz TEE_Result zynqmp_csu_aes_decrypt_data(const void *src, size_t src_len,
279f072eea4SJorge Ramirez-Ortiz 				       void *dst, size_t dst_len,
280f072eea4SJorge Ramirez-Ortiz 				       const void *tag, size_t tag_len,
281f072eea4SJorge Ramirez-Ortiz 				       const void *iv,  size_t iv_len,
282f072eea4SJorge Ramirez-Ortiz 				       enum zynqmp_csu_key key)
283f072eea4SJorge Ramirez-Ortiz {
284f072eea4SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
285f072eea4SJorge Ramirez-Ortiz 
286f072eea4SJorge Ramirez-Ortiz 	if (key != ZYNQMP_CSU_AES_KEY_SRC_DEV) {
287f072eea4SJorge Ramirez-Ortiz 		EMSG("Key type not supported");
288f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_NOT_IMPLEMENTED;
289f072eea4SJorge Ramirez-Ortiz 	}
290f072eea4SJorge Ramirez-Ortiz 
291f072eea4SJorge Ramirez-Ortiz 	if (src_len % 4 || dst_len != src_len) {
292f072eea4SJorge Ramirez-Ortiz 		EMSG("Invalid source size");
293f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
294f072eea4SJorge Ramirez-Ortiz 	}
295f072eea4SJorge Ramirez-Ortiz 
296f072eea4SJorge Ramirez-Ortiz 	if (iv_len != ZYNQMP_GCM_IV_SIZE) {
297f072eea4SJorge Ramirez-Ortiz 		EMSG("Invalid IV size");
298f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
299f072eea4SJorge Ramirez-Ortiz 	}
300f072eea4SJorge Ramirez-Ortiz 
301f072eea4SJorge Ramirez-Ortiz 	if (tag_len != ZYNQMP_GCM_TAG_SIZE) {
302f072eea4SJorge Ramirez-Ortiz 		EMSG("Invalid tag size");
303f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
304f072eea4SJorge Ramirez-Ortiz 	}
305f072eea4SJorge Ramirez-Ortiz 
306f072eea4SJorge Ramirez-Ortiz 	if (!src || !dst || !tag || !iv) {
307f072eea4SJorge Ramirez-Ortiz 		EMSG("Invalid input value");
308f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
309f072eea4SJorge Ramirez-Ortiz 	}
310f072eea4SJorge Ramirez-Ortiz 
311f072eea4SJorge Ramirez-Ortiz 	ret = aes_prepare_op(AES_DEC, key);
312f072eea4SJorge Ramirez-Ortiz 	if (ret) {
313f072eea4SJorge Ramirez-Ortiz 		EMSG("Decrypt init failed");
314f072eea4SJorge Ramirez-Ortiz 		goto out;
315f072eea4SJorge Ramirez-Ortiz 	}
316f072eea4SJorge Ramirez-Ortiz 
317f072eea4SJorge Ramirez-Ortiz 	ret = aes_transfer_dec(src, dst, src_len, tag, iv);
318f072eea4SJorge Ramirez-Ortiz 	if (ret) {
319f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA transfer failed");
320f072eea4SJorge Ramirez-Ortiz 		goto out;
321f072eea4SJorge Ramirez-Ortiz 	}
322f072eea4SJorge Ramirez-Ortiz 
323f072eea4SJorge Ramirez-Ortiz 	ret = aes_wait(AES_STS_AES_BUSY, false);
324f072eea4SJorge Ramirez-Ortiz 	if (ret)
325f072eea4SJorge Ramirez-Ortiz 		EMSG("AES-GCM transfer failed");
326f072eea4SJorge Ramirez-Ortiz out:
327f072eea4SJorge Ramirez-Ortiz 	return aes_done_op(AES_DEC, ret);
328f072eea4SJorge Ramirez-Ortiz }
329f072eea4SJorge Ramirez-Ortiz 
zynqmp_csu_aes_encrypt_data(const void * src,size_t src_len,void * dst,size_t dst_len,void * tag,size_t tag_len,const void * iv,size_t iv_len,enum zynqmp_csu_key key)330f072eea4SJorge Ramirez-Ortiz TEE_Result zynqmp_csu_aes_encrypt_data(const void *src, size_t src_len,
331f072eea4SJorge Ramirez-Ortiz 				       void *dst, size_t dst_len,
332f072eea4SJorge Ramirez-Ortiz 				       void *tag, size_t tag_len,
333f072eea4SJorge Ramirez-Ortiz 				       const void *iv, size_t iv_len,
334f072eea4SJorge Ramirez-Ortiz 				       enum zynqmp_csu_key key)
335f072eea4SJorge Ramirez-Ortiz {
336f072eea4SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
337f072eea4SJorge Ramirez-Ortiz 
338f072eea4SJorge Ramirez-Ortiz 	if (key != ZYNQMP_CSU_AES_KEY_SRC_DEV) {
339f072eea4SJorge Ramirez-Ortiz 		EMSG("Key type not supported");
340f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_NOT_IMPLEMENTED;
341f072eea4SJorge Ramirez-Ortiz 	}
342f072eea4SJorge Ramirez-Ortiz 
343f072eea4SJorge Ramirez-Ortiz 	if (src_len % 4 || dst_len != ZYNQMP_CSU_AES_DST_LEN(src_len)) {
344f072eea4SJorge Ramirez-Ortiz 		EMSG("Invalid source size");
345f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
346f072eea4SJorge Ramirez-Ortiz 	}
347f072eea4SJorge Ramirez-Ortiz 
348f072eea4SJorge Ramirez-Ortiz 	if (iv_len != ZYNQMP_GCM_IV_SIZE) {
349f072eea4SJorge Ramirez-Ortiz 		EMSG("Invalid IV size");
350f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
351f072eea4SJorge Ramirez-Ortiz 	}
352f072eea4SJorge Ramirez-Ortiz 
353f072eea4SJorge Ramirez-Ortiz 	if (tag_len != ZYNQMP_GCM_TAG_SIZE) {
354f072eea4SJorge Ramirez-Ortiz 		EMSG("Invalid tag size");
355f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
356f072eea4SJorge Ramirez-Ortiz 	}
357f072eea4SJorge Ramirez-Ortiz 
358f072eea4SJorge Ramirez-Ortiz 	if (!src || !dst || !tag || !iv) {
359f072eea4SJorge Ramirez-Ortiz 		EMSG("Invalid input value");
360f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
361f072eea4SJorge Ramirez-Ortiz 	}
362f072eea4SJorge Ramirez-Ortiz 
363f072eea4SJorge Ramirez-Ortiz 	ret = aes_prepare_op(AES_ENC, key);
364f072eea4SJorge Ramirez-Ortiz 	if (ret) {
365f072eea4SJorge Ramirez-Ortiz 		EMSG("Encrypt init failed");
366f072eea4SJorge Ramirez-Ortiz 		goto out;
367f072eea4SJorge Ramirez-Ortiz 	}
368f072eea4SJorge Ramirez-Ortiz 
369f072eea4SJorge Ramirez-Ortiz 	ret = aes_transfer_enc(src, dst, dst_len, tag, iv);
370f072eea4SJorge Ramirez-Ortiz 	if (ret) {
371f072eea4SJorge Ramirez-Ortiz 		EMSG("DMA transfer failed");
372f072eea4SJorge Ramirez-Ortiz 		goto out;
373f072eea4SJorge Ramirez-Ortiz 	}
374f072eea4SJorge Ramirez-Ortiz 
375f072eea4SJorge Ramirez-Ortiz 	ret = aes_wait(AES_STS_AES_BUSY, false);
376f072eea4SJorge Ramirez-Ortiz 	if (ret)
377f072eea4SJorge Ramirez-Ortiz 		EMSG("AES transfer failed");
378f072eea4SJorge Ramirez-Ortiz out:
379f072eea4SJorge Ramirez-Ortiz 	return aes_done_op(AES_ENC, ret);
380f072eea4SJorge Ramirez-Ortiz }
381f072eea4SJorge Ramirez-Ortiz 
382f072eea4SJorge Ramirez-Ortiz static const char *const dt_ctrl_match_table[] = {
383f072eea4SJorge Ramirez-Ortiz 	"xlnx,zynqmp-aes",
384f072eea4SJorge Ramirez-Ortiz };
385f072eea4SJorge Ramirez-Ortiz 
zynqmp_csu_aes_dt_enable_secure_status(void)386f072eea4SJorge Ramirez-Ortiz TEE_Result zynqmp_csu_aes_dt_enable_secure_status(void)
387f072eea4SJorge Ramirez-Ortiz {
388f072eea4SJorge Ramirez-Ortiz 	unsigned int i = 0;
389f072eea4SJorge Ramirez-Ortiz 	void *fdt = NULL;
390f072eea4SJorge Ramirez-Ortiz 	int node = -1;
391f072eea4SJorge Ramirez-Ortiz 
392f072eea4SJorge Ramirez-Ortiz 	fdt = get_external_dt();
393f072eea4SJorge Ramirez-Ortiz 	if (!fdt)
394f072eea4SJorge Ramirez-Ortiz 		return TEE_SUCCESS;
395f072eea4SJorge Ramirez-Ortiz 
396f072eea4SJorge Ramirez-Ortiz 	for (i = 0; i < ARRAY_SIZE(dt_ctrl_match_table); i++) {
397f072eea4SJorge Ramirez-Ortiz 		node = fdt_node_offset_by_compatible(fdt, 0,
398f072eea4SJorge Ramirez-Ortiz 						     dt_ctrl_match_table[i]);
399f072eea4SJorge Ramirez-Ortiz 		if (node >= 0)
400f072eea4SJorge Ramirez-Ortiz 			break;
401f072eea4SJorge Ramirez-Ortiz 	}
402f072eea4SJorge Ramirez-Ortiz 
403f072eea4SJorge Ramirez-Ortiz 	if (node < 0)
404f072eea4SJorge Ramirez-Ortiz 		return TEE_SUCCESS;
405f072eea4SJorge Ramirez-Ortiz 
406*f354a5d8SGatien Chevallier 	if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED)
407f072eea4SJorge Ramirez-Ortiz 		return TEE_SUCCESS;
408f072eea4SJorge Ramirez-Ortiz 
409f072eea4SJorge Ramirez-Ortiz 	if (dt_enable_secure_status(fdt, node)) {
410f072eea4SJorge Ramirez-Ortiz 		EMSG("Not able to set the AES-GCM DTB entry secure");
411f072eea4SJorge Ramirez-Ortiz 		return TEE_ERROR_NOT_SUPPORTED;
412f072eea4SJorge Ramirez-Ortiz 	}
413f072eea4SJorge Ramirez-Ortiz 
414f072eea4SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
415f072eea4SJorge Ramirez-Ortiz }
416