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