xref: /optee_os/core/arch/arm/plat-rockchip/platform_rk3588.c (revision 6cb05ea90ccf9cea168d68a77d38c6e4ebb35485)
1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
4  * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
5  */
6 
7 #include <assert.h>
8 #include <common.h>
9 #include <drivers/rockchip_otp.h>
10 #include <io.h>
11 #include <kernel/panic.h>
12 #include <kernel/mutex.h>
13 #include <kernel/tee_common_otp.h>
14 #include <mm/core_memprot.h>
15 #include <platform.h>
16 #include <platform_config.h>
17 #include <rng_support.h>
18 #include <stdlib_ext.h>
19 #include <string.h>
20 #include <string_ext.h>
21 #include <utee_defines.h>
22 
23 #define FIREWALL_DDR_RGN(i)		((i) * 0x4)
24 #define FIREWALL_DDR_CON		0xf0
25 #define FIREWALL_DSU_RGN(i)		((i) * 0x4)
26 #define FIREWALL_DSU_CON(i)		(0xf0 + ((i) * 0x4))
27 
28 #define RG_MAP_SECURE(top, base)	\
29 	(((((top) - 1) & 0x7fff) << 16) | ((base) & 0x7fff))
30 
31 #define DDR_CHN_CNT			4
32 
33 #define TRNG_S_CTRL		0x0000
34 #define TRNG_S_STAT		0x0004
35 #define TRNG_S_MODE		0x0008
36 #define TRNG_S_IE		0x0010
37 #define TRNG_S_ISTAT		0x0014
38 #define TRNG_S_RAND		0x0020
39 #define TRNG_S_AUTO_RQSTS	0x0060
40 
41 #define CMD_NOP			0
42 #define CMD_RAND		1
43 #define CMD_SEED		2
44 
45 #define LEN_128BIT		0
46 #define LEN_256BIT		3
47 
48 #define TRNG_S_SEEDED_BIT	BIT32(9)
49 #define TRNG_S_SEED_DONE_BIT	BIT32(1)
50 #define TRNG_S_RAND_RDY_BIT	BIT32(0)
51 
52 #define TRNG_POLL_PERIOD_US	0
53 #define TRNG_POLL_TIMEOUT_US	1000
54 
55 register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE);
56 register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DSU_BASE, FIREWALL_DSU_SIZE);
57 register_phys_mem_pgdir(MEM_AREA_IO_SEC, TRNG_S_BASE, TRNG_S_SIZE);
58 
59 static struct mutex trng_mutex = MUTEX_INITIALIZER;
60 static struct mutex huk_mutex = MUTEX_INITIALIZER;
61 
62 /* Cache the HUK in memory */
63 static struct tee_hw_unique_key *huk;
64 
platform_secure_ddr_region(int rgn,paddr_t st,size_t sz)65 int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz)
66 {
67 	vaddr_t fw_ddr_base = (vaddr_t)phys_to_virt_io(FIREWALL_DDR_BASE,
68 						       FIREWALL_DDR_SIZE);
69 	vaddr_t fw_dsu_base = (vaddr_t)phys_to_virt_io(FIREWALL_DSU_BASE,
70 						       FIREWALL_DSU_SIZE);
71 	paddr_t ed = st + sz;
72 	uint32_t st_mb = st / SIZE_M(1);
73 	uint32_t ed_mb = ed / SIZE_M(1);
74 	uint32_t i = 0;
75 
76 	if (!fw_ddr_base || !fw_dsu_base)
77 		panic();
78 
79 	assert(rgn <= 16);
80 	assert(st < ed);
81 
82 	/* Check aligned 1MB */
83 	assert(st % SIZE_M(1) == 0);
84 	assert(ed % SIZE_M(1) == 0);
85 
86 	DMSG("protecting region %d: 0x%"PRIxPA"-0x%"PRIxPA"", rgn, st, ed);
87 
88 	/* Map secure region in DDR */
89 	io_write32(fw_ddr_base + FIREWALL_DDR_RGN(rgn),
90 		   RG_MAP_SECURE(ed_mb, st_mb));
91 
92 	/* Map secure region in each DSU channel and enable */
93 	for (i = 0; i < DDR_CHN_CNT; i++) {
94 		io_write32(fw_dsu_base + FIREWALL_DSU_RGN(i),
95 			   RG_MAP_SECURE(ed_mb, st_mb));
96 		io_setbits32(fw_dsu_base + FIREWALL_DSU_CON(i), BIT(rgn));
97 	}
98 
99 	/* Enable secure region for DDR */
100 	io_setbits32(fw_ddr_base + FIREWALL_DDR_CON, BIT(rgn));
101 
102 	return 0;
103 }
104 
hw_get_random_bytes(void * buf,size_t blen)105 TEE_Result hw_get_random_bytes(void *buf, size_t blen)
106 {
107 	vaddr_t trng_s_base = (vaddr_t)phys_to_virt_io(TRNG_S_BASE,
108 						       TRNG_S_SIZE);
109 	size_t remaining = blen;
110 	size_t copy_len = 0;
111 	uint32_t val = 0;
112 	uint32_t rnd = 0;
113 
114 	mutex_lock(&trng_mutex);
115 
116 	if (!trng_s_base)
117 		panic("TRNG_S base not mapped");
118 
119 	/* Ensure TRNG is seeded and ready */
120 	val = io_read32(trng_s_base + TRNG_S_STAT);
121 	if (!(val & TRNG_S_SEEDED_BIT)) {
122 		/* TRNG not seeded, issue SEED command */
123 		io_write32(trng_s_base + TRNG_S_CTRL, CMD_SEED);
124 
125 		/* Wait for SEED_DONE flag with timeout */
126 		if (IO_READ32_POLL_TIMEOUT(trng_s_base + TRNG_S_ISTAT, val,
127 					   val & TRNG_S_SEED_DONE_BIT,
128 					   TRNG_POLL_PERIOD_US,
129 					   TRNG_POLL_TIMEOUT_US)) {
130 			mutex_unlock(&trng_mutex);
131 			return TEE_ERROR_BUSY;
132 		}
133 
134 		/* SEED_DONE flag set, clear SEED_DONE */
135 		io_write32(trng_s_base + TRNG_S_ISTAT, TRNG_S_SEED_DONE_BIT);
136 	}
137 
138 	/* Set RNG length to 256 bits */
139 	io_write32(trng_s_base + TRNG_S_MODE, LEN_256BIT);
140 
141 	while (remaining > 0) {
142 		/* Set RAND command to generate random numbers */
143 		io_write32(trng_s_base + TRNG_S_CTRL, CMD_RAND);
144 
145 		/* Wait for RAND_RDY flag with timeout */
146 		if (IO_READ32_POLL_TIMEOUT(trng_s_base + TRNG_S_ISTAT, val,
147 					   val & TRNG_S_RAND_RDY_BIT,
148 					   TRNG_POLL_PERIOD_US,
149 					   TRNG_POLL_TIMEOUT_US)) {
150 			mutex_unlock(&trng_mutex);
151 			return TEE_ERROR_BUSY;
152 		}
153 
154 		/* Read random data from RAND register */
155 		rnd = io_read32(trng_s_base + TRNG_S_RAND);
156 
157 		/* Copy as many bytes as required */
158 		copy_len = MIN(remaining, sizeof(uint32_t));
159 		memcpy((uint8_t *)buf + (blen - remaining), &rnd, copy_len);
160 		remaining -= copy_len;
161 
162 		/* Clear RAND_RDY flag */
163 		io_write32(trng_s_base + TRNG_S_ISTAT, TRNG_S_RAND_RDY_BIT);
164 	}
165 
166 	/* Reset RNG mode to NOP */
167 	io_write32(trng_s_base + TRNG_S_CTRL, CMD_NOP);
168 
169 	mutex_unlock(&trng_mutex);
170 
171 	return TEE_SUCCESS;
172 }
173 
generate_huk(struct tee_hw_unique_key * hwkey)174 static TEE_Result generate_huk(struct tee_hw_unique_key *hwkey)
175 {
176 	TEE_Result res = TEE_SUCCESS;
177 	uint8_t buffer[HW_UNIQUE_KEY_LENGTH] = { };
178 	size_t i = 0;
179 	bool key_is_zero = true;
180 
181 	/* Generate random 128-bit key from TRNG */
182 	res = hw_get_random_bytes(buffer, sizeof(buffer));
183 	if (res)
184 		return res;
185 
186 	/* All zero HUK cannot be written to OTP and indicates TRNG failure */
187 	for (i = 0; i < ARRAY_SIZE(buffer); i++) {
188 		if (buffer[i] != 0)
189 			key_is_zero = false;
190 	}
191 	if (key_is_zero)
192 		return TEE_ERROR_NO_DATA;
193 
194 	memcpy(hwkey->data, buffer, HW_UNIQUE_KEY_LENGTH);
195 
196 	return res;
197 }
198 
persist_huk(struct tee_hw_unique_key * hwkey)199 static TEE_Result persist_huk(struct tee_hw_unique_key *hwkey)
200 {
201 	TEE_Result res = TEE_SUCCESS;
202 	uint32_t buffer[ROCKCHIP_OTP_HUK_SIZE] = { };
203 
204 	static_assert(sizeof(buffer) == sizeof(hwkey->data));
205 
206 	memcpy(buffer, hwkey->data, HW_UNIQUE_KEY_LENGTH);
207 
208 	/* Write the new HUK into OTP at ROCKCHIP_OTP_HUK_INDEX */
209 	res = rockchip_otp_write_secure(buffer, ROCKCHIP_OTP_HUK_INDEX,
210 					ROCKCHIP_OTP_HUK_SIZE);
211 
212 	/* Clear buffer memory */
213 	memzero_explicit(buffer, sizeof(buffer));
214 
215 	return res;
216 }
217 
read_huk(struct tee_hw_unique_key * hwkey)218 static TEE_Result read_huk(struct tee_hw_unique_key *hwkey)
219 {
220 	TEE_Result res = TEE_SUCCESS;
221 	uint32_t buffer[ROCKCHIP_OTP_HUK_SIZE] = { };
222 	bool key_is_empty = true;
223 	size_t i = 0;
224 
225 	static_assert(sizeof(buffer) == sizeof(hwkey->data));
226 
227 	/* Read 4 words (16 bytes) from OTP at ROCKCHIP_OTP_HUK_INDEX */
228 	res = rockchip_otp_read_secure(buffer,
229 				       ROCKCHIP_OTP_HUK_INDEX,
230 				       ROCKCHIP_OTP_HUK_SIZE);
231 	if (res)
232 		goto out;
233 
234 	/* Check if the buffer is all zero => HUK not present */
235 	for (i = 0; i < ARRAY_SIZE(buffer); i++) {
236 		if (buffer[i] != 0)
237 			key_is_empty = false;
238 	}
239 	if (key_is_empty)
240 		return TEE_ERROR_NO_DATA;
241 
242 	/* Copy HUK into hwkey->data */
243 	memcpy(hwkey->data, buffer, HW_UNIQUE_KEY_LENGTH);
244 
245 out:
246 	/* Clear buffer memory */
247 	memzero_explicit(buffer, sizeof(buffer));
248 
249 	return res;
250 }
251 
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)252 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
253 {
254 	TEE_Result res = TEE_SUCCESS;
255 
256 	if (!hwkey)
257 		return TEE_ERROR_BAD_PARAMETERS;
258 
259 	mutex_lock(&huk_mutex);
260 
261 	/* Try to use the cached HUK from memory */
262 	if (huk)
263 		goto out;
264 
265 	huk = malloc(sizeof(*huk));
266 	if (!huk) {
267 		res = TEE_ERROR_OUT_OF_MEMORY;
268 		goto out;
269 	}
270 
271 	/* Try to read and cache the HUK persisted in the OTP */
272 	res = read_huk(huk);
273 	if (res != TEE_ERROR_NO_DATA)
274 		goto out;
275 
276 	/* Try to generate and use a new HUK and persist it in the OTP */
277 	res = generate_huk(huk);
278 	if (res != TEE_SUCCESS)
279 		goto out;
280 	res = persist_huk(huk);
281 
282 out:
283 	if (res == TEE_SUCCESS) {
284 		memcpy(hwkey->data, huk->data, HW_UNIQUE_KEY_LENGTH);
285 	} else if (huk) {
286 		free_wipe(huk);
287 		huk = NULL;
288 	}
289 
290 	mutex_unlock(&huk_mutex);
291 
292 	return res;
293 }
294