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