1 /* 2 * Copyright (c) 2013, Google Inc. 3 * 4 * (C) Copyright 2008 Semihalf 5 * 6 * (C) Copyright 2000-2006 7 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12 #include "mkimage.h" 13 #include <bootm.h> 14 #include <image.h> 15 #include <version.h> 16 17 /** 18 * fit_set_hash_value - set hash value in requested has node 19 * @fit: pointer to the FIT format image header 20 * @noffset: hash node offset 21 * @value: hash value to be set 22 * @value_len: hash value length 23 * 24 * fit_set_hash_value() attempts to set hash value in a node at offset 25 * given and returns operation status to the caller. 26 * 27 * returns 28 * 0, on success 29 * -1, on failure 30 */ 31 static int fit_set_hash_value(void *fit, int noffset, uint8_t *value, 32 int value_len) 33 { 34 int ret; 35 36 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); 37 if (ret) { 38 printf("Can't set hash '%s' property for '%s' node(%s)\n", 39 FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), 40 fdt_strerror(ret)); 41 return -1; 42 } 43 44 return 0; 45 } 46 47 /** 48 * fit_image_process_hash - Process a single subnode of the images/ node 49 * 50 * Check each subnode and process accordingly. For hash nodes we generate 51 * a hash of the supplised data and store it in the node. 52 * 53 * @fit: pointer to the FIT format image header 54 * @image_name: name of image being processes (used to display errors) 55 * @noffset: subnode offset 56 * @data: data to process 57 * @size: size of data in bytes 58 * @return 0 if ok, -1 on error 59 */ 60 static int fit_image_process_hash(void *fit, const char *image_name, 61 int noffset, const void *data, size_t size) 62 { 63 uint8_t value[FIT_MAX_HASH_LEN]; 64 const char *node_name; 65 int value_len; 66 char *algo; 67 68 node_name = fit_get_name(fit, noffset, NULL); 69 70 if (fit_image_hash_get_algo(fit, noffset, &algo)) { 71 printf("Can't get hash algo property for '%s' hash node in '%s' image node\n", 72 node_name, image_name); 73 return -1; 74 } 75 76 if (calculate_hash(data, size, algo, value, &value_len)) { 77 printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", 78 algo, node_name, image_name); 79 return -1; 80 } 81 82 if (fit_set_hash_value(fit, noffset, value, value_len)) { 83 printf("Can't set hash value for '%s' hash node in '%s' image node\n", 84 node_name, image_name); 85 return -1; 86 } 87 88 return 0; 89 } 90 91 /** 92 * fit_image_write_sig() - write the signature to a FIT 93 * 94 * This writes the signature and signer data to the FIT. 95 * 96 * @fit: pointer to the FIT format image header 97 * @noffset: hash node offset 98 * @value: signature value to be set 99 * @value_len: signature value length 100 * @comment: Text comment to write (NULL for none) 101 * 102 * returns 103 * 0, on success 104 * -FDT_ERR_..., on failure 105 */ 106 static int fit_image_write_sig(void *fit, int noffset, uint8_t *value, 107 int value_len, const char *comment, const char *region_prop, 108 int region_proplen) 109 { 110 int string_size; 111 int ret; 112 113 /* 114 * Get the current string size, before we update the FIT and add 115 * more 116 */ 117 string_size = fdt_size_dt_strings(fit); 118 119 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); 120 if (!ret) { 121 ret = fdt_setprop_string(fit, noffset, "signer-name", 122 "mkimage"); 123 } 124 if (!ret) { 125 ret = fdt_setprop_string(fit, noffset, "signer-version", 126 PLAIN_VERSION); 127 } 128 if (comment && !ret) 129 ret = fdt_setprop_string(fit, noffset, "comment", comment); 130 if (!ret) 131 ret = fit_set_timestamp(fit, noffset, time(NULL)); 132 if (region_prop && !ret) { 133 uint32_t strdata[2]; 134 135 ret = fdt_setprop(fit, noffset, "hashed-nodes", 136 region_prop, region_proplen); 137 strdata[0] = 0; 138 strdata[1] = cpu_to_fdt32(string_size); 139 if (!ret) { 140 ret = fdt_setprop(fit, noffset, "hashed-strings", 141 strdata, sizeof(strdata)); 142 } 143 } 144 145 return ret; 146 } 147 148 static int fit_image_setup_sig(struct image_sign_info *info, 149 const char *keydir, void *fit, const char *image_name, 150 int noffset, const char *require_keys) 151 { 152 const char *node_name; 153 char *algo_name; 154 155 node_name = fit_get_name(fit, noffset, NULL); 156 if (fit_image_hash_get_algo(fit, noffset, &algo_name)) { 157 printf("Can't get algo property for '%s' signature node in '%s' image node\n", 158 node_name, image_name); 159 return -1; 160 } 161 162 memset(info, '\0', sizeof(*info)); 163 info->keydir = keydir; 164 info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL); 165 info->fit = fit; 166 info->node_offset = noffset; 167 info->algo = image_get_sig_algo(algo_name); 168 info->require_keys = require_keys; 169 if (!info->algo) { 170 printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n", 171 algo_name, node_name, image_name); 172 return -1; 173 } 174 175 return 0; 176 } 177 178 /** 179 * fit_image_process_sig- Process a single subnode of the images/ node 180 * 181 * Check each subnode and process accordingly. For signature nodes we 182 * generate a signed hash of the supplised data and store it in the node. 183 * 184 * @keydir: Directory containing keys to use for signing 185 * @keydest: Destination FDT blob to write public keys into 186 * @fit: pointer to the FIT format image header 187 * @image_name: name of image being processes (used to display errors) 188 * @noffset: subnode offset 189 * @data: data to process 190 * @size: size of data in bytes 191 * @comment: Comment to add to signature nodes 192 * @require_keys: Mark all keys as 'required' 193 * @return 0 if ok, -1 on error 194 */ 195 static int fit_image_process_sig(const char *keydir, void *keydest, 196 void *fit, const char *image_name, 197 int noffset, const void *data, size_t size, 198 const char *comment, int require_keys) 199 { 200 struct image_sign_info info; 201 struct image_region region; 202 const char *node_name; 203 uint8_t *value; 204 uint value_len; 205 int ret; 206 207 if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset, 208 require_keys ? "image" : NULL)) 209 return -1; 210 211 node_name = fit_get_name(fit, noffset, NULL); 212 region.data = data; 213 region.size = size; 214 ret = info.algo->sign(&info, ®ion, 1, &value, &value_len); 215 if (ret) { 216 printf("Failed to sign '%s' signature node in '%s' image node: %d\n", 217 node_name, image_name, ret); 218 219 /* We allow keys to be missing */ 220 if (ret == -ENOENT) 221 return 0; 222 return -1; 223 } 224 225 ret = fit_image_write_sig(fit, noffset, value, value_len, comment, 226 NULL, 0); 227 if (ret) { 228 if (ret == -FDT_ERR_NOSPACE) 229 return -ENOSPC; 230 printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n", 231 node_name, image_name, fdt_strerror(ret)); 232 return -1; 233 } 234 free(value); 235 236 /* Get keyname again, as FDT has changed and invalidated our pointer */ 237 info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL); 238 239 /* Write the public key into the supplied FDT file */ 240 if (keydest && info.algo->add_verify_data(&info, keydest)) { 241 printf("Failed to add verification data for '%s' signature node in '%s' image node\n", 242 node_name, image_name); 243 return -1; 244 } 245 246 return 0; 247 } 248 249 /** 250 * fit_image_add_verification_data() - calculate/set verig. data for image node 251 * 252 * This adds hash and signature values for an component image node. 253 * 254 * All existing hash subnodes are checked, if algorithm property is set to 255 * one of the supported hash algorithms, hash value is computed and 256 * corresponding hash node property is set, for example: 257 * 258 * Input component image node structure: 259 * 260 * o image@1 (at image_noffset) 261 * | - data = [binary data] 262 * o hash@1 263 * |- algo = "sha1" 264 * 265 * Output component image node structure: 266 * 267 * o image@1 (at image_noffset) 268 * | - data = [binary data] 269 * o hash@1 270 * |- algo = "sha1" 271 * |- value = sha1(data) 272 * 273 * For signature details, please see doc/uImage.FIT/signature.txt 274 * 275 * @keydir Directory containing *.key and *.crt files (or NULL) 276 * @keydest FDT Blob to write public keys into (NULL if none) 277 * @fit: Pointer to the FIT format image header 278 * @image_noffset: Requested component image node 279 * @comment: Comment to add to signature nodes 280 * @require_keys: Mark all keys as 'required' 281 * @return: 0 on success, <0 on failure 282 */ 283 int fit_image_add_verification_data(const char *keydir, void *keydest, 284 void *fit, int image_noffset, const char *comment, 285 int require_keys) 286 { 287 const char *image_name; 288 const void *data; 289 size_t size; 290 int noffset; 291 292 /* Get image data and data length */ 293 if (fit_image_get_data(fit, image_noffset, &data, &size)) { 294 printf("Can't get image data/size\n"); 295 return -1; 296 } 297 298 image_name = fit_get_name(fit, image_noffset, NULL); 299 300 /* Process all hash subnodes of the component image node */ 301 for (noffset = fdt_first_subnode(fit, image_noffset); 302 noffset >= 0; 303 noffset = fdt_next_subnode(fit, noffset)) { 304 const char *node_name; 305 int ret = 0; 306 307 /* 308 * Check subnode name, must be equal to "hash" or "signature". 309 * Multiple hash nodes require unique unit node 310 * names, e.g. hash@1, hash@2, signature@1, etc. 311 */ 312 node_name = fit_get_name(fit, noffset, NULL); 313 if (!strncmp(node_name, FIT_HASH_NODENAME, 314 strlen(FIT_HASH_NODENAME))) { 315 ret = fit_image_process_hash(fit, image_name, noffset, 316 data, size); 317 } else if (IMAGE_ENABLE_SIGN && keydir && 318 !strncmp(node_name, FIT_SIG_NODENAME, 319 strlen(FIT_SIG_NODENAME))) { 320 ret = fit_image_process_sig(keydir, keydest, 321 fit, image_name, noffset, data, size, 322 comment, require_keys); 323 } 324 if (ret) 325 return -1; 326 } 327 328 return 0; 329 } 330 331 struct strlist { 332 int count; 333 char **strings; 334 }; 335 336 static void strlist_init(struct strlist *list) 337 { 338 memset(list, '\0', sizeof(*list)); 339 } 340 341 static void strlist_free(struct strlist *list) 342 { 343 int i; 344 345 for (i = 0; i < list->count; i++) 346 free(list->strings[i]); 347 free(list->strings); 348 } 349 350 static int strlist_add(struct strlist *list, const char *str) 351 { 352 char *dup; 353 354 dup = strdup(str); 355 list->strings = realloc(list->strings, 356 (list->count + 1) * sizeof(char *)); 357 if (!list || !str) 358 return -1; 359 list->strings[list->count++] = dup; 360 361 return 0; 362 } 363 364 static const char *fit_config_get_image_list(void *fit, int noffset, 365 int *lenp, int *allow_missingp) 366 { 367 static const char default_list[] = FIT_KERNEL_PROP "\0" 368 FIT_FDT_PROP; 369 const char *prop; 370 371 /* If there is an "image" property, use that */ 372 prop = fdt_getprop(fit, noffset, "sign-images", lenp); 373 if (prop) { 374 *allow_missingp = 0; 375 return *lenp ? prop : NULL; 376 } 377 378 /* Default image list */ 379 *allow_missingp = 1; 380 *lenp = sizeof(default_list); 381 382 return default_list; 383 } 384 385 static int fit_config_get_hash_list(void *fit, int conf_noffset, 386 int sig_offset, struct strlist *node_inc) 387 { 388 int allow_missing; 389 const char *prop, *iname, *end; 390 const char *conf_name, *sig_name; 391 char name[200], path[200]; 392 int image_count; 393 int ret, len; 394 395 conf_name = fit_get_name(fit, conf_noffset, NULL); 396 sig_name = fit_get_name(fit, sig_offset, NULL); 397 398 /* 399 * Build a list of nodes we need to hash. We always need the root 400 * node and the configuration. 401 */ 402 strlist_init(node_inc); 403 snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name); 404 if (strlist_add(node_inc, "/") || 405 strlist_add(node_inc, name)) 406 goto err_mem; 407 408 /* Get a list of images that we intend to sign */ 409 prop = fit_config_get_image_list(fit, sig_offset, &len, 410 &allow_missing); 411 if (!prop) 412 return 0; 413 414 /* Locate the images */ 415 end = prop + len; 416 image_count = 0; 417 for (iname = prop; iname < end; iname += strlen(iname) + 1) { 418 int noffset; 419 int image_noffset; 420 int hash_count; 421 422 image_noffset = fit_conf_get_prop_node(fit, conf_noffset, 423 iname); 424 if (image_noffset < 0) { 425 printf("Failed to find image '%s' in configuration '%s/%s'\n", 426 iname, conf_name, sig_name); 427 if (allow_missing) 428 continue; 429 430 return -ENOENT; 431 } 432 433 ret = fdt_get_path(fit, image_noffset, path, sizeof(path)); 434 if (ret < 0) 435 goto err_path; 436 if (strlist_add(node_inc, path)) 437 goto err_mem; 438 439 snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, 440 conf_name); 441 442 /* Add all this image's hashes */ 443 hash_count = 0; 444 for (noffset = fdt_first_subnode(fit, image_noffset); 445 noffset >= 0; 446 noffset = fdt_next_subnode(fit, noffset)) { 447 const char *name = fit_get_name(fit, noffset, NULL); 448 449 if (strncmp(name, FIT_HASH_NODENAME, 450 strlen(FIT_HASH_NODENAME))) 451 continue; 452 ret = fdt_get_path(fit, noffset, path, sizeof(path)); 453 if (ret < 0) 454 goto err_path; 455 if (strlist_add(node_inc, path)) 456 goto err_mem; 457 hash_count++; 458 } 459 460 if (!hash_count) { 461 printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n", 462 conf_name, sig_name, iname); 463 return -ENOMSG; 464 } 465 466 image_count++; 467 } 468 469 if (!image_count) { 470 printf("Failed to find any images for configuration '%s/%s'\n", 471 conf_name, sig_name); 472 return -ENOMSG; 473 } 474 475 return 0; 476 477 err_mem: 478 printf("Out of memory processing configuration '%s/%s'\n", conf_name, 479 sig_name); 480 return -ENOMEM; 481 482 err_path: 483 printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n", 484 iname, conf_name, sig_name, fdt_strerror(ret)); 485 return -ENOENT; 486 } 487 488 static int fit_config_get_data(void *fit, int conf_noffset, int noffset, 489 struct image_region **regionp, int *region_countp, 490 char **region_propp, int *region_proplen) 491 { 492 char * const exc_prop[] = {"data"}; 493 struct strlist node_inc; 494 struct image_region *region; 495 struct fdt_region fdt_regions[100]; 496 const char *conf_name, *sig_name; 497 char path[200]; 498 int count, i; 499 char *region_prop; 500 int ret, len; 501 502 conf_name = fit_get_name(fit, conf_noffset, NULL); 503 sig_name = fit_get_name(fit, conf_noffset, NULL); 504 debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name); 505 506 /* Get a list of nodes we want to hash */ 507 ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc); 508 if (ret) 509 return ret; 510 511 /* Get a list of regions to hash */ 512 count = fdt_find_regions(fit, node_inc.strings, node_inc.count, 513 exc_prop, ARRAY_SIZE(exc_prop), 514 fdt_regions, ARRAY_SIZE(fdt_regions), 515 path, sizeof(path), 1); 516 if (count < 0) { 517 printf("Failed to hash configuration '%s/%s': %s\n", conf_name, 518 sig_name, fdt_strerror(ret)); 519 return -EIO; 520 } 521 if (count == 0) { 522 printf("No data to hash for configuration '%s/%s': %s\n", 523 conf_name, sig_name, fdt_strerror(ret)); 524 return -EINVAL; 525 } 526 527 /* Build our list of data blocks */ 528 region = fit_region_make_list(fit, fdt_regions, count, NULL); 529 if (!region) { 530 printf("Out of memory hashing configuration '%s/%s'\n", 531 conf_name, sig_name); 532 return -ENOMEM; 533 } 534 535 /* Create a list of all hashed properties */ 536 debug("Hash nodes:\n"); 537 for (i = len = 0; i < node_inc.count; i++) { 538 debug(" %s\n", node_inc.strings[i]); 539 len += strlen(node_inc.strings[i]) + 1; 540 } 541 region_prop = malloc(len); 542 if (!region_prop) { 543 printf("Out of memory setting up regions for configuration '%s/%s'\n", 544 conf_name, sig_name); 545 return -ENOMEM; 546 } 547 for (i = len = 0; i < node_inc.count; 548 len += strlen(node_inc.strings[i]) + 1, i++) 549 strcpy(region_prop + len, node_inc.strings[i]); 550 strlist_free(&node_inc); 551 552 *region_countp = count; 553 *regionp = region; 554 *region_propp = region_prop; 555 *region_proplen = len; 556 557 return 0; 558 } 559 560 static int fit_config_process_sig(const char *keydir, void *keydest, 561 void *fit, const char *conf_name, int conf_noffset, 562 int noffset, const char *comment, int require_keys) 563 { 564 struct image_sign_info info; 565 const char *node_name; 566 struct image_region *region; 567 char *region_prop; 568 int region_proplen; 569 int region_count; 570 uint8_t *value; 571 uint value_len; 572 int ret; 573 574 node_name = fit_get_name(fit, noffset, NULL); 575 if (fit_config_get_data(fit, conf_noffset, noffset, ®ion, 576 ®ion_count, ®ion_prop, ®ion_proplen)) 577 return -1; 578 579 if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset, 580 require_keys ? "conf" : NULL)) 581 return -1; 582 583 ret = info.algo->sign(&info, region, region_count, &value, &value_len); 584 free(region); 585 if (ret) { 586 printf("Failed to sign '%s' signature node in '%s' conf node\n", 587 node_name, conf_name); 588 589 /* We allow keys to be missing */ 590 if (ret == -ENOENT) 591 return 0; 592 return -1; 593 } 594 595 ret = fit_image_write_sig(fit, noffset, value, value_len, comment, 596 region_prop, region_proplen); 597 if (ret) { 598 if (ret == -FDT_ERR_NOSPACE) 599 return -ENOSPC; 600 printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n", 601 node_name, conf_name, fdt_strerror(ret)); 602 return -1; 603 } 604 free(value); 605 free(region_prop); 606 607 /* Get keyname again, as FDT has changed and invalidated our pointer */ 608 info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL); 609 610 /* Write the public key into the supplied FDT file */ 611 if (keydest) { 612 ret = info.algo->add_verify_data(&info, keydest); 613 if (ret == -ENOSPC) 614 return -ENOSPC; 615 if (ret) { 616 printf("Failed to add verification data for '%s' signature node in '%s' image node\n", 617 node_name, conf_name); 618 } 619 return ret; 620 } 621 622 return 0; 623 } 624 625 static int fit_config_add_verification_data(const char *keydir, void *keydest, 626 void *fit, int conf_noffset, const char *comment, 627 int require_keys) 628 { 629 const char *conf_name; 630 int noffset; 631 632 conf_name = fit_get_name(fit, conf_noffset, NULL); 633 634 /* Process all hash subnodes of the configuration node */ 635 for (noffset = fdt_first_subnode(fit, conf_noffset); 636 noffset >= 0; 637 noffset = fdt_next_subnode(fit, noffset)) { 638 const char *node_name; 639 int ret = 0; 640 641 node_name = fit_get_name(fit, noffset, NULL); 642 if (!strncmp(node_name, FIT_SIG_NODENAME, 643 strlen(FIT_SIG_NODENAME))) { 644 ret = fit_config_process_sig(keydir, keydest, 645 fit, conf_name, conf_noffset, noffset, comment, 646 require_keys); 647 } 648 if (ret) 649 return ret; 650 } 651 652 return 0; 653 } 654 655 int fit_add_verification_data(const char *keydir, void *keydest, void *fit, 656 const char *comment, int require_keys) 657 { 658 int images_noffset, confs_noffset; 659 int noffset; 660 int ret; 661 662 /* Find images parent node offset */ 663 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 664 if (images_noffset < 0) { 665 printf("Can't find images parent node '%s' (%s)\n", 666 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 667 return images_noffset; 668 } 669 670 /* Process its subnodes, print out component images details */ 671 for (noffset = fdt_first_subnode(fit, images_noffset); 672 noffset >= 0; 673 noffset = fdt_next_subnode(fit, noffset)) { 674 /* 675 * Direct child node of the images parent node, 676 * i.e. component image node. 677 */ 678 ret = fit_image_add_verification_data(keydir, keydest, 679 fit, noffset, comment, require_keys); 680 if (ret) 681 return ret; 682 } 683 684 /* If there are no keys, we can't sign configurations */ 685 if (!IMAGE_ENABLE_SIGN || !keydir) 686 return 0; 687 688 /* Find configurations parent node offset */ 689 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); 690 if (confs_noffset < 0) { 691 printf("Can't find images parent node '%s' (%s)\n", 692 FIT_CONFS_PATH, fdt_strerror(confs_noffset)); 693 return -ENOENT; 694 } 695 696 /* Process its subnodes, print out component images details */ 697 for (noffset = fdt_first_subnode(fit, confs_noffset); 698 noffset >= 0; 699 noffset = fdt_next_subnode(fit, noffset)) { 700 ret = fit_config_add_verification_data(keydir, keydest, 701 fit, noffset, comment, 702 require_keys); 703 if (ret) 704 return ret; 705 } 706 707 return 0; 708 } 709 710 #ifdef CONFIG_FIT_SIGNATURE 711 int fit_check_sign(const void *fit, const void *key) 712 { 713 int cfg_noffset; 714 int ret; 715 716 cfg_noffset = fit_conf_get_node(fit, NULL); 717 if (!cfg_noffset) 718 return -1; 719 720 printf("Verifying Hash Integrity ... "); 721 ret = fit_config_verify(fit, cfg_noffset); 722 if (ret) 723 return ret; 724 ret = bootm_host_load_images(fit, cfg_noffset); 725 726 return ret; 727 } 728 #endif 729