xref: /optee_os/core/drivers/crypto/ele/ele.c (revision 66810831378ac65da0a51d75b7a87c47e007989d)
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 <stdint.h>
16 #include <tee/cache.h>
17 #include <tee_api_defines.h>
18 #include <trace.h>
19 #include <types_ext.h>
20 #include <utee_types.h>
21 #include <util.h>
22 
23 #define ELE_BASE_ADDR MU_BASE
24 #define ELE_BASE_SIZE MU_SIZE
25 
26 #define ELE_VERSION_BASELINE 0x06
27 #define ELE_COMMAND_SUCCEED 0xd6
28 #define ELE_COMMAND_FAILED  0x29
29 #define ELE_RESPONSE_TAG    0xe1
30 
31 #define ELE_CMD_SESSION_OPEN	    0x10
32 #define ELE_CMD_SESSION_CLOSE	    0x11
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_rsp {
56 	uint32_t rsp_code;
57 	uint16_t soc_id;
58 	uint16_t soc_rev;
59 	uint16_t lifecycle;
60 	uint8_t sssm_state;
61 	uint8_t unused_1;
62 	uint32_t uid[4];
63 	uint32_t sha256_rom_patch[8];
64 	uint32_t sha256_firmware[8];
65 	uint32_t oem_srkh[16];
66 	uint8_t trng_state;
67 	uint8_t csal_state;
68 	uint8_t imem_state;
69 	uint8_t unused_2;
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  */
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  */
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  */
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  */
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 
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  */
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  */
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 
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  */
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 mu_id;
251 		uint8_t interrupt_num;
252 		uint8_t tz;
253 		uint8_t did;
254 		uint8_t priority;
255 		uint8_t op_mode;
256 		uint16_t reserved;
257 	} __packed cmd = {
258 		.mu_id = ELE_MU_ID,
259 		.interrupt_num = ELE_MU_IRQ,
260 		.tz = 0,
261 		.did = ELE_MU_DID,
262 		.priority = 0,
263 		.op_mode = 0,
264 		.reserved = 0,
265 	};
266 	struct open_session_rsp {
267 		uint32_t rsp_code;
268 		uint32_t session_handle;
269 	} rsp = { };
270 	struct imx_mu_msg msg = {
271 		.header.version = ELE_VERSION_HSM,
272 		.header.size = SIZE_MSG_32(cmd),
273 		.header.tag = ELE_REQUEST_TAG,
274 		.header.command = ELE_CMD_SESSION_OPEN,
275 	};
276 
277 	assert(session_handle);
278 
279 	memcpy(msg.data.u8, &cmd, sizeof(cmd));
280 
281 	res = imx_ele_call(&msg);
282 	if (res)
283 		return res;
284 
285 	memcpy(&rsp, msg.data.u8, sizeof(rsp));
286 
287 	*session_handle = rsp.session_handle;
288 
289 	return TEE_SUCCESS;
290 }
291 
292 /*
293  * Close a session with EdgeLock Enclave.
294  *
295  * @session_handle EdgeLock Enclave session handle
296  */
297 static TEE_Result __maybe_unused imx_ele_session_close(uint32_t session_handle)
298 {
299 	struct close_session_cmd {
300 		uint32_t session_handle;
301 	} cmd = {
302 		.session_handle = session_handle,
303 	};
304 	struct imx_mu_msg msg = {
305 		.header.version = ELE_VERSION_HSM,
306 		.header.size = SIZE_MSG_32(cmd),
307 		.header.tag = ELE_REQUEST_TAG,
308 		.header.command = ELE_CMD_SESSION_CLOSE,
309 	};
310 
311 	memcpy(msg.data.u8, &cmd, sizeof(cmd));
312 
313 	return imx_ele_call(&msg);
314 }
315 
316 static TEE_Result imx_ele_get_device_info(struct get_info_rsp *rsp)
317 {
318 	TEE_Result res = TEE_ERROR_GENERIC;
319 	struct imx_ele_buf output = { };
320 	struct {
321 		uint32_t addr_msb;
322 		uint32_t addr_lsb;
323 		uint16_t size;
324 	} __packed cmd = { };
325 	struct imx_mu_msg msg = {
326 		.header.version = ELE_VERSION_BASELINE,
327 		.header.size = SIZE_MSG_32(cmd),
328 		.header.tag = ELE_REQUEST_TAG,
329 		.header.command = ELE_CMD_GET_INFO,
330 	};
331 
332 	if (!rsp)
333 		return TEE_ERROR_BAD_PARAMETERS;
334 
335 	res = imx_ele_buf_alloc(&output, NULL, sizeof(*rsp));
336 	if (res)
337 		goto out;
338 
339 	cmd.addr_msb = output.paddr_msb;
340 	cmd.addr_lsb = output.paddr_lsb;
341 	cmd.size = sizeof(*rsp);
342 
343 	memcpy(msg.data.u8, &cmd, sizeof(cmd));
344 
345 	res = imx_ele_call(&msg);
346 	if (res)
347 		goto out;
348 
349 	res = imx_ele_buf_copy(&output, (uint8_t *)rsp, sizeof(*rsp));
350 out:
351 	imx_ele_buf_free(&output);
352 
353 	return res;
354 }
355 
356 int tee_otp_get_die_id(uint8_t *buffer, size_t len)
357 {
358 	static uint32_t uid[4];
359 	static bool is_fetched;
360 	struct get_info_rsp rsp = { };
361 
362 	assert(buffer && len);
363 
364 	if (!is_fetched) {
365 		if (imx_ele_get_device_info(&rsp))
366 			panic("Fail to get the device UID");
367 
368 		memcpy(uid, rsp.uid, MIN(sizeof(rsp.uid), len));
369 		is_fetched = true;
370 	}
371 
372 	memcpy(buffer, uid, MIN(sizeof(uid), len));
373 
374 	return 0;
375 }
376 
377 #if defined(CFG_MX93) || defined(CFG_MX91)
378 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
379 {
380 	TEE_Result res = TEE_ERROR_GENERIC;
381 	const char pattern[16] __aligned(CACHELINE_SIZE) = "TEE_for_HUK_ELE";
382 	static uint8_t key[CACHELINE_SIZE] __aligned(CACHELINE_SIZE);
383 	static bool is_fetched;
384 	uint32_t msb = 0;
385 	uint32_t lsb = 0;
386 	struct key_derive_cmd {
387 		uint32_t key_addr_msb;
388 		uint32_t key_addr_lsb;
389 		uint32_t ctx_addr_msb;
390 		uint32_t ctx_addr_lsb;
391 		uint16_t key_size;
392 		uint16_t ctx_size;
393 		uint32_t crc;
394 	} __packed cmd = { };
395 	struct imx_mu_msg msg = {
396 		.header.version = ELE_VERSION_BASELINE,
397 		.header.size = SIZE_MSG_32(cmd),
398 		.header.tag = ELE_REQUEST_TAG,
399 		.header.command = ELE_CMD_DERIVE_KEY,
400 	};
401 
402 	if (is_fetched)
403 		goto out;
404 
405 	/*
406 	 * Intermediate msb and lsb values are needed. Directly using
407 	 * key_addr_msb and key_addr_lsb might be unaligned because of the
408 	 * __packed attribute of key_derive_cmd {}
409 	 */
410 	reg_pair_from_64((uint64_t)virt_to_phys(key), &msb, &lsb);
411 
412 	cmd.key_addr_lsb = lsb;
413 	cmd.key_addr_msb = msb;
414 	cmd.key_size = HW_UNIQUE_KEY_LENGTH;
415 
416 	reg_pair_from_64((uint64_t)virt_to_phys((void *)pattern), &msb, &lsb);
417 
418 	cmd.ctx_addr_lsb = lsb;
419 	cmd.ctx_addr_msb = msb;
420 	cmd.ctx_size = sizeof(pattern);
421 
422 	memcpy(msg.data.u8, &cmd, sizeof(cmd));
423 	update_crc(&msg);
424 
425 	cache_operation(TEE_CACHEFLUSH, key, HW_UNIQUE_KEY_LENGTH);
426 	cache_operation(TEE_CACHECLEAN, (void *)pattern, sizeof(pattern));
427 
428 	res = imx_ele_call(&msg);
429 	if (res)
430 		panic("failed to get the huk");
431 
432 	cache_operation(TEE_CACHEINVALIDATE, key, HW_UNIQUE_KEY_LENGTH);
433 	is_fetched = true;
434 out:
435 	memcpy(hwkey->data, key,
436 	       MIN(sizeof(key), (size_t)HW_UNIQUE_KEY_LENGTH));
437 
438 	return TEE_SUCCESS;
439 }
440 
441 /*
442  * Get the current state of the ELE TRNG
443  */
444 static TEE_Result imx_ele_rng_get_trng_state(void)
445 {
446 	TEE_Result res = TEE_ERROR_GENERIC;
447 	struct rng_get_trng_state_msg_rsp {
448 		uint32_t rsp_code;
449 		uint8_t trng_state;
450 		uint8_t csal_state;
451 	} __packed rsp = { };
452 	struct imx_mu_msg msg = {
453 		.header.version = ELE_VERSION_BASELINE,
454 		.header.size = 1,
455 		.header.tag = ELE_REQUEST_TAG,
456 		.header.command = ELE_CMD_TRNG_STATE,
457 	};
458 
459 	res = imx_ele_call(&msg);
460 	if (res)
461 		return res;
462 
463 	memcpy(&rsp, msg.data.u8, sizeof(rsp));
464 
465 	if (rsp.trng_state != IMX_ELE_TRNG_STATUS_READY)
466 		return TEE_ERROR_BUSY;
467 	else
468 		return TEE_SUCCESS;
469 }
470 
471 unsigned long plat_get_aslr_seed(void)
472 {
473 	TEE_Result res = TEE_ERROR_GENERIC;
474 	uint64_t timeout = timeout_init_us(10 * 1000);
475 	struct rng_get_random_cmd {
476 		uint32_t addr_msb;
477 		uint32_t addr_lsb;
478 		uint32_t size;
479 		uint32_t crc;
480 	} cmd = { };
481 	struct imx_mu_msg msg = {
482 		.header.version = ELE_VERSION_HSM,
483 		.header.size = SIZE_MSG_32(cmd),
484 		.header.tag = ELE_REQUEST_TAG,
485 		.header.command = ELE_CMD_RNG_GET,
486 	};
487 	unsigned long aslr __aligned(CACHELINE_SIZE) = 0;
488 
489 	/*
490 	 * This function can only be called when the MMU is off. No
491 	 * virtual/physical address translation is performed, nor cache
492 	 * maintenance.
493 	 */
494 	assert(!cpu_mmu_enabled());
495 
496 	reg_pair_from_64((uint64_t)&aslr, &cmd.addr_msb, &cmd.addr_lsb);
497 	cmd.size = sizeof(aslr);
498 
499 	/*
500 	 * Check the current TRNG state of the ELE. The TRNG must be
501 	 * started with a command earlier in the boot to allow the TRNG
502 	 * to generate enough entropy.
503 	 */
504 	while (imx_ele_rng_get_trng_state() == TEE_ERROR_BUSY)
505 		if (timeout_elapsed(timeout))
506 			panic("ELE RNG is busy");
507 
508 	memcpy(msg.data.u8, &cmd, sizeof(cmd));
509 	update_crc(&msg);
510 
511 	res = imx_ele_call(&msg);
512 	if (res)
513 		panic("Cannot retrieve random data from ELE");
514 
515 	return aslr;
516 }
517 #endif /* CFG_MX93 || CFG_MX91 */
518