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 */
print_rsp_code(struct response_code rsp __maybe_unused)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 */
print_msg_header(struct imx_mu_msg_header hdr __maybe_unused)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 */
dump_message(const struct imx_mu_msg * msg __maybe_unused)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 */
compute_crc(const struct imx_mu_msg * msg)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
update_crc(struct imx_mu_msg * msg)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 */
imx_ele_init(paddr_t pa,size_t sz)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 */
get_response_code(uint32_t word)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
imx_ele_call(struct imx_mu_msg * msg)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 */
imx_ele_session_open(uint32_t * session_handle)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 */
imx_ele_session_close(uint32_t session_handle)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
imx_ele_get_device_info(struct get_info_rsp * rsp)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
tee_otp_get_die_id(uint8_t * buffer,size_t len)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 #if defined(CFG_MX93) || defined(CFG_MX91) || defined(CFG_MX95)
imx_ele_derive_key(const uint8_t * ctx,size_t ctx_size,uint8_t * key,size_t key_size)376 static TEE_Result imx_ele_derive_key(const uint8_t *ctx, size_t ctx_size,
377 uint8_t *key, size_t key_size)
378 {
379 TEE_Result res = TEE_ERROR_GENERIC;
380 struct key_derive_cmd {
381 uint32_t key_addr_msb;
382 uint32_t key_addr_lsb;
383 uint32_t ctx_addr_msb;
384 uint32_t ctx_addr_lsb;
385 uint16_t key_size;
386 uint16_t ctx_size;
387 uint32_t crc;
388 } __packed cmd = { };
389 struct imx_mu_msg msg = {
390 .header.version = ELE_VERSION_BASELINE,
391 .header.size = SIZE_MSG_32(cmd),
392 .header.tag = ELE_REQUEST_TAG,
393 .header.command = ELE_CMD_DERIVE_KEY,
394 };
395 struct imx_ele_buf ele_ctx = { };
396 struct imx_ele_buf ele_key = { };
397
398 assert(ctx && key);
399
400 if (key_size != 16 && key_size != 32)
401 return TEE_ERROR_BAD_PARAMETERS;
402
403 res = imx_ele_buf_alloc(&ele_ctx, ctx, ctx_size);
404 if (res)
405 goto out;
406
407 res = imx_ele_buf_alloc(&ele_key, key, key_size);
408 if (res)
409 goto out;
410
411 cmd.key_addr_lsb = ele_key.paddr_lsb;
412 cmd.key_addr_msb = ele_key.paddr_msb;
413 cmd.key_size = key_size;
414
415 cmd.ctx_addr_lsb = ele_ctx.paddr_lsb;
416 cmd.ctx_addr_msb = ele_ctx.paddr_msb;
417 cmd.ctx_size = ctx_size;
418
419 memcpy(msg.data.u8, &cmd, sizeof(cmd));
420 update_crc(&msg);
421
422 res = imx_ele_call(&msg);
423 if (res)
424 goto out;
425
426 res = imx_ele_buf_copy(&ele_key, key, key_size);
427 out:
428 imx_ele_buf_free(&ele_key);
429 imx_ele_buf_free(&ele_ctx);
430
431 return res;
432 }
433
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)434 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
435 {
436 static const char pattern[] = "TEE_for_HUK_ELE";
437 static uint8_t key[HW_UNIQUE_KEY_LENGTH];
438 static bool is_fetched;
439
440 if (is_fetched)
441 goto out;
442
443 if (imx_ele_derive_key((const uint8_t *)pattern, sizeof(pattern), key,
444 sizeof(key)))
445 panic("Fail to get HUK from ELE");
446
447 is_fetched = true;
448 out:
449 memcpy(hwkey->data, key,
450 MIN(sizeof(key), (size_t)HW_UNIQUE_KEY_LENGTH));
451
452 return TEE_SUCCESS;
453 }
454
455 /*
456 * Get the current state of the ELE TRNG
457 */
imx_ele_rng_get_trng_state(void)458 static TEE_Result imx_ele_rng_get_trng_state(void)
459 {
460 TEE_Result res = TEE_ERROR_GENERIC;
461 struct rng_get_trng_state_msg_rsp {
462 uint32_t rsp_code;
463 uint8_t trng_state;
464 uint8_t csal_state;
465 } __packed rsp = { };
466 struct imx_mu_msg msg = {
467 .header.version = ELE_VERSION_BASELINE,
468 .header.size = 1,
469 .header.tag = ELE_REQUEST_TAG,
470 .header.command = ELE_CMD_TRNG_STATE,
471 };
472
473 res = imx_ele_call(&msg);
474 if (res)
475 return res;
476
477 memcpy(&rsp, msg.data.u8, sizeof(rsp));
478
479 if (rsp.trng_state != IMX_ELE_TRNG_STATUS_READY)
480 return TEE_ERROR_BUSY;
481 else
482 return TEE_SUCCESS;
483 }
484
485 /*
486 * Get random data from the EdgeLock Enclave.
487 *
488 * This function can be called when the MMU is off or on.
489 * virtual/physical address translation and cache maintenance
490 * is performed if needed.
491 *
492 * @buffer: data output
493 * @size: RNG data size
494 */
imx_ele_rng_get_random(uint8_t * buffer,size_t size)495 static TEE_Result imx_ele_rng_get_random(uint8_t *buffer, size_t size)
496 {
497 TEE_Result res = TEE_ERROR_GENERIC;
498 struct imx_ele_buf rng = { };
499 struct rng_get_random_cmd {
500 uint32_t addr_msb;
501 uint32_t addr_lsb;
502 uint32_t size;
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
511 if (!buffer || !size)
512 return TEE_ERROR_BAD_PARAMETERS;
513
514 if (cpu_mmu_enabled()) {
515 res = imx_ele_buf_alloc(&rng, NULL, size);
516 if (res != TEE_SUCCESS)
517 return res;
518
519 cmd.addr_msb = rng.paddr_msb;
520 cmd.addr_lsb = rng.paddr_lsb;
521 } else {
522 paddr_t pa = (paddr_t)buffer;
523
524 if (!IS_ALIGNED_WITH_TYPE(pa, uint32_t))
525 return TEE_ERROR_BAD_PARAMETERS;
526
527 reg_pair_from_64((uint64_t)pa, &cmd.addr_msb, &cmd.addr_lsb);
528 }
529
530 cmd.size = (uint32_t)size;
531
532 memcpy(msg.data.u8, &cmd, sizeof(cmd));
533
534 res = imx_ele_call(&msg);
535 if (res)
536 goto out;
537
538 if (cpu_mmu_enabled())
539 res = imx_ele_buf_copy(&rng, buffer, size);
540 out:
541 imx_ele_buf_free(&rng);
542
543 return res;
544 }
545
plat_get_aslr_seed(void)546 unsigned long plat_get_aslr_seed(void)
547 {
548 uint64_t timeout = timeout_init_us(10 * 1000);
549 unsigned long __aligned(CACHELINE_SIZE) aslr = 0;
550
551 /*
552 * Check the current TRNG state of the ELE. The TRNG must be
553 * started with a command earlier in the boot to allow the TRNG
554 * to generate enough entropy.
555 */
556 while (imx_ele_rng_get_trng_state() == TEE_ERROR_BUSY)
557 if (timeout_elapsed(timeout))
558 panic("ELE RNG is busy");
559
560 if (imx_ele_rng_get_random((uint8_t *)&aslr, sizeof(aslr)))
561 panic("Cannot retrieve random data from ELE");
562
563 return aslr;
564 }
565
566 #ifndef CFG_WITH_SOFTWARE_PRNG
hw_get_random_bytes(void * buf,size_t len)567 TEE_Result hw_get_random_bytes(void *buf, size_t len)
568 {
569 return imx_ele_rng_get_random((uint8_t *)buf, len);
570 }
571 #endif /* CFG_WITH_SOFTWARE_PRNG */
572 #endif /* CFG_MX93 || CFG_MX91 */
573