1 /* 2 * Copyright (c) 2020, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <stddef.h> 9 10 #include <common/fdt_wrappers.h> 11 #include <drivers/auth/mbedtls/mbedtls_config.h> 12 #include <drivers/auth/auth_mod.h> 13 #include <lib/fconf/fconf.h> 14 #include <lib/object_pool.h> 15 #include <libfdt.h> 16 17 #include <tools_share/tbbr_oid.h> 18 19 /* static structures used during authentication process */ 20 static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( 21 AUTH_PARAM_SIG, 0); 22 static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( 23 AUTH_PARAM_SIG_ALG, 0); 24 static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( 25 AUTH_PARAM_RAW_DATA, 0); 26 27 /* pointers to an array of CoT descriptors */ 28 static const auth_img_desc_t *cot_desc[MAX_NUMBER_IDS]; 29 /* array of CoT descriptors */ 30 static auth_img_desc_t auth_img_descs[MAX_NUMBER_IDS]; 31 32 /* array of authentication methods structures */ 33 static auth_method_desc_t auth_methods[MAX_NUMBER_IDS * AUTH_METHOD_NUM]; 34 static OBJECT_POOL_ARRAY(auth_methods_pool, auth_methods); 35 36 /* array of authentication params structures */ 37 static auth_param_desc_t auth_params[MAX_NUMBER_IDS * COT_MAX_VERIFIED_PARAMS]; 38 static OBJECT_POOL_ARRAY(auth_params_pool, auth_params); 39 40 /* array of authentication param type structures */ 41 static auth_param_type_desc_t auth_param_type_descs[MAX_NUMBER_IDS]; 42 static OBJECT_POOL_ARRAY(auth_param_type_descs_pool, auth_param_type_descs); 43 44 /* 45 * array of OIDs 46 * Object IDs are used to search hash, pk, counter values in certificate. 47 * As per binding we have below 2 combinations: 48 * 1. Certificates are validated using nv-cntr and pk 49 * 2. Raw images are authenticated using hash 50 * Hence in worst case, there are maximum 2 OIDs per image/certificate 51 */ 52 static unsigned char oids[(MAX_NUMBER_IDS * 2)][MAX_OID_NAME_LEN]; 53 static OBJECT_POOL_ARRAY(oid_pool, oids); 54 55 /* An array of auth buffer which holds hashes and pk 56 * ToDo: Size decided with the current number of images and 57 * certificates which are available in CoT. Size of these buffers bound to 58 * increase in the future on the addition of images/certificates. 59 */ 60 static unsigned char hash_auth_bufs[20][HASH_DER_LEN]; 61 static OBJECT_POOL_ARRAY(hash_auth_buf_pool, hash_auth_bufs); 62 static unsigned char pk_auth_bufs[12][PK_DER_LEN]; 63 static OBJECT_POOL_ARRAY(pk_auth_buf_pool, pk_auth_bufs); 64 65 /******************************************************************************* 66 * update_parent_auth_data() - Update authentication data structure 67 * @auth_desc[in]: Pointer to the auth image descriptor 68 * @type_desc[in]: Pointer to authentication parameter 69 * @auth_buf_size[in]: Buffer size to hold pk or hash 70 * 71 * Return 0 on success or an error value otherwise. 72 ******************************************************************************/ 73 static int update_parent_auth_data(const auth_img_desc_t *auth_desc, 74 auth_param_type_desc_t *type_desc, 75 unsigned int auth_buf_size) 76 { 77 unsigned int i; 78 auth_param_desc_t *auth_data = &auth_desc->authenticated_data[0]; 79 unsigned char *auth_buf; 80 81 for (i = 0U; i < COT_MAX_VERIFIED_PARAMS; i++) { 82 if (auth_data[i].type_desc == type_desc) { 83 return 0; 84 } 85 if (auth_data[i].type_desc == NULL) { 86 break; 87 } 88 } 89 90 if (auth_buf_size == HASH_DER_LEN) { 91 auth_buf = pool_alloc(&hash_auth_buf_pool); 92 } else if (auth_buf_size == PK_DER_LEN) { 93 auth_buf = pool_alloc(&pk_auth_buf_pool); 94 } else { 95 return -1; 96 } 97 98 if (i < COT_MAX_VERIFIED_PARAMS) { 99 auth_data[i].type_desc = type_desc; 100 auth_data[i].data.ptr = auth_buf; 101 auth_data[i].data.len = auth_buf_size; 102 } else { 103 ERROR("Out of authentication data array\n"); 104 return -1; 105 } 106 107 return 0; 108 } 109 110 /******************************************************************************* 111 * get_auth_param_type_desc() - Get pointer of authentication parameter 112 * @img_id[in]: Image Id 113 * @type_desc[out]: Pointer to authentication parameter 114 * @buf_size[out]: Buffer size which hold hash/pk 115 * 116 * Return 0 on success or an error value otherwise. 117 ******************************************************************************/ 118 static int get_auth_param_type_desc(unsigned int img_id, 119 auth_param_type_desc_t **type_desc, 120 unsigned int *buf_size) 121 { 122 auth_method_desc_t *img_auth_method = NULL; 123 img_type_t type = auth_img_descs[img_id].img_type; 124 125 if (type == IMG_CERT) { 126 img_auth_method = 127 &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_SIG]; 128 *type_desc = img_auth_method->param.sig.pk; 129 *buf_size = PK_DER_LEN; 130 } else if (type == IMG_RAW) { 131 img_auth_method = 132 &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_HASH]; 133 *type_desc = img_auth_method->param.hash.hash; 134 *buf_size = HASH_DER_LEN; 135 } else { 136 return -1; 137 } 138 139 return 0; 140 } 141 142 /******************************************************************************* 143 * set_auth_method() - Update global auth image descriptors with authentication 144 * method data 145 * @auth_method_type[in]: Type of authentication method 146 * @oid[in]: Object Idetifier for pk/hash search 147 * @auth_method[in]: Pointer to authentication method to set 148 ******************************************************************************/ 149 static void set_auth_method(auth_method_type_t auth_method_type, char *oid, 150 auth_method_desc_t *auth_method) 151 { 152 auth_param_type_t auth_param_type = AUTH_PARAM_NONE; 153 auth_param_type_desc_t *auth_param_type_desc; 154 155 assert(auth_method != NULL); 156 157 auth_param_type_desc = pool_alloc(&auth_param_type_descs_pool); 158 auth_method->type = auth_method_type; 159 160 if (auth_method_type == AUTH_METHOD_SIG) { 161 auth_param_type = AUTH_PARAM_PUB_KEY; 162 auth_method->param.sig.sig = &sig; 163 auth_method->param.sig.alg = &sig_alg; 164 auth_method->param.sig.data = &raw_data; 165 auth_method->param.sig.pk = auth_param_type_desc; 166 } else if (auth_method_type == AUTH_METHOD_HASH) { 167 auth_param_type = AUTH_PARAM_HASH; 168 auth_method->param.hash.data = &raw_data; 169 auth_method->param.hash.hash = auth_param_type_desc; 170 } else if (auth_method_type == AUTH_METHOD_NV_CTR) { 171 auth_param_type = AUTH_PARAM_NV_CTR; 172 auth_method->param.nv_ctr.cert_nv_ctr = auth_param_type_desc; 173 auth_method->param.nv_ctr.plat_nv_ctr = auth_param_type_desc; 174 } 175 176 auth_param_type_desc->type = auth_param_type; 177 auth_param_type_desc->cookie = (void *)oid; 178 } 179 180 /******************************************************************************* 181 * get_oid() - get object identifier from device tree 182 * @dtb[in]: Pointer to the device tree blob in memory 183 * @node[in]: Offset of the node 184 * @prop[in]: Property to read from the given node 185 * @oid[out]: Object Indentifier of key/hash/nv-counter in certificate 186 * 187 * Return 0 on success or an error value otherwise. 188 ******************************************************************************/ 189 static int get_oid(const void *dtb, int node, const char *prop, char **oid) 190 { 191 uint32_t phandle; 192 int rc; 193 194 rc = fdt_read_uint32(dtb, node, prop, &phandle); 195 if (rc < 0) { 196 return rc; 197 } 198 199 node = fdt_node_offset_by_phandle(dtb, phandle); 200 if (node < 0) { 201 return node; 202 } 203 204 *oid = pool_alloc(&oid_pool); 205 rc = fdtw_read_string(dtb, node, "oid", *oid, MAX_OID_NAME_LEN); 206 207 return rc; 208 } 209 210 /******************************************************************************* 211 * populate_and_set_auth_methods() - Populate auth method parameters from 212 * device tree and set authentication method 213 * structure. 214 * @dtb[in]: Pointer to the device tree blob in memory 215 * @node[in]: Offset of the node 216 * @img_id[in]: Image identifier 217 * @type[in]: Type of image 218 * @root_certificate[in]:Root certificate (authenticated by ROTPK) 219 * 220 * Return 0 on success or an error value otherwise. 221 ******************************************************************************/ 222 static int populate_and_set_auth_methods(const void *dtb, int node, 223 unsigned int img_id, img_type_t type, 224 bool root_certificate) 225 { 226 auth_method_type_t auth_method_type = AUTH_METHOD_NONE; 227 int rc; 228 char *oid = NULL; 229 230 auth_method_desc_t *auth_method = pool_alloc_n(&auth_methods_pool, 231 AUTH_METHOD_NUM); 232 233 /* 234 * This is as per binding document where certificates are 235 * verified by signature and images are verified by hash. 236 */ 237 if (type == IMG_CERT) { 238 if (root_certificate) { 239 oid = NULL; 240 } else { 241 rc = get_oid(dtb, node, "signing-key", &oid); 242 if (rc < 0) { 243 ERROR("FCONF: Can't read %s property\n", 244 "signing-key"); 245 return rc; 246 } 247 } 248 auth_method_type = AUTH_METHOD_SIG; 249 } else if (type == IMG_RAW) { 250 rc = get_oid(dtb, node, "hash", &oid); 251 if (rc < 0) { 252 ERROR("FCONF: Can't read %s property\n", 253 "hash"); 254 return rc; 255 } 256 auth_method_type = AUTH_METHOD_HASH; 257 } else { 258 return -1; 259 } 260 261 set_auth_method(auth_method_type, oid, 262 &auth_method[auth_method_type]); 263 264 /* Retrieve the optional property */ 265 rc = get_oid(dtb, node, "antirollback-counter", &oid); 266 if (rc == 0) { 267 auth_method_type = AUTH_METHOD_NV_CTR; 268 set_auth_method(auth_method_type, oid, 269 &auth_method[auth_method_type]); 270 } 271 272 auth_img_descs[img_id].img_auth_methods = &auth_method[0]; 273 274 return 0; 275 } 276 277 /******************************************************************************* 278 * get_parent_img_id() - Get parent image id for given child node 279 * @dtb[in]: Pointer to the device tree blob in memory 280 * @node[in]: Offset of the child node 281 * @parent_img_id[out]: Image id of parent 282 * 283 * Return 0 on success or an error value otherwise. 284 ******************************************************************************/ 285 static int get_parent_img_id(const void *dtb, int node, 286 unsigned int *parent_img_id) 287 { 288 uint32_t phandle; 289 int err; 290 291 err = fdt_read_uint32(dtb, node, "parent", &phandle); 292 if (err < 0) { 293 ERROR("FCONF: Could not read %s property in node\n", 294 "parent"); 295 return err; 296 } 297 298 node = fdt_node_offset_by_phandle(dtb, phandle); 299 if (node < 0) { 300 ERROR("FCONF: Failed to locate node using its phandle\n"); 301 return node; 302 } 303 304 err = fdt_read_uint32(dtb, node, "image-id", parent_img_id); 305 if (err < 0) { 306 ERROR("FCONF: Could not read %s property in node\n", 307 "image-id"); 308 } 309 310 return err; 311 } 312 313 /******************************************************************************* 314 * set_desc_data() - Update data in descriptor's structure 315 * @dtb[in]: Pointer to the device tree blob in memory 316 * @node[in]: Offset of the node 317 * @type[in]: Type of image (RAW/CERT) 318 * 319 * Return 0 on success or an error value otherwise. 320 ******************************************************************************/ 321 static int set_desc_data(const void *dtb, int node, img_type_t type) 322 { 323 int rc; 324 bool root_certificate = false; 325 unsigned int img_id, parent_img_id; 326 327 rc = fdt_read_uint32(dtb, node, "image-id", &img_id); 328 if (rc < 0) { 329 ERROR("FCONF: Can't find property %s in node\n", 330 "image-id"); 331 return rc; 332 } 333 334 if (fdt_getprop(dtb, node, "root-certificate", 335 NULL) != NULL) { 336 root_certificate = true; 337 } 338 339 if (!root_certificate) { 340 rc = get_parent_img_id(dtb, node, &parent_img_id); 341 if (rc < 0) { 342 return rc; 343 } 344 auth_img_descs[img_id].parent = &auth_img_descs[parent_img_id]; 345 } 346 347 auth_img_descs[img_id].img_id = img_id; 348 auth_img_descs[img_id].img_type = type; 349 350 rc = populate_and_set_auth_methods(dtb, node, img_id, type, 351 root_certificate); 352 if (rc < 0) { 353 return rc; 354 } 355 356 if (type == IMG_CERT) { 357 auth_param_desc_t *auth_param = 358 pool_alloc_n(&auth_params_pool, 359 COT_MAX_VERIFIED_PARAMS); 360 auth_img_descs[img_id].authenticated_data = &auth_param[0]; 361 } 362 363 cot_desc[img_id] = &auth_img_descs[img_id]; 364 365 return rc; 366 } 367 368 /******************************************************************************* 369 * populate_manifest_descs() - Populate CoT descriptors and update global 370 * certificate structures 371 * @dtb[in]: Pointer to the device tree blob in memory 372 * 373 * Return 0 on success or an error value otherwise. 374 ******************************************************************************/ 375 static int populate_manifest_descs(const void *dtb) 376 { 377 int node, child; 378 int rc; 379 380 /* 381 * Assert the node offset points to "arm, cert-descs" 382 * compatible property 383 */ 384 const char *compatible_str = "arm, cert-descs"; 385 386 node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); 387 if (node < 0) { 388 ERROR("FCONF: Can't find %s compatible in node\n", 389 compatible_str); 390 return node; 391 } 392 393 fdt_for_each_subnode(child, dtb, node) { 394 rc = set_desc_data(dtb, child, IMG_CERT); 395 if (rc < 0) { 396 return rc; 397 } 398 } 399 400 return 0; 401 } 402 403 /******************************************************************************* 404 * populate_image_descs() - Populate CoT descriptors and update global 405 * image descriptor structures. 406 * @dtb[in]: Pointer to the device tree blob in memory 407 * 408 * Return 0 on success or an error value otherwise. 409 ******************************************************************************/ 410 static int populate_image_descs(const void *dtb) 411 { 412 int node, child; 413 int rc; 414 415 /* 416 * Assert the node offset points to "arm, img-descs" 417 * compatible property 418 */ 419 const char *compatible_str = "arm, img-descs"; 420 421 node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); 422 if (node < 0) { 423 ERROR("FCONF: Can't find %s compatible in node\n", 424 compatible_str); 425 return node; 426 } 427 428 fdt_for_each_subnode(child, dtb, node) { 429 rc = set_desc_data(dtb, child, IMG_RAW); 430 if (rc < 0) { 431 return rc; 432 } 433 } 434 435 return 0; 436 } 437 438 /******************************************************************************* 439 * fconf_populate_cot_descs() - Populate CoT descriptors and update global 440 * structures 441 * @config[in]: Pointer to the device tree blob in memory 442 * 443 * Return 0 on success or an error value otherwise. 444 ******************************************************************************/ 445 static int fconf_populate_cot_descs(uintptr_t config) 446 { 447 auth_param_type_desc_t *type_desc = NULL; 448 unsigned int auth_buf_size = 0U; 449 int rc; 450 451 /* As libfdt uses void *, we can't avoid this cast */ 452 const void *dtb = (void *)config; 453 454 /* populate manifest descs information */ 455 rc = populate_manifest_descs(dtb); 456 if (rc < 0) { 457 ERROR("FCONF: population of %s descs failed %d\n", 458 "manifest", rc); 459 return rc; 460 } 461 462 /* populate image descs information */ 463 rc = populate_image_descs(dtb); 464 if (rc < 0) { 465 ERROR("FCONF: population of %s descs failed %d\n", 466 "images", rc); 467 return rc; 468 } 469 470 /* update parent's authentication data */ 471 for (unsigned int i = 0U; i < MAX_NUMBER_IDS; i++) { 472 if (auth_img_descs[i].parent != NULL) { 473 rc = get_auth_param_type_desc(i, 474 &type_desc, 475 &auth_buf_size); 476 if (rc < 0) { 477 ERROR("FCONF: failed to get auth data %d\n", 478 rc); 479 return rc; 480 } 481 482 rc = update_parent_auth_data(auth_img_descs[i].parent, 483 type_desc, 484 auth_buf_size); 485 if (rc < 0) { 486 ERROR("FCONF: auth data update failed %d\n", 487 rc); 488 return rc; 489 } 490 } 491 } 492 493 return rc; 494 } 495 496 FCONF_REGISTER_POPULATOR(TB_FW, cot_desc, fconf_populate_cot_descs); 497 REGISTER_COT(cot_desc); 498