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