1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2022-2023, 2025 NXP 4 */ 5 #include <drivers/imx_mu.h> 6 #include <ele.h> 7 #include <initcall.h> 8 #include <kernel/boot.h> 9 #include <kernel/delay.h> 10 #include <kernel/panic.h> 11 #include <kernel/tee_common_otp.h> 12 #include <memutils.h> 13 #include <mm/core_memprot.h> 14 #include <mm/core_mmu.h> 15 #include <rng_support.h> 16 #include <stdint.h> 17 #include <string_ext.h> 18 #include <tee/cache.h> 19 #include <tee_api_defines.h> 20 #include <trace.h> 21 #include <types_ext.h> 22 #include <utee_types.h> 23 #include <util.h> 24 25 #define ELE_BASE_ADDR MU_BASE 26 #define ELE_BASE_SIZE MU_SIZE 27 28 #define ELE_VERSION_BASELINE 0x06 29 #define ELE_COMMAND_SUCCEED 0xd6 30 #define ELE_COMMAND_FAILED 0x29 31 #define ELE_RESPONSE_TAG 0xe1 32 33 #define ELE_CMD_SESSION_OPEN 0x10 34 #define ELE_CMD_SESSION_CLOSE 0x11 35 #define ELE_CMD_RNG_GET 0xCD 36 #define ELE_CMD_TRNG_STATE 0xA4 37 #define ELE_CMD_GET_INFO 0xDA 38 #define ELE_CMD_DERIVE_KEY 0xA9 39 #define ELE_CMD_SAB_INIT 0x17 40 41 #define IMX_ELE_TRNG_STATUS_READY 0x3 42 43 #define ELE_MU_IRQ 0x0 44 45 #define CACHELINE_SIZE 64 46 47 register_phys_mem_pgdir(MEM_AREA_IO_SEC, MU_BASE, MU_SIZE); 48 49 struct get_info_rsp { 50 uint32_t rsp_code; 51 uint16_t soc_id; 52 uint16_t soc_rev; 53 uint16_t lifecycle; 54 uint8_t sssm_state; 55 uint8_t unused_1; 56 uint32_t uid[4]; 57 uint32_t sha256_rom_patch[8]; 58 uint32_t sha256_firmware[8]; 59 uint32_t oem_srkh[16]; 60 uint8_t trng_state; 61 uint8_t csal_state; 62 #ifndef CFG_MX95 63 uint8_t imem_state; 64 uint8_t unused_2; 65 #else 66 uint8_t unused_2[2]; 67 uint32_t oem_pqc_srkh[16]; 68 uint32_t rsvd[8]; 69 #endif 70 } __packed; 71 72 struct response_code { 73 uint8_t status; 74 uint8_t rating; 75 uint16_t rating_extension; 76 } __packed; 77 78 /* 79 * Print ELE response status and rating 80 * 81 * @rsp response code structure 82 */ 83 static void print_rsp_code(struct response_code rsp __maybe_unused) 84 { 85 DMSG("Response status %#"PRIx8", rating %#"PRIx8" (ext %#"PRIx16")", 86 rsp.status, rsp.rating, rsp.rating_extension); 87 } 88 89 /* 90 * Print ELE message header 91 * 92 * @hdr message header 93 */ 94 static void print_msg_header(struct imx_mu_msg_header hdr __maybe_unused) 95 { 96 DMSG("Header ver %#"PRIx8", size %"PRId8", tag %#"PRIx8", cmd %#"PRIx8, 97 hdr.version, hdr.size, hdr.tag, hdr.command); 98 } 99 100 /* 101 * Print full ELE message content 102 * 103 * @msg message 104 */ 105 static void dump_message(const struct imx_mu_msg *msg __maybe_unused) 106 { 107 size_t i = 0; 108 size_t size __maybe_unused = msg->header.size; 109 uint32_t *data __maybe_unused = (uint32_t *)msg; 110 111 DMSG("Dump of message %p(%zu)", data, size); 112 for (i = 0; i < size; i++) 113 DMSG("word %zu: %#"PRIx32, i, data[i]); 114 } 115 116 /* 117 * The CRC for the message is computed xor-ing all the words of the message: 118 * the header and all the words except the word storing the CRC. 119 * 120 * @msg MU message to hash 121 */ 122 static uint32_t compute_crc(const struct imx_mu_msg *msg) 123 { 124 uint32_t crc = 0; 125 uint8_t i = 0; 126 uint32_t *payload = (uint32_t *)msg; 127 128 assert(msg); 129 130 for (i = 0; i < msg->header.size - 1; i++) 131 crc ^= payload[i]; 132 133 return crc; 134 } 135 136 void update_crc(struct imx_mu_msg *msg) 137 { 138 assert(msg); 139 /* 140 * The CRC field is the last element of array. The size of the header 141 * is also subtracted from CRC computation. 142 */ 143 msg->data.u32[msg->header.size - 2] = compute_crc(msg); 144 } 145 146 /* 147 * Return the given MU base address, depending on the MMU state. 148 * 149 * @pa MU physical base address 150 * @sz MU size 151 */ 152 static vaddr_t imx_ele_init(paddr_t pa, size_t sz) 153 { 154 static bool is_initialized; 155 vaddr_t va = 0; 156 157 assert(pa && sz); 158 159 if (cpu_mmu_enabled()) 160 va = core_mmu_get_va(pa, MEM_AREA_IO_SEC, sz); 161 else 162 va = (vaddr_t)pa; 163 164 if (!is_initialized) { 165 imx_mu_init(va); 166 is_initialized = true; 167 } 168 169 return va; 170 } 171 172 /* 173 * Extract response codes from the given word 174 * 175 * @word 32 bits word MU response 176 */ 177 static struct response_code get_response_code(uint32_t word) 178 { 179 struct response_code rsp = { 180 .rating_extension = (word & GENMASK_32(31, 16)) >> 16, 181 .rating = (word & GENMASK_32(15, 8)) >> 8, 182 .status = (word & GENMASK_32(7, 0)) >> 0, 183 }; 184 185 return rsp; 186 } 187 188 TEE_Result imx_ele_call(struct imx_mu_msg *msg) 189 { 190 TEE_Result res = TEE_ERROR_GENERIC; 191 struct response_code rsp = { }; 192 vaddr_t va = 0; 193 194 assert(msg); 195 196 if (msg->header.tag != ELE_REQUEST_TAG) { 197 EMSG("Request has invalid tag: %#"PRIx8" instead of %#"PRIx8, 198 msg->header.tag, ELE_REQUEST_TAG); 199 return TEE_ERROR_BAD_PARAMETERS; 200 } 201 202 va = imx_ele_init(ELE_BASE_ADDR, ELE_BASE_SIZE); 203 if (!va) { 204 EMSG("Fail to get base address"); 205 return TEE_ERROR_GENERIC; 206 } 207 208 res = imx_mu_call(va, msg, true); 209 if (res) { 210 EMSG("Failed to transmit message: %#"PRIx32, res); 211 print_msg_header(msg->header); 212 dump_message(msg); 213 return res; 214 } 215 216 rsp = get_response_code(msg->data.u32[0]); 217 218 if (msg->header.tag != ELE_RESPONSE_TAG) { 219 EMSG("Response has invalid tag: %#"PRIx8" instead of %#"PRIx8, 220 msg->header.tag, ELE_RESPONSE_TAG); 221 print_msg_header(msg->header); 222 return TEE_ERROR_GENERIC; 223 } 224 225 if (rsp.status != ELE_COMMAND_SUCCEED) { 226 EMSG("Command has failed"); 227 print_rsp_code(rsp); 228 return TEE_ERROR_GENERIC; 229 } 230 231 /* The rating can be different in success and failing cases */ 232 if (rsp.rating != 0) { 233 EMSG("Command has invalid rating: %#"PRIx8, rsp.rating); 234 print_rsp_code(rsp); 235 return TEE_ERROR_GENERIC; 236 } 237 238 return TEE_SUCCESS; 239 } 240 241 /* 242 * Open a session with EdgeLock Enclave. It returns a session handle. 243 * 244 * @session_handle EdgeLock Enclave session handle 245 */ 246 static TEE_Result __maybe_unused imx_ele_session_open(uint32_t *session_handle) 247 { 248 TEE_Result res = TEE_ERROR_GENERIC; 249 struct open_session_cmd { 250 uint8_t rsvd1; 251 uint8_t interrupt_num; 252 uint16_t rsvd2; 253 uint8_t priority; 254 uint8_t op_mode; 255 uint16_t rsvd3; 256 } __packed cmd = { 257 .rsvd1 = 0, 258 .interrupt_num = ELE_MU_IRQ, 259 .rsvd2 = 0, 260 .priority = 0, 261 .op_mode = 0, 262 .rsvd3 = 0, 263 }; 264 struct open_session_rsp { 265 uint32_t rsp_code; 266 uint32_t session_handle; 267 } rsp = { }; 268 struct imx_mu_msg msg = { 269 .header.version = ELE_VERSION_HSM, 270 .header.size = SIZE_MSG_32(cmd), 271 .header.tag = ELE_REQUEST_TAG, 272 .header.command = ELE_CMD_SESSION_OPEN, 273 }; 274 275 assert(session_handle); 276 277 memcpy(msg.data.u8, &cmd, sizeof(cmd)); 278 279 res = imx_ele_call(&msg); 280 if (res) 281 return res; 282 283 memcpy(&rsp, msg.data.u8, sizeof(rsp)); 284 285 *session_handle = rsp.session_handle; 286 287 return TEE_SUCCESS; 288 } 289 290 /* 291 * Close a session with EdgeLock Enclave. 292 * 293 * @session_handle EdgeLock Enclave session handle 294 */ 295 static TEE_Result __maybe_unused imx_ele_session_close(uint32_t session_handle) 296 { 297 struct close_session_cmd { 298 uint32_t session_handle; 299 } cmd = { 300 .session_handle = session_handle, 301 }; 302 struct imx_mu_msg msg = { 303 .header.version = ELE_VERSION_HSM, 304 .header.size = SIZE_MSG_32(cmd), 305 .header.tag = ELE_REQUEST_TAG, 306 .header.command = ELE_CMD_SESSION_CLOSE, 307 }; 308 309 memcpy(msg.data.u8, &cmd, sizeof(cmd)); 310 311 return imx_ele_call(&msg); 312 } 313 314 static TEE_Result imx_ele_get_device_info(struct get_info_rsp *rsp) 315 { 316 TEE_Result res = TEE_ERROR_GENERIC; 317 struct imx_ele_buf output = { }; 318 struct { 319 uint32_t addr_msb; 320 uint32_t addr_lsb; 321 uint16_t size; 322 } __packed cmd = { }; 323 struct imx_mu_msg msg = { 324 .header.version = ELE_VERSION_BASELINE, 325 .header.size = SIZE_MSG_32(cmd), 326 .header.tag = ELE_REQUEST_TAG, 327 .header.command = ELE_CMD_GET_INFO, 328 }; 329 330 if (!rsp) 331 return TEE_ERROR_BAD_PARAMETERS; 332 333 res = imx_ele_buf_alloc(&output, NULL, sizeof(*rsp)); 334 if (res) 335 goto out; 336 337 cmd.addr_msb = output.paddr_msb; 338 cmd.addr_lsb = output.paddr_lsb; 339 cmd.size = sizeof(*rsp); 340 341 memcpy(msg.data.u8, &cmd, sizeof(cmd)); 342 343 res = imx_ele_call(&msg); 344 if (res) 345 goto out; 346 347 res = imx_ele_buf_copy(&output, (uint8_t *)rsp, sizeof(*rsp)); 348 out: 349 imx_ele_buf_free(&output); 350 351 return res; 352 } 353 354 int tee_otp_get_die_id(uint8_t *buffer, size_t len) 355 { 356 static uint32_t uid[4]; 357 static bool is_fetched; 358 struct get_info_rsp rsp = { }; 359 360 assert(buffer && len); 361 362 if (!is_fetched) { 363 if (imx_ele_get_device_info(&rsp)) 364 panic("Fail to get the device UID"); 365 366 memcpy(uid, rsp.uid, MIN(sizeof(rsp.uid), len)); 367 is_fetched = true; 368 } 369 370 memcpy(buffer, uid, MIN(sizeof(uid), len)); 371 372 return 0; 373 } 374 375 /* 376 * Initialize EdgeLock Enclave services 377 */ 378 static TEE_Result imx_ele_sab_init(void) 379 { 380 struct imx_mu_msg msg = { 381 .header.version = ELE_VERSION_HSM, 382 .header.size = 1, 383 .header.tag = ELE_REQUEST_TAG, 384 .header.command = ELE_CMD_SAB_INIT, 385 }; 386 387 return imx_ele_call(&msg); 388 } 389 390 driver_init(imx_ele_sab_init); 391 392 #if defined(CFG_MX93) || defined(CFG_MX91) || defined(CFG_MX95) 393 static TEE_Result imx_ele_derive_key(const uint8_t *ctx, size_t ctx_size, 394 uint8_t *key, size_t key_size) 395 { 396 TEE_Result res = TEE_ERROR_GENERIC; 397 struct key_derive_cmd { 398 uint32_t key_addr_msb; 399 uint32_t key_addr_lsb; 400 uint32_t ctx_addr_msb; 401 uint32_t ctx_addr_lsb; 402 uint16_t key_size; 403 uint16_t ctx_size; 404 uint32_t crc; 405 } __packed cmd = { }; 406 struct imx_mu_msg msg = { 407 .header.version = ELE_VERSION_BASELINE, 408 .header.size = SIZE_MSG_32(cmd), 409 .header.tag = ELE_REQUEST_TAG, 410 .header.command = ELE_CMD_DERIVE_KEY, 411 }; 412 struct imx_ele_buf ele_ctx = { }; 413 struct imx_ele_buf ele_key = { }; 414 415 assert(ctx && key); 416 417 if (key_size != 16 && key_size != 32) 418 return TEE_ERROR_BAD_PARAMETERS; 419 420 res = imx_ele_buf_alloc(&ele_ctx, ctx, ctx_size); 421 if (res) 422 goto out; 423 424 res = imx_ele_buf_alloc(&ele_key, key, key_size); 425 if (res) 426 goto out; 427 428 cmd.key_addr_lsb = ele_key.paddr_lsb; 429 cmd.key_addr_msb = ele_key.paddr_msb; 430 cmd.key_size = key_size; 431 432 cmd.ctx_addr_lsb = ele_ctx.paddr_lsb; 433 cmd.ctx_addr_msb = ele_ctx.paddr_msb; 434 cmd.ctx_size = ctx_size; 435 436 memcpy(msg.data.u8, &cmd, sizeof(cmd)); 437 update_crc(&msg); 438 439 res = imx_ele_call(&msg); 440 if (res) 441 goto out; 442 443 res = imx_ele_buf_copy(&ele_key, key, key_size); 444 out: 445 imx_ele_buf_free(&ele_key); 446 imx_ele_buf_free(&ele_ctx); 447 448 return res; 449 } 450 451 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) 452 { 453 static const char pattern[] = "TEE_for_HUK_ELE"; 454 static uint8_t key[HW_UNIQUE_KEY_LENGTH]; 455 static bool is_fetched; 456 457 if (is_fetched) 458 goto out; 459 460 if (imx_ele_derive_key((const uint8_t *)pattern, sizeof(pattern), key, 461 sizeof(key))) 462 panic("Fail to get HUK from ELE"); 463 464 is_fetched = true; 465 out: 466 memcpy(hwkey->data, key, 467 MIN(sizeof(key), (size_t)HW_UNIQUE_KEY_LENGTH)); 468 469 return TEE_SUCCESS; 470 } 471 472 /* 473 * Get the current state of the ELE TRNG 474 */ 475 static TEE_Result imx_ele_rng_get_trng_state(void) 476 { 477 TEE_Result res = TEE_ERROR_GENERIC; 478 struct rng_get_trng_state_msg_rsp { 479 uint32_t rsp_code; 480 uint8_t trng_state; 481 uint8_t csal_state; 482 } __packed rsp = { }; 483 struct imx_mu_msg msg = { 484 .header.version = ELE_VERSION_BASELINE, 485 .header.size = 1, 486 .header.tag = ELE_REQUEST_TAG, 487 .header.command = ELE_CMD_TRNG_STATE, 488 }; 489 490 res = imx_ele_call(&msg); 491 if (res) 492 return res; 493 494 memcpy(&rsp, msg.data.u8, sizeof(rsp)); 495 496 if (rsp.trng_state != IMX_ELE_TRNG_STATUS_READY) 497 return TEE_ERROR_BUSY; 498 else 499 return TEE_SUCCESS; 500 } 501 502 /* 503 * Get random data from the EdgeLock Enclave. 504 * 505 * This function can be called when the MMU is off or on. 506 * virtual/physical address translation and cache maintenance 507 * is performed if needed. 508 * 509 * @buffer: data output 510 * @size: RNG data size 511 */ 512 static TEE_Result imx_ele_rng_get_random(uint8_t *buffer, size_t size) 513 { 514 TEE_Result res = TEE_ERROR_GENERIC; 515 struct imx_ele_buf rng = { }; 516 struct rng_get_random_cmd { 517 uint32_t addr_msb; 518 uint32_t addr_lsb; 519 uint32_t size; 520 } cmd = { }; 521 struct imx_mu_msg msg = { 522 .header.version = ELE_VERSION_HSM, 523 .header.size = SIZE_MSG_32(cmd), 524 .header.tag = ELE_REQUEST_TAG, 525 .header.command = ELE_CMD_RNG_GET, 526 }; 527 528 if (!buffer || !size) 529 return TEE_ERROR_BAD_PARAMETERS; 530 531 if (cpu_mmu_enabled()) { 532 res = imx_ele_buf_alloc(&rng, NULL, size); 533 if (res != TEE_SUCCESS) 534 return res; 535 536 cmd.addr_msb = rng.paddr_msb; 537 cmd.addr_lsb = rng.paddr_lsb; 538 } else { 539 paddr_t pa = (paddr_t)buffer; 540 541 if (!IS_ALIGNED_WITH_TYPE(pa, uint32_t)) 542 return TEE_ERROR_BAD_PARAMETERS; 543 544 reg_pair_from_64((uint64_t)pa, &cmd.addr_msb, &cmd.addr_lsb); 545 } 546 547 cmd.size = (uint32_t)size; 548 549 memcpy(msg.data.u8, &cmd, sizeof(cmd)); 550 551 res = imx_ele_call(&msg); 552 if (res) 553 goto out; 554 555 if (cpu_mmu_enabled()) 556 res = imx_ele_buf_copy(&rng, buffer, size); 557 out: 558 imx_ele_buf_free(&rng); 559 560 return res; 561 } 562 563 unsigned long plat_get_aslr_seed(void) 564 { 565 uint64_t timeout = timeout_init_us(10 * 1000); 566 unsigned long __aligned(CACHELINE_SIZE) aslr = 0; 567 568 /* 569 * Check the current TRNG state of the ELE. The TRNG must be 570 * started with a command earlier in the boot to allow the TRNG 571 * to generate enough entropy. 572 */ 573 while (imx_ele_rng_get_trng_state() == TEE_ERROR_BUSY) 574 if (timeout_elapsed(timeout)) 575 panic("ELE RNG is busy"); 576 577 if (imx_ele_rng_get_random((uint8_t *)&aslr, sizeof(aslr))) 578 panic("Cannot retrieve random data from ELE"); 579 580 return aslr; 581 } 582 583 #ifndef CFG_WITH_SOFTWARE_PRNG 584 TEE_Result hw_get_random_bytes(void *buf, size_t len) 585 { 586 return imx_ele_rng_get_random((uint8_t *)buf, len); 587 } 588 #endif /* CFG_WITH_SOFTWARE_PRNG */ 589 #endif /* CFG_MX93 || CFG_MX91 */ 590