xref: /optee_os/core/drivers/versal_huk.c (revision 107905a9985f155551b775361c3d593119d79e82)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2022 Foundries.io Ltd.
4  * Jorge Ramirez-Ortiz <jorge@foundries.io>
5  */
6 
7 #include <assert.h>
8 #include <drivers/versal_nvm.h>
9 #include <drivers/versal_pmc.h>
10 #include <drivers/versal_puf.h>
11 #include <drivers/versal_sha3_384.h>
12 #include <io.h>
13 #include <kernel/panic.h>
14 #include <kernel/tee_common_otp.h>
15 #include <mm/core_memprot.h>
16 #include <string_ext.h>
17 #include <tee/tee_cryp_utl.h>
18 #include <trace.h>
19 #include <utee_defines.h>
20 
21 static struct {
22 	uint8_t key[HW_UNIQUE_KEY_LENGTH];
23 	bool ready;
24 } huk;
25 
26 #define MODULE_SHIFT 8
27 #define MODULE_ID 5
28 #define API_ID(__x) ((MODULE_ID << MODULE_SHIFT) | (__x))
29 
30 #define	VERSAL_AES_KEY_SIZE_256  2
31 #define VERSAL_AES_GCM_ENCRYPT 0
32 
33 enum versal_aes_key_src {
34 	VERSAL_AES_BBRAM_KEY = 0,
35 	VERSAL_AES_BBRAM_RED_KEY,
36 	VERSAL_AES_BH_KEY,
37 	VERSAL_AES_BH_RED_KEY,
38 	VERSAL_AES_EFUSE_KEY,
39 	VERSAL_AES_EFUSE_RED_KEY,
40 	VERSAL_AES_EFUSE_USER_KEY_0,
41 	VERSAL_AES_EFUSE_USER_KEY_1,
42 	VERSAL_AES_EFUSE_USER_RED_KEY_0,
43 	VERSAL_AES_EFUSE_USER_RED_KEY_1,
44 	VERSAL_AES_KUP_KEY,
45 	VERSAL_AES_PUF_KEY,
46 	VERSAL_AES_USER_KEY_0,
47 	VERSAL_AES_USER_KEY_1,
48 	VERSAL_AES_USER_KEY_2,
49 	VERSAL_AES_USER_KEY_3,
50 	VERSAL_AES_USER_KEY_4,
51 	VERSAL_AES_USER_KEY_5,
52 	VERSAL_AES_USER_KEY_6,
53 	VERSAL_AES_USER_KEY_7,
54 	VERSAL_AES_EXPANDED_KEYS,
55 };
56 
57 #define VERSAL_AES_MAX_KEY_SOURCES VERSAL_AES_USER_KEY_7
58 
59 enum versal_crypto_api {
60 	VERSAL_AES_INIT = 9U,
61 	VERSAL_AES_OP_INIT,
62 	VERSAL_AES_UPDATE_AAD,
63 	VERSAL_AES_ENCRYPT_UPDATE,
64 	VERSAL_AES_ENCRYPT_FINAL,
65 	VERSAL_AES_DECRYPT_UPDATE,
66 	VERSAL_AES_DECRYPT_FINAL,
67 	VERSAL_AES_KEY_ZERO,
68 	VERSAL_AES_WRITE_KEY,
69 	VERSAL_AES_LOCK_USER_KEY,
70 	VERSAL_AES_KEK_DECRYPT,
71 	VERSAL_AES_SET_DPA_CM,
72 };
73 
74 struct versal_aes_input_param {
75 	uint64_t input_addr;
76 	uint32_t input_len;
77 	uint32_t is_last;
78 };
79 
80 struct versal_aes_init {
81 	uint64_t iv_addr;
82 	uint32_t operation;
83 	uint32_t key_src;
84 	uint32_t key_len;
85 };
86 
87 /*
88  * The PLM is little endian. When programming the keys in uint32_t the driver
89  * will BE swap the values.
90  *
91  * This way the test key below corresponds to the byte array 0xf8, 0x78, 0xb8,
92  * 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, ....
93  *
94  * NOTICE: This hardcoded value in DEVEL_KEY could have just been zeroes as done
95  * in the weak implementation found in otp_stubs.c.
96  */
97 #define DEVEL_KEY { \
98 		0xf878b838, 0xd8589818, 0xe868a828, 0xc8488808, \
99 		0xf070b030, 0xd0509010, 0xe060a020, 0xc0408000, \
100 	}
101 
102 #define AAD { \
103 		0x67, 0xe2, 0x1c, 0xf3, 0xcb, 0x29, 0xe0, 0xdc, 0xbc, 0x4d, \
104 		0x8b, 0x1d, 0x0c, 0xc5, 0x33, 0x4b, \
105 	}
106 
107 #define NONCE { \
108 		0xd2, 0x45, 0x0e, 0x07, 0xea, 0x5d, 0xe0, 0x42, 0x6c, 0x0f, \
109 		0xa1, 0x33, \
110 	}
111 
versal_persistent_key(enum versal_aes_key_src src,bool * secure)112 static bool versal_persistent_key(enum versal_aes_key_src src, bool *secure)
113 {
114 	struct versal_efuse_puf_sec_ctrl_bits puf_ctrl = { };
115 	struct versal_efuse_sec_ctrl_bits ctrl = { };
116 	struct versal_puf_data puf_data = { };
117 	struct versal_puf_cfg cfg = {
118 		.global_var_filter = VERSAL_PUF_GLBL_VAR_FLTR_OPTION,
119 		.read_option = VERSAL_PUF_READ_FROM_EFUSE_CACHE,
120 		.puf_operation = VERSAL_PUF_REGEN_ON_DEMAND,
121 		.shutter_value = VERSAL_PUF_SHUTTER_VALUE,
122 #if defined(PLATFORM_FLAVOR_net)
123 		.ro_swap_value = VERSAL_PUF_RO_SWAP_VALUE,
124 #endif
125 
126 	};
127 
128 	switch (src) {
129 	case VERSAL_AES_EFUSE_USER_KEY_0:
130 		if (versal_efuse_read_sec_ctrl(&ctrl))
131 			panic();
132 
133 		*secure = ctrl.user_key0_wr_lk;
134 		return true;
135 
136 	case VERSAL_AES_EFUSE_USER_KEY_1:
137 		if (versal_efuse_read_sec_ctrl(&ctrl))
138 			panic();
139 
140 		*secure = ctrl.user_key1_wr_lk;
141 		return true;
142 
143 	case VERSAL_AES_PUF_KEY:
144 		if (versal_efuse_read_puf_sec_ctrl(&puf_ctrl))
145 			panic();
146 
147 		if (versal_puf_regenerate(&puf_data, &cfg))
148 			panic();
149 
150 		*secure = puf_ctrl.puf_syn_lk;
151 		return true;
152 
153 	case VERSAL_AES_USER_KEY_0:
154 		*secure = false;
155 		return false;
156 
157 	default:
158 		EMSG("Trying to use an invalid key for the HUK");
159 		panic();
160 	}
161 
162 	return false;
163 }
164 
165 /* Encrypt using an AES-GCM key selectable with CFG_VERSAL_HUK_KEY */
aes_gcm_encrypt(uint8_t * src,size_t src_len,uint8_t * dst,size_t dst_len)166 static TEE_Result aes_gcm_encrypt(uint8_t *src, size_t src_len,
167 				  uint8_t *dst, size_t dst_len)
168 {
169 	struct versal_aes_input_param *input = NULL;
170 	struct versal_aes_init *init = NULL;
171 	struct versal_mbox_mem input_cmd = { };
172 	struct versal_mbox_mem init_buf = { };
173 	struct versal_mbox_mem p = { };
174 	struct versal_mbox_mem q = { };
175 	uint32_t key_data[8] = DEVEL_KEY;
176 	uint8_t nce_data[12] = NONCE;
177 	uint8_t aad_data[16] = AAD;
178 	size_t nce_len = sizeof(nce_data);
179 	size_t key_len = sizeof(key_data);
180 	size_t aad_len = sizeof(aad_data);
181 	TEE_Result ret = TEE_SUCCESS;
182 	struct versal_ipi_cmd cmd = { };
183 	bool secure = false;
184 	size_t i = 0;
185 	uint32_t key_id = CFG_VERSAL_HUK_KEY;
186 
187 	if (key_id > VERSAL_AES_MAX_KEY_SOURCES)
188 		return TEE_ERROR_BAD_PARAMETERS;
189 
190 	cmd.data[0] = API_ID(VERSAL_AES_INIT);
191 	if (versal_pmc_notify(&cmd, NULL, NULL)) {
192 		EMSG("AES_INIT error");
193 		return TEE_ERROR_GENERIC;
194 	}
195 
196 	if (!versal_persistent_key(key_id, &secure)) {
197 		for (i = 0; i < ARRAY_SIZE(key_data); i++)
198 			key_data[i] = TEE_U32_BSWAP(key_data[i]);
199 
200 		ret = versal_mbox_alloc(key_len, key_data, &p);
201 		if (ret)
202 			return ret;
203 
204 		cmd.data[0] = API_ID(VERSAL_AES_WRITE_KEY);
205 		cmd.data[1] = VERSAL_AES_KEY_SIZE_256;
206 		cmd.data[2] = key_id;
207 		reg_pair_from_64(virt_to_phys(p.buf),
208 				 &cmd.data[4], &cmd.data[3]);
209 		cmd.ibuf[0].mem = p;
210 		if (versal_pmc_notify(&cmd, NULL, NULL)) {
211 			EMSG("AES_WRITE_KEY error");
212 			ret = TEE_ERROR_GENERIC;
213 		}
214 		versal_mbox_free(&p);
215 		memset(&cmd, 0, sizeof(cmd));
216 		if (ret)
217 			return ret;
218 	}
219 
220 	/* Trace indication that it is safe to generate a RPMB key */
221 	IMSG("Using %s HUK", secure ? "Production" : "Development");
222 
223 	ret = versal_mbox_alloc(sizeof(*init), NULL, &init_buf);
224 	if (ret)
225 		return ret;
226 	ret = versal_mbox_alloc(nce_len, nce_data, &p);
227 	if (ret) {
228 		versal_mbox_free(&init_buf);
229 		return ret;
230 	}
231 
232 	init = init_buf.buf;
233 	init->operation = VERSAL_AES_GCM_ENCRYPT;
234 	init->key_len = VERSAL_AES_KEY_SIZE_256;
235 	init->iv_addr = virt_to_phys(p.buf);
236 	init->key_src = key_id;
237 	cmd.data[0] = API_ID(VERSAL_AES_OP_INIT);
238 	reg_pair_from_64(virt_to_phys(init), &cmd.data[2], &cmd.data[1]);
239 	cmd.ibuf[0].mem = init_buf;
240 	cmd.ibuf[1].mem = p;
241 	if (versal_pmc_notify(&cmd, NULL, NULL)) {
242 		EMSG("AES_OP_INIT error");
243 		ret = TEE_ERROR_GENERIC;
244 	}
245 	versal_mbox_free(&init_buf);
246 	versal_mbox_free(&p);
247 	memset(&cmd, 0, sizeof(cmd));
248 	if (ret)
249 		return ret;
250 
251 	ret = versal_mbox_alloc(aad_len, aad_data, &p);
252 	if (ret)
253 		return ret;
254 
255 	cmd.data[0] = API_ID(VERSAL_AES_UPDATE_AAD);
256 	reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[2], &cmd.data[1]);
257 	if (p.len % 16)
258 		cmd.data[3] = p.alloc_len;
259 	else
260 		cmd.data[3] = p.len;
261 	cmd.ibuf[0].mem = p;
262 	if (versal_pmc_notify(&cmd, NULL, NULL)) {
263 		EMSG("AES_UPDATE_AAD error");
264 		ret = TEE_ERROR_GENERIC;
265 	}
266 	versal_mbox_free(&p);
267 	memset(&cmd, 0, sizeof(cmd));
268 	if (ret)
269 		return ret;
270 
271 	ret = versal_mbox_alloc(sizeof(*input), NULL, &input_cmd);
272 	if (ret)
273 		return ret;
274 
275 	ret = versal_mbox_alloc(src_len, src, &p);
276 	if (ret) {
277 		versal_mbox_free(&input_cmd);
278 		return ret;
279 	}
280 	ret = versal_mbox_alloc(dst_len, NULL, &q);
281 	if (ret) {
282 		versal_mbox_free(&p);
283 		versal_mbox_free(&input_cmd);
284 		return ret;
285 	}
286 
287 	input = input_cmd.buf;
288 	input->input_addr = virt_to_phys(p.buf);
289 	input->input_len = p.len;
290 	input->is_last = true;
291 	cmd.data[0] = API_ID(VERSAL_AES_ENCRYPT_UPDATE);
292 	reg_pair_from_64(virt_to_phys(input), &cmd.data[2], &cmd.data[1]);
293 	reg_pair_from_64(virt_to_phys(q.buf), &cmd.data[4], &cmd.data[3]);
294 	cmd.ibuf[0].mem = input_cmd;
295 	cmd.ibuf[1].mem = p;
296 	cmd.ibuf[2].mem = q;
297 	if (versal_pmc_notify(&cmd, NULL, NULL)) {
298 		EMSG("AES_UPDATE_PAYLOAD error");
299 		ret = TEE_ERROR_GENERIC;
300 	}
301 	memcpy(dst, q.buf, dst_len);
302 	versal_mbox_free(&q);
303 	versal_mbox_free(&p);
304 	versal_mbox_free(&input_cmd);
305 	memset(&cmd, 0, sizeof(cmd));
306 	if (ret)
307 		return ret;
308 
309 	ret = versal_mbox_alloc(16, NULL, &p);
310 	if (ret)
311 		return ret;
312 
313 	cmd.data[0] = API_ID(VERSAL_AES_ENCRYPT_FINAL);
314 	reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[2], &cmd.data[1]);
315 	if (versal_pmc_notify(&cmd, NULL, NULL)) {
316 		EMSG("AES_ENCRYPT_FINAL error");
317 		ret = TEE_ERROR_GENERIC;
318 	}
319 	versal_mbox_free(&p);
320 	memzero_explicit(&cmd, sizeof(cmd));
321 
322 	return ret;
323 }
324 
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)325 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
326 {
327 	uint32_t dna[EFUSE_DNA_LEN / sizeof(uint32_t)] = { };
328 	uint8_t enc_data[64] = { };
329 	uint8_t sha[48] = { };
330 	TEE_Result ret = TEE_SUCCESS;
331 
332 	if (huk.ready)
333 		goto out;
334 
335 	if (versal_efuse_read_dna(dna, sizeof(dna)))
336 		return TEE_ERROR_GENERIC;
337 
338 	if (versal_sha3_384((uint8_t *)dna, sizeof(dna), sha, sizeof(sha))) {
339 		ret = TEE_ERROR_GENERIC;
340 		goto cleanup;
341 	}
342 
343 	if (aes_gcm_encrypt(sha, sizeof(sha), enc_data, sizeof(enc_data))) {
344 		ret = TEE_ERROR_GENERIC;
345 		goto cleanup;
346 	}
347 
348 	if (tee_hash_createdigest(TEE_ALG_SHA256, enc_data, sizeof(enc_data),
349 				  huk.key, sizeof(huk.key))) {
350 		ret = TEE_ERROR_GENERIC;
351 		goto cleanup;
352 	}
353 
354 cleanup:
355 	memzero_explicit(enc_data, sizeof(enc_data));
356 	memzero_explicit(dna, sizeof(dna));
357 	memzero_explicit(sha, sizeof(sha));
358 
359 	if (ret)
360 		return ret;
361 
362 	huk.ready = true;
363 out:
364 	memcpy(hwkey->data, huk.key, HW_UNIQUE_KEY_LENGTH);
365 	return TEE_SUCCESS;
366 }
367