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