1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2021 Foundries.io Ltd.
4  * Jorge Ramirez-Ortiz <jorge@foundries.io>
5  */
6 
7 #include <assert.h>
8 #include <drivers/zynqmp_csu_aes.h>
9 #include <drivers/zynqmp_csu_puf.h>
10 #include <drivers/zynqmp_huk.h>
11 #include <drivers/zynqmp_pm.h>
12 #include <io.h>
13 #include <kernel/tee_common_otp.h>
14 #include <mm/core_memprot.h>
15 #include <string_ext.h>
16 #include <tee/tee_cryp_utl.h>
17 #include <trace.h>
18 #include <utee_defines.h>
19 
20 static struct {
21 	uint8_t key[HW_UNIQUE_KEY_LENGTH];
22 	bool ready;
23 } huk;
24 
tee_zynqmp_get_device_dna(uint8_t * device_dna,size_t size)25 __weak TEE_Result tee_zynqmp_get_device_dna(uint8_t *device_dna, size_t size)
26 {
27 	if (size != ZYNQMP_EFUSE_LEN(DNA))
28 		return TEE_ERROR_BAD_PARAMETERS;
29 
30 	/* Get Device DNA from the PS eFuses */
31 	return zynqmp_efuse_read(device_dna, size, DNA, false);
32 }
33 
34 /*
35  * Generate HUK source data
36  *
37  * Performs SHA256 over of data:
38  * - Device DNA (from PL preferably)
39  * - Selected user eFuses (HUK seed)
40  *
41  * HUK source data is later on AES encrypted with device key to shuffle source
42  * data even further with secret key.
43  *
44  * Note: Even though the device key is secret used details for HUK source data
45  * should not be exposed to REE environment.
46  *
47  * Note: You should not change HUK source data generation parameters after
48  * devices have been deployed.
49  *
50  * @device_dna: Value of Device DNA
51  * @device_dna_size: Size of Device DNA
52  * @huk_source: Output buffer for HUK source data
53  * @huk_source_size: Output buffer size for HUK source data
54  * Return a TEE_Result compliant status
55  */
tee_zynqmp_generate_huk_src(const uint8_t * device_dna,size_t device_dna_size,uint8_t * huk_source,size_t huk_source_size)56 static TEE_Result tee_zynqmp_generate_huk_src(const uint8_t *device_dna,
57 					      size_t device_dna_size,
58 					      uint8_t *huk_source,
59 					      size_t huk_source_size)
60 {
61 	TEE_Result res = TEE_ERROR_GENERIC;
62 	uint32_t user_efuse = 0;
63 	void *ctx = NULL;
64 	int i = 0;
65 
66 	assert(device_dna_size == ZYNQMP_EFUSE_LEN(DNA));
67 	assert(huk_source_size == HW_UNIQUE_KEY_LENGTH);
68 
69 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
70 	if (res)
71 		return res;
72 
73 	res = crypto_hash_init(ctx);
74 	if (res)
75 		goto out;
76 
77 	res = crypto_hash_update(ctx, device_dna, device_dna_size);
78 	if (res)
79 		goto out;
80 
81 	/* Hash selected user eFuses */
82 	for (i = 0; i < (USER7 - USER0 + 1); i++) {
83 		if (CFG_ZYNQMP_HUK_USER_EFUSE_MASK & BIT(i)) {
84 			DMSG("Use User eFuse %d for HUK source data", i);
85 
86 			res = zynqmp_efuse_read((uint8_t *)&user_efuse,
87 						sizeof(user_efuse), USER0 + i,
88 						false);
89 			if (res)
90 				goto out;
91 
92 			res = crypto_hash_update(ctx, (uint8_t *)&user_efuse,
93 						 sizeof(user_efuse));
94 			if (res)
95 				goto out;
96 		}
97 	}
98 
99 	res = crypto_hash_final(ctx, huk_source, huk_source_size);
100 out:
101 	crypto_hash_free_ctx(ctx);
102 	memzero_explicit(&user_efuse, sizeof(user_efuse));
103 	return res;
104 }
105 
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)106 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
107 {
108 	vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE);
109 	uint8_t device_dna[ZYNQMP_EFUSE_LEN(DNA)] = { 0 };
110 	uint8_t src[HW_UNIQUE_KEY_LENGTH] __aligned_csuaes = { 0 };
111 	uint8_t iv[ZYNQMP_GCM_IV_SIZE] = { 0 };
112 	uint8_t tag[ZYNQMP_GCM_TAG_SIZE] __aligned_csuaes = { 0 };
113 	uint8_t sha[HW_UNIQUE_KEY_LENGTH] = { 0 };
114 	uint8_t dst[ZYNQMP_CSU_AES_DST_LEN(sizeof(src))]
115 		__aligned_csuaes = { 0 };
116 	TEE_Result ret = TEE_ERROR_GENERIC;
117 	uint32_t status = 0;
118 
119 	static_assert(sizeof(device_dna) == ZYNQMP_GCM_IV_SIZE);
120 
121 	if (huk.ready)
122 		goto out;
123 
124 	ret = tee_zynqmp_get_device_dna(device_dna, sizeof(device_dna));
125 	if (ret) {
126 		EMSG("Can't read the Device DNA");
127 		goto cleanup;
128 	}
129 
130 	status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET);
131 	if (!(status & ZYNQMP_CSU_STATUS_AUTH)) {
132 		/* The DNA is a unique identifier valid but not secure */
133 		IMSG("CSU authentication disabled, using development HUK");
134 
135 		/* Use hash of device DNA for development HUK */
136 		ret = tee_hash_createdigest(TEE_ALG_SHA256, device_dna,
137 					    sizeof(device_dna), huk.key,
138 					    sizeof(huk.key));
139 		if (ret) {
140 			EMSG("Can't generate the SHA256 for the DNA eFuse");
141 			goto cleanup;
142 		}
143 
144 		huk.ready = true;
145 		goto out;
146 	}
147 
148 	/* Use device DNA for IV */
149 	memcpy(iv, device_dna, sizeof(device_dna));
150 
151 	/* Generate HUK source data */
152 	ret = tee_zynqmp_generate_huk_src(device_dna, sizeof(device_dna), src,
153 					  sizeof(src));
154 	if (ret) {
155 		EMSG("Failed to generate HUK source data");
156 		goto cleanup;
157 	}
158 
159 #ifdef CFG_ZYNQMP_CSU_PUF
160 	/*
161 	 * Neither the PMUFW nor the PUF hardware provide an indication of the
162 	 * PUF KEK registration status. The verification algorithm that follows
163 	 * encrypts and then decrypts the resulting string regenerating the
164 	 * PUF KEK in between: if the outputs match, then the PUF KEK was
165 	 * registered properly and we can use it to generate the HUK.
166 	 */
167 	zynqmp_csu_puf_reset();
168 
169 	ret = zynqmp_csu_puf_regenerate();
170 	if (ret) {
171 		EMSG("PUF regeneration error");
172 		goto cleanup;
173 	}
174 #endif
175 
176 	memcpy(sha, src, sizeof(sha));
177 	/* The dst buffer must be large enough to include the generated tag */
178 	ret = zynqmp_csu_aes_encrypt_data(src, sizeof(src), dst, sizeof(dst),
179 					  tag, sizeof(tag), iv, sizeof(iv),
180 					  ZYNQMP_CSU_AES_KEY_SRC_DEV);
181 	if (ret) {
182 		EMSG("Can't encrypt DNA, please make sure PUF was registered");
183 		goto cleanup;
184 	}
185 
186 #ifdef CFG_ZYNQMP_CSU_PUF
187 	/* regenerate the PUF KEK */
188 	ret = zynqmp_csu_puf_regenerate();
189 	if (ret) {
190 		EMSG("PUF regeneration error");
191 		goto cleanup;
192 	}
193 #endif
194 	memset(src, 0, sizeof(src));
195 	/* Ignore the tag data from the dst buffer - pass a smaller size */
196 	ret = zynqmp_csu_aes_decrypt_data(dst, sizeof(src), src, sizeof(src),
197 					  tag, sizeof(tag), iv,
198 					  ZYNQMP_EFUSE_LEN(DNA),
199 					  ZYNQMP_CSU_AES_KEY_SRC_DEV);
200 	if (ret) {
201 		EMSG("Can't decrypt DNA, please make sure PUF was registered");
202 		goto cleanup;
203 	}
204 
205 	if (memcmp(src, sha, sizeof(sha))) {
206 		EMSG("PUF not ready, can't create HUK");
207 		ret = TEE_ERROR_GENERIC;
208 		goto cleanup;
209 	}
210 
211 	IMSG("HUK ready");
212 
213 	/*
214 	 * The HUK is the SHA-256 of Device DNA with optional User eFuses
215 	 * included and then AES-GCM encrypted with the selected Device Key
216 	 * using the Device DNA as the IV.
217 	 */
218 	memcpy(huk.key, dst, sizeof(huk.key));
219 	huk.ready = true;
220 out:
221 	memcpy(hwkey->data, huk.key, HW_UNIQUE_KEY_LENGTH);
222 	ret = TEE_SUCCESS;
223 
224 cleanup:
225 	/* Cleanup stack memory so that there are no left overs */
226 	memzero_explicit(dst, sizeof(dst));
227 	memzero_explicit(sha, sizeof(sha));
228 	memzero_explicit(tag, sizeof(tag));
229 	memzero_explicit(iv, sizeof(iv));
230 	memzero_explicit(src, sizeof(src));
231 	memzero_explicit(device_dna, sizeof(device_dna));
232 
233 	return ret;
234 }
235