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