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