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