xref: /optee_os/core/drivers/versal_puf.c (revision 107905a9985f155551b775361c3d593119d79e82)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2022 Foundries.io Ltd
4  * Jorge Ramirez-Ortiz <jorge@foundries.io>
5  */
6 
7 #include <arm.h>
8 #include <confine_array_index.h>
9 #include <drivers/versal_nvm.h>
10 #include <drivers/versal_pmc.h>
11 #include <drivers/versal_puf.h>
12 #include <initcall.h>
13 #include <mm/core_memprot.h>
14 #include <string.h>
15 #include <tee/cache.h>
16 
17 /* Protocol API with the remote processor */
18 #define VERSAL_PUF_MODULE_SHIFT		8
19 #define VERSAL_PUF_MODULE		12
20 #define PUF_API_ID(_id) ((VERSAL_PUF_MODULE << VERSAL_PUF_MODULE_SHIFT) | (_id))
21 
22 enum versal_puf_error {
23 	/* Registration */
24 	ERROR_INVALID_PARAM = 0x02,
25 	ERROR_INVALID_SYNDROME_MODE = 0x03,
26 	ERROR_SYNDROME_WORD_WAIT_TIMEOUT = 0x04,
27 	ERROR_PUF_DONE_WAIT_TIMEOUT = 0x07,
28 	ERROR_REGISTRATION_INVALID = 0x08,
29 	SHUTTER_GVF_MISMATCH = 0x09,
30 	ERROR_SYN_DATA_ERROR = 0x0A,
31 	IRO_FREQ_WRITE_MISMATCH = 0x0B,
32 	/* Regeneration */
33 	ERROR_CHASH_NOT_PROGRAMMED = 0x10,
34 	ERROR_PUF_STATUS_DONE_TIMEOUT = 0x11,
35 	ERROR_INVALID_REGENERATION_TYPE = 0x12,
36 	ERROR_INVALID_PUF_OPERATION = 0x13,
37 	ERROR_REGENERATION_INVALID = 0x14,
38 	ERROR_REGEN_PUF_HD_INVALID = 0x15,
39 	ERROR_INVALID_READ_HD_INPUT = 0x16,
40 	ERROR_PUF_DONE_KEY_NT_RDY = 0x17,
41 	ERROR_PUF_DONE_ID_NT_RDY = 0x18,
42 	ERROR_PUF_ID_ZERO_TIMEOUT = 0x19,
43 };
44 
45 #define VERSAL_PUF_ERROR(m) { .error = (m), .name = TO_STR(m) }
46 
versal_puf_error(uint8_t err)47 static const char *versal_puf_error(uint8_t err)
48 {
49 	struct {
50 		enum versal_puf_error error;
51 		const char *name;
52 	} elist[] = {
53 		/* Registration */
54 		VERSAL_PUF_ERROR(ERROR_INVALID_PARAM),
55 		VERSAL_PUF_ERROR(ERROR_INVALID_SYNDROME_MODE),
56 		VERSAL_PUF_ERROR(ERROR_SYNDROME_WORD_WAIT_TIMEOUT),
57 		VERSAL_PUF_ERROR(ERROR_PUF_DONE_WAIT_TIMEOUT),
58 		VERSAL_PUF_ERROR(ERROR_REGISTRATION_INVALID),
59 		VERSAL_PUF_ERROR(SHUTTER_GVF_MISMATCH),
60 		VERSAL_PUF_ERROR(ERROR_SYN_DATA_ERROR),
61 		VERSAL_PUF_ERROR(IRO_FREQ_WRITE_MISMATCH),
62 		/* Regeneration */
63 		VERSAL_PUF_ERROR(ERROR_CHASH_NOT_PROGRAMMED),
64 		VERSAL_PUF_ERROR(ERROR_PUF_STATUS_DONE_TIMEOUT),
65 		VERSAL_PUF_ERROR(ERROR_INVALID_REGENERATION_TYPE),
66 		VERSAL_PUF_ERROR(ERROR_INVALID_PUF_OPERATION),
67 		VERSAL_PUF_ERROR(ERROR_REGENERATION_INVALID),
68 		VERSAL_PUF_ERROR(ERROR_REGEN_PUF_HD_INVALID),
69 		VERSAL_PUF_ERROR(ERROR_INVALID_READ_HD_INPUT),
70 		VERSAL_PUF_ERROR(ERROR_PUF_DONE_KEY_NT_RDY),
71 		VERSAL_PUF_ERROR(ERROR_PUF_DONE_ID_NT_RDY),
72 		VERSAL_PUF_ERROR(ERROR_PUF_ID_ZERO_TIMEOUT),
73 	};
74 	size_t error = 0;
75 	size_t index = 0;
76 
77 	if (err <= ERROR_PUF_ID_ZERO_TIMEOUT && err >= ERROR_INVALID_PARAM) {
78 		index = err - ERROR_INVALID_PARAM;
79 
80 		/* Spectre gadget protection: array index is external event */
81 		error = confine_array_index(index, ARRAY_SIZE(elist));
82 		if (elist[error].name)
83 			return elist[error].name;
84 
85 		return "Invalid";
86 	}
87 
88 	return "Unknown";
89 }
90 
91 /*
92  * Register the Physical Unclonable Function (prior operating with it)
93  *
94  * This must happen during the device provisioning phase and can be done from
95  * the Secure World via this interface or from an earlier firmware.
96  */
versal_puf_register(struct versal_puf_data * buf,struct versal_puf_cfg * cfg)97 TEE_Result versal_puf_register(struct versal_puf_data *buf,
98 			       struct versal_puf_cfg *cfg)
99 {
100 	struct versal_puf_data_req req __aligned_puf = { };
101 	struct versal_mbox_mem request = {
102 		.alloc_len = sizeof(req),
103 		.len = sizeof(req),
104 		.buf = &req,
105 	};
106 	struct versal_mbox_mem efuse_syn_data_addr = { };
107 	struct versal_mbox_mem syndrome_data_addr = { };
108 	struct versal_mbox_mem puf_id_addr = { };
109 	struct versal_mbox_mem hash_addr = { };
110 	struct versal_mbox_mem aux_addr = { };
111 	struct versal_ipi_cmd arg = { };
112 	TEE_Result ret = TEE_SUCCESS;
113 	uint32_t err = 0;
114 
115 	ret = versal_mbox_alloc(sizeof(buf->puf_id), NULL, &puf_id_addr);
116 	if (ret)
117 		goto out;
118 	ret = versal_mbox_alloc(sizeof(buf->chash), NULL, &hash_addr);
119 	if (ret)
120 		goto out;
121 	ret = versal_mbox_alloc(sizeof(buf->aux), NULL, &aux_addr);
122 	if (ret)
123 		goto out;
124 	ret = versal_mbox_alloc(sizeof(buf->efuse_syn_data), NULL,
125 				&efuse_syn_data_addr);
126 	if (ret)
127 		goto out;
128 	ret = versal_mbox_alloc(sizeof(buf->syndrome_data), NULL,
129 				&syndrome_data_addr);
130 	if (ret)
131 		goto out;
132 
133 	arg.ibuf[0].mem = request;
134 	arg.ibuf[1].mem = syndrome_data_addr;
135 	arg.ibuf[2].mem = hash_addr;
136 	arg.ibuf[3].mem = aux_addr;
137 	arg.ibuf[4].mem = puf_id_addr;
138 	arg.ibuf[5].mem = efuse_syn_data_addr;
139 
140 	req.efuse_syn_data_addr = virt_to_phys(efuse_syn_data_addr.buf);
141 	req.syndrome_data_addr = virt_to_phys(syndrome_data_addr.buf);
142 	req.puf_id_addr = virt_to_phys(puf_id_addr.buf);
143 	req.hash_addr = virt_to_phys(hash_addr.buf);
144 	req.aux_addr = virt_to_phys(aux_addr.buf);
145 
146 	req.global_var_filter = cfg->global_var_filter;
147 	req.shutter_value = cfg->shutter_value;
148 	req.puf_operation = cfg->puf_operation;
149 	req.read_option = cfg->read_option;
150 #if defined(PLATFORM_FLAVOR_net)
151 	req.ro_swap_value = cfg->ro_swap_value;
152 #endif
153 
154 	arg.data[0] = PUF_API_ID(VERSAL_PUF_REGISTER);
155 	reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf),
156 			 &arg.data[2], &arg.data[1]);
157 
158 	if (versal_pmc_notify(&arg, NULL, &err)) {
159 		EMSG("Versal, failed to register the PUF [%s]",
160 		     versal_puf_error(err));
161 
162 		ret = TEE_ERROR_GENERIC;
163 	}
164 
165 	/* Return the generated data */
166 	memcpy(buf->puf_id, puf_id_addr.buf, sizeof(buf->puf_id));
167 	memcpy(&buf->chash, hash_addr.buf, sizeof(buf->chash));
168 	memcpy(&buf->aux, aux_addr.buf, sizeof(buf->aux));
169 	memcpy(buf->efuse_syn_data, efuse_syn_data_addr.buf,
170 	       sizeof(buf->efuse_syn_data));
171 	memcpy(buf->syndrome_data, syndrome_data_addr.buf,
172 	       sizeof(buf->syndrome_data));
173 
174 out:
175 	versal_mbox_free(&syndrome_data_addr);
176 	versal_mbox_free(&efuse_syn_data_addr);
177 	versal_mbox_free(&aux_addr);
178 	versal_mbox_free(&hash_addr);
179 	versal_mbox_free(&puf_id_addr);
180 
181 	return ret;
182 }
183 
184 /*
185  * Re-seed the PUF circuitry so it can re-generate the Key Encryption Key.
186  *
187  * Depending on the configuration options it might use eFused data instead of
188  * the helper data provided via the interface.
189  */
versal_puf_regenerate(struct versal_puf_data * buf,struct versal_puf_cfg * cfg)190 TEE_Result versal_puf_regenerate(struct versal_puf_data *buf,
191 				 struct versal_puf_cfg *cfg)
192 {
193 	struct versal_puf_data_req req __aligned_puf = { };
194 	struct versal_mbox_mem request = {
195 		.alloc_len = sizeof(req),
196 		.len = sizeof(req),
197 		.buf = &req,
198 	};
199 	struct versal_mbox_mem syndrome_data_addr = { };
200 	struct versal_mbox_mem puf_id_addr = { };
201 	struct versal_mbox_mem hash_addr = { };
202 	struct versal_mbox_mem aux_addr = { };
203 	struct versal_ipi_cmd arg = { };
204 	TEE_Result ret = TEE_SUCCESS;
205 	uint32_t err = 0;
206 
207 	ret = versal_mbox_alloc(sizeof(buf->puf_id), NULL, &puf_id_addr);
208 	if (ret)
209 		goto out;
210 	ret = versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr);
211 	if (ret)
212 		goto out;
213 	ret = versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr);
214 	if (ret)
215 		goto out;
216 	ret = versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data,
217 				&syndrome_data_addr);
218 	if (ret)
219 		goto out;
220 
221 	arg.ibuf[0].mem = request;
222 	arg.ibuf[1].mem = syndrome_data_addr;
223 	arg.ibuf[2].mem = hash_addr;
224 	arg.ibuf[3].mem = aux_addr;
225 	arg.ibuf[4].mem = puf_id_addr;
226 
227 	req.syndrome_addr = virt_to_phys(syndrome_data_addr.buf);
228 	req.puf_id_addr = virt_to_phys(puf_id_addr.buf);
229 	req.hash_addr = virt_to_phys(hash_addr.buf);
230 	req.aux_addr = virt_to_phys(aux_addr.buf);
231 
232 	req.global_var_filter = cfg->global_var_filter;
233 	req.shutter_value = cfg->shutter_value;
234 	req.puf_operation = cfg->puf_operation;
235 	req.read_option = cfg->read_option;
236 #if defined(PLATFORM_FLAVOR_net)
237 	req.ro_swap_value = cfg->ro_swap_value;
238 #endif
239 
240 	arg.data[0] = PUF_API_ID(VERSAL_PUF_REGENERATE);
241 	reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf),
242 			 &arg.data[2], &arg.data[1]);
243 
244 	if (versal_pmc_notify(&arg, NULL, &err)) {
245 		EMSG("Versal, failed to regenerate the PUF [%s]",
246 		     versal_puf_error(err));
247 
248 		ret = TEE_ERROR_GENERIC;
249 	}
250 
251 	/* Return the updated PUF_ID */
252 	memcpy(buf->puf_id, puf_id_addr.buf, sizeof(buf->puf_id));
253 
254 out:
255 	versal_mbox_free(&syndrome_data_addr);
256 	versal_mbox_free(&aux_addr);
257 	versal_mbox_free(&hash_addr);
258 	versal_mbox_free(&puf_id_addr);
259 
260 	return ret;
261 }
262 
263 /*
264  * Clear/Hide the PUF Unique ID
265  *
266  * The fully accessible (non-secret) Unique ID is generated from the PUF
267  */
versal_puf_clear_id(void)268 TEE_Result versal_puf_clear_id(void)
269 {
270 	struct versal_ipi_cmd arg = { };
271 
272 	arg.data[0] = PUF_API_ID(VERSAL_PUF_CLEAR_ID);
273 
274 	if (versal_pmc_notify(&arg, NULL, NULL)) {
275 		EMSG("Versal, failed to clear the PUF_ID");
276 
277 		return TEE_ERROR_GENERIC;
278 	}
279 
280 	return TEE_SUCCESS;
281 }
282 
283 /* Check that the API id is available to the client */
versal_puf_check_api(enum versal_puf_api id)284 TEE_Result versal_puf_check_api(enum versal_puf_api id)
285 {
286 	struct versal_ipi_cmd arg = { };
287 
288 	arg.data[0] = PUF_API_ID(VERSAL_PUF_API_FEATURES);
289 	arg.data[1] = id;
290 
291 	if (versal_pmc_notify(&arg, NULL, NULL))
292 		return TEE_ERROR_GENERIC;
293 
294 	return TEE_SUCCESS;
295 }
296