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 */
print_rsp_code(struct response_code rsp __maybe_unused)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 */
print_msg_header(struct imx_mu_msg_header hdr __maybe_unused)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 */
dump_message(const struct imx_mu_msg * msg __maybe_unused)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 */
size_msg_32(size_t cmd)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 */
compute_crc(const struct imx_mu_msg * msg)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 */
update_crc(struct imx_mu_msg * msg)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 */
imx_ele_init(paddr_t pa,size_t sz)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 */
get_response_code(uint32_t word)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 */
imx_ele_call(struct imx_mu_msg * msg)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
imx_ele_session_get_device_info(uint32_t session_handle,struct session_get_device_info_rsp * rsp)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 */
imx_ele_session_open(uint32_t * session_handle)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 */
imx_ele_session_close(uint32_t session_handle)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 */
imx_ele_rng_get_trng_state(void)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
plat_get_aslr_seed(void)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
tee_otp_get_die_id(uint8_t * buffer,size_t len)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)
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)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