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