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