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