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_mbox.h>
10 #include <drivers/versal_nvm.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 versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr);
116 versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr);
117 versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr);
118 versal_mbox_alloc(sizeof(buf->efuse_syn_data), buf->efuse_syn_data,
119 &efuse_syn_data_addr);
120 versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data,
121 &syndrome_data_addr);
122
123 arg.ibuf[0].mem = request;
124 arg.ibuf[1].mem = syndrome_data_addr;
125 arg.ibuf[2].mem = hash_addr;
126 arg.ibuf[3].mem = aux_addr;
127 arg.ibuf[4].mem = puf_id_addr;
128 arg.ibuf[5].mem = efuse_syn_data_addr;
129
130 req.efuse_syn_data_addr = virt_to_phys(efuse_syn_data_addr.buf);
131 req.syndrome_data_addr = virt_to_phys(syndrome_data_addr.buf);
132 req.puf_id_addr = virt_to_phys(puf_id_addr.buf);
133 req.hash_addr = virt_to_phys(hash_addr.buf);
134 req.aux_addr = virt_to_phys(aux_addr.buf);
135
136 req.global_var_filter = cfg->global_var_filter;
137 req.shutter_value = cfg->shutter_value;
138 req.puf_operation = cfg->puf_operation;
139 req.read_option = cfg->read_option;
140 req.reg_mode = cfg->reg_mode;
141
142 arg.data[0] = PUF_API_ID(VERSAL_PUF_REGISTER);
143 reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf),
144 &arg.data[2], &arg.data[1]);
145
146 if (versal_mbox_notify(&arg, NULL, &err)) {
147 EMSG("Versal, failed to register the PUF [%s]",
148 versal_puf_error(err));
149
150 ret = TEE_ERROR_GENERIC;
151 }
152
153 /* Return the generated data */
154 memcpy(buf->puf_id, puf_id_addr.buf, sizeof(buf->puf_id));
155 memcpy(&buf->chash, hash_addr.buf, sizeof(buf->chash));
156 memcpy(&buf->aux, aux_addr.buf, sizeof(buf->aux));
157 memcpy(buf->efuse_syn_data, efuse_syn_data_addr.buf,
158 sizeof(buf->efuse_syn_data));
159 memcpy(buf->syndrome_data, syndrome_data_addr.buf,
160 sizeof(buf->syndrome_data));
161
162 free(syndrome_data_addr.buf);
163 free(hash_addr.buf);
164 free(aux_addr.buf);
165 free(puf_id_addr.buf);
166 free(efuse_syn_data_addr.buf);
167
168 return ret;
169 }
170
171 /*
172 * Re-seed the PUF circuitry so it can re-generate the Key Encryption Key.
173 *
174 * Depending on the configuration options it might use eFused data instead of
175 * the helper data provided via the interface.
176 */
versal_puf_regenerate(struct versal_puf_data * buf,struct versal_puf_cfg * cfg)177 TEE_Result versal_puf_regenerate(struct versal_puf_data *buf,
178 struct versal_puf_cfg *cfg)
179 {
180 struct versal_puf_data_req req __aligned_puf = { };
181 struct versal_mbox_mem request = {
182 .alloc_len = sizeof(req),
183 .len = sizeof(req),
184 .buf = &req,
185 };
186 struct versal_mbox_mem efuse_syn_data_addr = { };
187 struct versal_mbox_mem syndrome_data_addr = { };
188 struct versal_mbox_mem puf_id_addr = { };
189 struct versal_mbox_mem hash_addr = { };
190 struct versal_mbox_mem aux_addr = { };
191 struct versal_ipi_cmd arg = { };
192 TEE_Result ret = TEE_SUCCESS;
193 uint32_t err = 0;
194
195 versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr);
196 versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr);
197 versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr);
198 versal_mbox_alloc(sizeof(buf->efuse_syn_data), buf->efuse_syn_data,
199 &efuse_syn_data_addr);
200 versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data,
201 &syndrome_data_addr);
202
203 arg.ibuf[0].mem = request;
204 arg.ibuf[1].mem = syndrome_data_addr;
205 arg.ibuf[2].mem = hash_addr;
206 arg.ibuf[3].mem = aux_addr;
207 arg.ibuf[4].mem = puf_id_addr;
208 arg.ibuf[5].mem = efuse_syn_data_addr;
209
210 req.efuse_syn_data_addr = virt_to_phys(efuse_syn_data_addr.buf);
211 req.syndrome_addr = virt_to_phys(syndrome_data_addr.buf);
212 req.puf_id_addr = virt_to_phys(puf_id_addr.buf);
213 req.hash_addr = virt_to_phys(hash_addr.buf);
214 req.aux_addr = virt_to_phys(aux_addr.buf);
215
216 req.global_var_filter = cfg->global_var_filter;
217 req.shutter_value = cfg->shutter_value;
218 req.puf_operation = cfg->puf_operation;
219 req.read_option = cfg->read_option;
220 req.reg_mode = cfg->reg_mode;
221
222 arg.data[0] = PUF_API_ID(VERSAL_PUF_REGENERATE);
223 reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf),
224 &arg.data[2], &arg.data[1]);
225
226 if (versal_mbox_notify(&arg, NULL, &err)) {
227 EMSG("Versal, failed to regenerate the PUF [%s]",
228 versal_puf_error(err));
229
230 ret = TEE_ERROR_GENERIC;
231 }
232
233 /* Return the updated PUF_ID */
234 memcpy(buf->puf_id, puf_id_addr.buf, sizeof(buf->puf_id));
235
236 free(syndrome_data_addr.buf);
237 free(hash_addr.buf);
238 free(aux_addr.buf);
239 free(puf_id_addr.buf);
240 free(efuse_syn_data_addr.buf);
241
242 return ret;
243 }
244
245 /*
246 * Clear/Hide the PUF Unique ID
247 *
248 * The fully accessible (non-secret) Unique ID is generated from the PUF
249 */
versal_puf_clear_id(void)250 TEE_Result versal_puf_clear_id(void)
251 {
252 struct versal_ipi_cmd arg = { };
253
254 arg.data[0] = PUF_API_ID(VERSAL_PUF_CLEAR_ID);
255
256 if (versal_mbox_notify(&arg, NULL, NULL)) {
257 EMSG("Versal, failed to clear the PUF_ID");
258
259 return TEE_ERROR_GENERIC;
260 }
261
262 return TEE_SUCCESS;
263 }
264
265 /* Check that the API id is available to the client */
versal_puf_check_api(enum versal_puf_api id)266 TEE_Result versal_puf_check_api(enum versal_puf_api id)
267 {
268 struct versal_ipi_cmd arg = { };
269
270 arg.data[0] = PUF_API_ID(VERSAL_PUF_API_FEATURES);
271 arg.data[1] = id;
272
273 if (versal_mbox_notify(&arg, NULL, NULL))
274 return TEE_ERROR_GENERIC;
275
276 return TEE_SUCCESS;
277 }
278