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