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