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