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