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