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