1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2013, Google Inc. 4 */ 5 6#ifdef USE_HOSTCC 7#include "mkimage.h" 8#include <time.h> 9#else 10#include <common.h> 11#include <log.h> 12#include <malloc.h> 13#include <asm/global_data.h> 14DECLARE_GLOBAL_DATA_PTR; 15#endif /* !USE_HOSTCC*/ 16#include <fdt_region.h> 17#include <image.h> 18#include <u-boot/rsa.h> 19#include <u-boot/hash-checksum.h> 20 21#define IMAGE_MAX_HASHED_NODES 100 22 23/** 24 * fit_region_make_list() - Make a list of image regions 25 * 26 * Given a list of fdt_regions, create a list of image_regions. This is a 27 * simple conversion routine since the FDT and image code use different 28 * structures. 29 * 30 * @fit: FIT image 31 * @fdt_regions: Pointer to FDT regions 32 * @count: Number of FDT regions 33 * @region: Pointer to image regions, which must hold @count records. If 34 * region is NULL, then (except for an SPL build) the array will be 35 * allocated. 36 * @return: Pointer to image regions 37 */ 38struct image_region *fit_region_make_list(const void *fit, 39 struct fdt_region *fdt_regions, 40 int count, 41 struct image_region *region) 42{ 43 int i; 44 45 debug("Hash regions:\n"); 46 debug("%10s %10s\n", "Offset", "Size"); 47 48 /* 49 * Use malloc() except in SPL (to save code size). In SPL the caller 50 * must allocate the array. 51 */ 52 if (!IS_ENABLED(CONFIG_SPL_BUILD) && !region) 53 region = calloc(sizeof(*region), count); 54 if (!region) 55 return NULL; 56 for (i = 0; i < count; i++) { 57 debug("%10x %10x\n", fdt_regions[i].offset, 58 fdt_regions[i].size); 59 region[i].data = fit + fdt_regions[i].offset; 60 region[i].size = fdt_regions[i].size; 61 } 62 63 return region; 64} 65 66static int fit_image_setup_verify(struct image_sign_info *info, 67 const void *fit, int noffset, 68 const void *key_blob, int required_keynode, 69 char **err_msgp) 70{ 71 const char *algo_name; 72 const char *padding_name; 73 74 if (fdt_totalsize(fit) > CONFIG_VAL(FIT_SIGNATURE_MAX_SIZE)) { 75 *err_msgp = "Total size too large"; 76 return 1; 77 } 78 if (fit_image_hash_get_algo(fit, noffset, &algo_name)) { 79 *err_msgp = "Can't get hash algo property"; 80 return -1; 81 } 82 83 padding_name = fdt_getprop(fit, noffset, "padding", NULL); 84 if (!padding_name) 85 padding_name = RSA_DEFAULT_PADDING_NAME; 86 87 memset(info, '\0', sizeof(*info)); 88 info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL); 89 info->fit = fit; 90 info->node_offset = noffset; 91 info->name = algo_name; 92 info->checksum = image_get_checksum_algo(algo_name); 93 info->crypto = image_get_crypto_algo(algo_name); 94 info->padding = image_get_padding_algo(padding_name); 95 info->fdt_blob = key_blob; 96 info->required_keynode = required_keynode; 97 printf("%s:%s", algo_name, info->keyname); 98 99 if (!info->checksum || !info->crypto || !info->padding) { 100 *err_msgp = "Unknown signature algorithm"; 101 return -1; 102 } 103 104 return 0; 105} 106 107int fit_image_check_sig(const void *fit, int noffset, const void *data, 108 size_t size, const void *key_blob, int required_keynode, 109 char **err_msgp) 110{ 111 struct image_sign_info info; 112 struct image_region region; 113 uint8_t *fit_value; 114 int fit_value_len; 115 116 *err_msgp = NULL; 117 if (fit_image_setup_verify(&info, fit, noffset, key_blob, 118 required_keynode, err_msgp)) 119 return -1; 120 121 if (fit_image_hash_get_value(fit, noffset, &fit_value, 122 &fit_value_len)) { 123 *err_msgp = "Can't get hash value property"; 124 return -1; 125 } 126 127 region.data = data; 128 region.size = size; 129 130 if (info.crypto->verify(&info, ®ion, 1, fit_value, fit_value_len)) { 131 *err_msgp = "Verification failed"; 132 return -1; 133 } 134 135 return 0; 136} 137 138static int fit_image_verify_sig(const void *fit, int image_noffset, 139 const char *data, size_t size, 140 const void *key_blob, int key_offset) 141{ 142 int noffset; 143 char *err_msg = ""; 144 int verified = 0; 145 int ret; 146 147 /* Process all hash subnodes of the component image node */ 148 fdt_for_each_subnode(noffset, fit, image_noffset) { 149 const char *name = fit_get_name(fit, noffset, NULL); 150 151 /* 152 * We don't support this since libfdt considers names with the 153 * name root but different @ suffix to be equal 154 */ 155 if (strchr(name, '@')) { 156 err_msg = "Node name contains @"; 157 goto error; 158 } 159 if (!strncmp(name, FIT_SIG_NODENAME, 160 strlen(FIT_SIG_NODENAME))) { 161 ret = fit_image_check_sig(fit, noffset, data, size, 162 key_blob, -1, &err_msg); 163 if (ret) { 164 puts("- "); 165 } else { 166 puts("+ "); 167 verified = 1; 168 break; 169 } 170 } 171 } 172 173 if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { 174 err_msg = "Corrupted or truncated tree"; 175 goto error; 176 } 177 178 return verified ? 0 : -EPERM; 179 180error: 181 printf(" error!\n%s for '%s' hash node in '%s' image node\n", 182 err_msg, fit_get_name(fit, noffset, NULL), 183 fit_get_name(fit, image_noffset, NULL)); 184 return -1; 185} 186 187int fit_image_verify_required_sigs(const void *fit, int image_noffset, 188 const char *data, size_t size, 189 const void *key_blob, int *no_sigsp) 190{ 191 int verify_count = 0; 192 int noffset; 193 int key_node; 194 195 /* Work out what we need to verify */ 196 *no_sigsp = 1; 197 key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME); 198 if (key_node < 0) { 199 debug("%s: No signature node found: %s\n", __func__, 200 fdt_strerror(key_node)); 201 return 0; 202 } 203 204 fdt_for_each_subnode(noffset, key_blob, key_node) { 205 const char *required; 206 int ret; 207 208 required = fdt_getprop(key_blob, noffset, FIT_KEY_REQUIRED, 209 NULL); 210 if (!required || strcmp(required, "image")) 211 continue; 212 ret = fit_image_verify_sig(fit, image_noffset, data, size, 213 key_blob, noffset); 214 if (ret) { 215 printf("Failed to verify required signature '%s'\n", 216 fit_get_name(key_blob, noffset, NULL)); 217 return ret; 218 } 219 verify_count++; 220 } 221 222 if (verify_count) 223 *no_sigsp = 0; 224 225 return 0; 226} 227 228/** 229 * fit_config_check_sig() - Check the signature of a config 230 * 231 * Here we are looking at a particular signature that needs verification (here 232 * signature-1): 233 * 234 * configurations { 235 * default = "conf-1"; 236 * conf-1 { 237 * kernel = "kernel-1"; 238 * fdt = "fdt-1"; 239 * signature-1 { 240 * algo = "sha1,rsa2048"; 241 * value = <...conf 1 signature...>; 242 * }; 243 * }; 244 * 245 * @fit: FIT to check 246 * @noffset: Offset of the signature node being checked (e.g. 247 * /configurations/conf-1/signature-1) 248 * @conf_noffset: Offset of configuration node (e.g. /configurations/conf-1) 249 * @key_blob: Blob containing the keys to check against 250 * @required_keynode: Offset in @key_blob of the required key node, 251 * if any. If this is given, then the configuration wil not 252 * pass verification unless that key is used. If this is 253 * -1 then any signature will do. 254 * @err_msgp: In the event of an error, this will be pointed to a 255 * help error string to display to the user. 256 * Return: 0 if all verified ok, <0 on error 257 */ 258static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset, 259 const void *key_blob, int required_keynode, 260 char **err_msgp) 261{ 262 static char * const exc_prop[] = { 263 FIT_DATA_PROP, 264 FIT_DATA_SIZE_PROP, 265 FIT_DATA_POSITION_PROP, 266 FIT_DATA_OFFSET_PROP, 267 }; 268 269 const char *prop, *end, *name; 270 struct image_sign_info info; 271 const uint32_t *strings; 272 const char *config_name; 273 uint8_t *fit_value; 274 int fit_value_len; 275 bool found_config; 276 int max_regions; 277 int i, prop_len; 278 char path[200]; 279 int count; 280 281 config_name = fit_get_name(fit, conf_noffset, NULL); 282 debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, key_blob, 283 fit_get_name(fit, noffset, NULL), 284 fit_get_name(key_blob, required_keynode, NULL)); 285 *err_msgp = NULL; 286 if (fit_image_setup_verify(&info, fit, noffset, key_blob, 287 required_keynode, err_msgp)) 288 return -1; 289 290 if (fit_image_hash_get_value(fit, noffset, &fit_value, 291 &fit_value_len)) { 292 *err_msgp = "Can't get hash value property"; 293 return -1; 294 } 295 296 /* Count the number of strings in the property */ 297 prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len); 298 end = prop ? prop + prop_len : prop; 299 for (name = prop, count = 0; name < end; name++) 300 if (!*name) 301 count++; 302 if (!count) { 303 *err_msgp = "Can't get hashed-nodes property"; 304 return -1; 305 } 306 307 if (prop && prop_len > 0 && prop[prop_len - 1] != '\0') { 308 *err_msgp = "hashed-nodes property must be null-terminated"; 309 return -1; 310 } 311 312 /* Add a sanity check here since we are using the stack */ 313 if (count > IMAGE_MAX_HASHED_NODES) { 314 *err_msgp = "Number of hashed nodes exceeds maximum"; 315 return -1; 316 } 317 318 /* Create a list of node names from those strings */ 319 char *node_inc[count]; 320 321 debug("Hash nodes (%d):\n", count); 322 found_config = false; 323 for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) { 324 debug(" '%s'\n", name); 325 node_inc[i] = (char *)name; 326 if (!strncmp(FIT_CONFS_PATH, name, strlen(FIT_CONFS_PATH)) && 327 name[sizeof(FIT_CONFS_PATH) - 1] == '/' && 328 !strcmp(name + sizeof(FIT_CONFS_PATH), config_name)) { 329 debug(" (found config node %s)", config_name); 330 found_config = true; 331 } 332 } 333 if (!found_config) { 334 *err_msgp = "Selected config not in hashed nodes"; 335 return -1; 336 } 337 338 /* 339 * Each node can generate one region for each sub-node. Allow for 340 * 7 sub-nodes (hash-1, signature-1, etc.) and some extra. 341 */ 342 max_regions = 20 + count * 7; 343 struct fdt_region fdt_regions[max_regions]; 344 345 /* Get a list of regions to hash */ 346 count = fdt_find_regions(fit, node_inc, count, 347 exc_prop, ARRAY_SIZE(exc_prop), 348 fdt_regions, max_regions - 1, 349 path, sizeof(path), 0); 350 if (count < 0) { 351 *err_msgp = "Failed to hash configuration"; 352 return -1; 353 } 354 if (count == 0) { 355 *err_msgp = "No data to hash"; 356 return -1; 357 } 358 if (count >= max_regions - 1) { 359 *err_msgp = "Too many hash regions"; 360 return -1; 361 } 362 363 /* Add the strings */ 364 strings = fdt_getprop(fit, noffset, "hashed-strings", NULL); 365 if (strings) { 366 /* 367 * The strings region offset must be a static 0x0. 368 * This is set in tool/image-host.c 369 */ 370 fdt_regions[count].offset = fdt_off_dt_strings(fit); 371 fdt_regions[count].size = fdt32_to_cpu(strings[1]); 372 count++; 373 } 374 375 /* Allocate the region list on the stack */ 376 struct image_region region[count]; 377 378 fit_region_make_list(fit, fdt_regions, count, region); 379 if (info.crypto->verify(&info, region, count, fit_value, 380 fit_value_len)) { 381 *err_msgp = "Verification failed"; 382 return -1; 383 } 384 385 return 0; 386} 387 388/** 389 * fit_config_verify_key() - Verify that a configuration is signed with a key 390 * 391 * Here we are looking at a particular configuration that needs verification: 392 * 393 * configurations { 394 * default = "conf-1"; 395 * conf-1 { 396 * kernel = "kernel-1"; 397 * fdt = "fdt-1"; 398 * signature-1 { 399 * algo = "sha1,rsa2048"; 400 * value = <...conf 1 signature...>; 401 * }; 402 * }; 403 * 404 * We must check each of the signature subnodes of conf-1. Hopefully one of them 405 * will match the key at key_offset. 406 * 407 * @fit: FIT to check 408 * @conf_noffset: Offset of the configuration node to check (e.g. 409 * /configurations/conf-1) 410 * @key_blob: Blob containing the keys to check against 411 * @key_offset: Offset of the key to check within @key_blob 412 * @return 0 if OK, -EPERM if any signatures did not verify, or the 413 * configuration node has an invalid name 414 */ 415static int fit_config_verify_key(const void *fit, int conf_noffset, 416 const void *key_blob, int key_offset) 417{ 418 int noffset; 419 char *err_msg = "No 'signature' subnode found"; 420 int verified = 0; 421 int ret; 422 423 /* Process all hash subnodes of the component conf node */ 424 fdt_for_each_subnode(noffset, fit, conf_noffset) { 425 const char *name = fit_get_name(fit, noffset, NULL); 426 427 if (!strncmp(name, FIT_SIG_NODENAME, 428 strlen(FIT_SIG_NODENAME))) { 429 ret = fit_config_check_sig(fit, noffset, conf_noffset, 430 key_blob, key_offset, 431 &err_msg); 432 if (ret) { 433 puts("- "); 434 } else { 435 puts("+ "); 436 verified = 1; 437 break; 438 } 439 } 440 } 441 442 if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { 443 err_msg = "Corrupted or truncated tree"; 444 goto error; 445 } 446 447 if (verified) 448 return 0; 449 450error: 451 printf(" error!\n%s for '%s' hash node in '%s' config node\n", 452 err_msg, fit_get_name(fit, noffset, NULL), 453 fit_get_name(fit, conf_noffset, NULL)); 454 return -EPERM; 455} 456 457/** 458 * fit_config_verify_required_keys() - verify any required signatures for config 459 * 460 * This looks through all the signatures we expect and verifies that at least 461 * all the required ones are valid signatures for the configuration 462 * 463 * @fit: FIT to check 464 * @conf_noffset: Offset of the configuration node to check (e.g. 465 * /configurations/conf-1) 466 * @key_blob: Blob containing the keys to check against 467 * @return 0 if OK, -EPERM if any signatures did not verify, or the 468 * configuration node has an invalid name 469 */ 470static int fit_config_verify_required_keys(const void *fit, int conf_noffset, 471 const void *key_blob) 472{ 473 const char *name = fit_get_name(fit, conf_noffset, NULL); 474 int noffset; 475 int key_node; 476 int verified = 0; 477 int reqd_sigs = 0; 478 bool reqd_policy_all = true; 479 const char *reqd_mode; 480 481 /* 482 * We don't support this since libfdt considers names with the 483 * name root but different @ suffix to be equal 484 */ 485 if (strchr(name, '@')) { 486 printf("Configuration node '%s' contains '@'\n", name); 487 return -EPERM; 488 } 489 490 /* Work out what we need to verify */ 491 key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME); 492 if (key_node < 0) { 493 debug("%s: No signature node found: %s\n", __func__, 494 fdt_strerror(key_node)); 495 return 0; 496 } 497 498 /* Get required-mode policy property from DTB */ 499 reqd_mode = fdt_getprop(key_blob, key_node, "required-mode", NULL); 500 if (reqd_mode && !strcmp(reqd_mode, "any")) 501 reqd_policy_all = false; 502 503 debug("%s: required-mode policy set to '%s'\n", __func__, 504 reqd_policy_all ? "all" : "any"); 505 506 /* 507 * The algorithm here is a little convoluted due to how we want it to 508 * work. Here we work through each of the signature nodes in the 509 * public-key area. These are in the U-Boot control devicetree. Each 510 * node was created by signing a configuration, so we check if it is 511 * 'required' and if so, request that it be verified. 512 */ 513 fdt_for_each_subnode(noffset, key_blob, key_node) { 514 const char *required; 515 int ret; 516 517 required = fdt_getprop(key_blob, noffset, FIT_KEY_REQUIRED, 518 NULL); 519 if (!required || strcmp(required, "conf")) 520 continue; 521 522 reqd_sigs++; 523 524 ret = fit_config_verify_key(fit, conf_noffset, key_blob, 525 noffset); 526 if (ret) { 527 if (reqd_policy_all) { 528 printf("Failed to verify required signature '%s'\n", 529 fit_get_name(key_blob, noffset, NULL)); 530 return ret; 531 } 532 } else { 533 verified++; 534 if (!reqd_policy_all) 535 break; 536 } 537 } 538 539 if (reqd_sigs && !verified) { 540 printf("Failed to verify 'any' of the required signature(s)\n"); 541 return -EPERM; 542 } 543 544 return 0; 545} 546 547int fit_config_verify(const void *fit, int conf_noffset) 548{ 549 return fit_config_verify_required_keys(fit, conf_noffset, 550 gd_fdt_blob()); 551} 552