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