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 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 */ 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 */ 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 */ 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 */ 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