1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2013, Google Inc. 4 * 5 * (C) Copyright 2008 Semihalf 6 * 7 * (C) Copyright 2000-2006 8 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 9 */ 10 11#include "mkimage.h" 12#include <bootm.h> 13#include <fdt_region.h> 14#include <image.h> 15#include <version.h> 16 17#if CONFIG_IS_ENABLED(FIT_SIGNATURE) 18#include <openssl/pem.h> 19#include <openssl/evp.h> 20#endif 21 22/** 23 * fit_set_hash_value - set hash value in requested has node 24 * @fit: pointer to the FIT format image header 25 * @noffset: hash node offset 26 * @value: hash value to be set 27 * @value_len: hash value length 28 * 29 * fit_set_hash_value() attempts to set hash value in a node at offset 30 * given and returns operation status to the caller. 31 * 32 * returns 33 * 0, on success 34 * -1, on failure 35 */ 36static int fit_set_hash_value(void *fit, int noffset, uint8_t *value, 37 int value_len) 38{ 39 int ret; 40 41 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); 42 if (ret) { 43 fprintf(stderr, "Can't set hash '%s' property for '%s' node(%s)\n", 44 FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), 45 fdt_strerror(ret)); 46 return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; 47 } 48 49 return 0; 50} 51 52/** 53 * fit_image_process_hash - Process a single subnode of the images/ node 54 * 55 * Check each subnode and process accordingly. For hash nodes we generate 56 * a hash of the supplied data and store it in the node. 57 * 58 * @fit: pointer to the FIT format image header 59 * @image_name: name of image being processed (used to display errors) 60 * @noffset: subnode offset 61 * @data: data to process 62 * @size: size of data in bytes 63 * Return: 0 if ok, -1 on error 64 */ 65static int fit_image_process_hash(void *fit, const char *image_name, 66 int noffset, const void *data, size_t size) 67{ 68 uint8_t value[FIT_MAX_HASH_LEN]; 69 const char *node_name; 70 int value_len; 71 const char *algo; 72 int ret; 73 74 node_name = fit_get_name(fit, noffset, NULL); 75 76 if (fit_image_hash_get_algo(fit, noffset, &algo)) { 77 fprintf(stderr, 78 "Can't get hash algo property for '%s' hash node in '%s' image node\n", 79 node_name, image_name); 80 return -ENOENT; 81 } 82 83 if (calculate_hash(data, size, algo, value, &value_len)) { 84 fprintf(stderr, 85 "Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", 86 algo, node_name, image_name); 87 return -EPROTONOSUPPORT; 88 } 89 90 ret = fit_set_hash_value(fit, noffset, value, value_len); 91 if (ret) { 92 fprintf(stderr, "Can't set hash value for '%s' hash node in '%s' image node\n", 93 node_name, image_name); 94 return ret; 95 } 96 97 return 0; 98} 99 100/** 101 * fit_image_write_sig() - write the signature to a FIT 102 * 103 * This writes the signature and signer data to the FIT. 104 * 105 * @fit: pointer to the FIT format image header 106 * @noffset: hash node offset 107 * @value: signature value to be set 108 * @value_len: signature value length 109 * @comment: Text comment to write (NULL for none) 110 * 111 * returns 112 * 0, on success 113 * -FDT_ERR_..., on failure 114 */ 115static int fit_image_write_sig(void *fit, int noffset, uint8_t *value, 116 int value_len, const char *comment, const char *region_prop, 117 int region_proplen, const char *cmdname, const char *algo_name) 118{ 119 int string_size; 120 int ret; 121 122 /* 123 * Get the current string size, before we update the FIT and add 124 * more 125 */ 126 string_size = fdt_size_dt_strings(fit); 127 128 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); 129 if (!ret) { 130 ret = fdt_setprop_string(fit, noffset, "signer-name", 131 "mkimage"); 132 } 133 if (!ret) { 134 ret = fdt_setprop_string(fit, noffset, "signer-version", 135 PLAIN_VERSION); 136 } 137 if (comment && !ret) 138 ret = fdt_setprop_string(fit, noffset, "comment", comment); 139 if (!ret) { 140 time_t timestamp = imagetool_get_source_date(cmdname, 141 time(NULL)); 142 uint32_t t = cpu_to_uimage(timestamp); 143 144 ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t, 145 sizeof(uint32_t)); 146 } 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 /* This is a legacy offset, it is unused, and must remain 0. */ 153 strdata[0] = 0; 154 strdata[1] = cpu_to_fdt32(string_size); 155 if (!ret) { 156 ret = fdt_setprop(fit, noffset, "hashed-strings", 157 strdata, sizeof(strdata)); 158 } 159 } 160 if (algo_name && !ret) 161 ret = fdt_setprop_string(fit, noffset, "algo", algo_name); 162 163 return ret; 164} 165 166static int fit_image_setup_sig(struct image_sign_info *info, 167 const char *keydir, const char *keyfile, void *fit, 168 const char *image_name, int noffset, const char *require_keys, 169 const char *engine_id, const char *algo_name) 170{ 171 const char *node_name; 172 const char *padding_name; 173 174 node_name = fit_get_name(fit, noffset, NULL); 175 if (!algo_name) { 176 if (fit_image_hash_get_algo(fit, noffset, &algo_name)) { 177 fprintf(stderr, 178 "Can't get algo property for '%s' signature node in '%s' image node\n", 179 node_name, image_name); 180 return -1; 181 } 182 } 183 184 padding_name = fdt_getprop(fit, noffset, "padding", NULL); 185 186 memset(info, '\0', sizeof(*info)); 187 info->keydir = keydir; 188 info->keyfile = keyfile; 189 info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL); 190 info->fit = fit; 191 info->node_offset = noffset; 192 info->name = strdup(algo_name); 193 info->checksum = image_get_checksum_algo(algo_name); 194 info->crypto = image_get_crypto_algo(algo_name); 195 info->padding = image_get_padding_algo(padding_name); 196 info->require_keys = require_keys; 197 info->engine_id = engine_id; 198 if (!info->checksum || !info->crypto) { 199 fprintf(stderr, 200 "Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n", 201 algo_name, node_name, image_name); 202 return -1; 203 } 204 205 return 0; 206} 207 208/** 209 * fit_image_process_sig- Process a single subnode of the images/ node 210 * 211 * Check each subnode and process accordingly. For signature nodes we 212 * generate a signed hash of the supplied data and store it in the node. 213 * 214 * @keydir: Directory containing keys to use for signing 215 * @keydest: Destination FDT blob to write public keys into (NULL if none) 216 * @fit: pointer to the FIT format image header 217 * @image_name: name of image being processed (used to display errors) 218 * @noffset: subnode offset 219 * @data: data to process 220 * @size: size of data in bytes 221 * @comment: Comment to add to signature nodes 222 * @require_keys: Mark all keys as 'required' 223 * @engine_id: Engine to use for signing 224 * Return: keydest node if @keydest is non-NULL, else 0 if none; -ve error code 225 * on failure 226 */ 227static int fit_image_process_sig(const char *keydir, const char *keyfile, 228 void *keydest, void *fit, const char *image_name, 229 int noffset, const void *data, size_t size, 230 const char *comment, int require_keys, const char *engine_id, 231 const char *cmdname, const char *algo_name) 232{ 233 struct image_sign_info info; 234 struct image_region region; 235 const char *node_name; 236 uint8_t *value; 237 uint value_len; 238 int ret; 239 240 if (fit_image_setup_sig(&info, keydir, keyfile, fit, image_name, 241 noffset, require_keys ? "image" : NULL, 242 engine_id, algo_name)) 243 return -1; 244 245 node_name = fit_get_name(fit, noffset, NULL); 246 region.data = data; 247 region.size = size; 248 ret = info.crypto->sign(&info, ®ion, 1, &value, &value_len); 249 if (ret) { 250 fprintf(stderr, "Failed to sign '%s' signature node in '%s' image node: %d\n", 251 node_name, image_name, ret); 252 253 /* We allow keys to be missing */ 254 if (ret == -ENOENT) 255 return 0; 256 return -1; 257 } 258 259 ret = fit_image_write_sig(fit, noffset, value, value_len, comment, 260 NULL, 0, cmdname, algo_name); 261 if (ret) { 262 if (ret == -FDT_ERR_NOSPACE) 263 return -ENOSPC; 264 fprintf(stderr, 265 "Can't write signature for '%s' signature node in '%s' conf node: %s\n", 266 node_name, image_name, fdt_strerror(ret)); 267 return -1; 268 } 269 free(value); 270 271 /* Get keyname again, as FDT has changed and invalidated our pointer */ 272 info.keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL); 273 274 /* 275 * Write the public key into the supplied FDT file; this might fail 276 * several times, since we try signing with successively increasing 277 * size values 278 */ 279 if (keydest) { 280 ret = info.crypto->add_verify_data(&info, keydest); 281 if (ret < 0) { 282 fprintf(stderr, 283 "Failed to add verification data for '%s' signature node in '%s' image node\n", 284 node_name, image_name); 285 return ret; 286 } 287 /* Return the node that was written to */ 288 return ret; 289 } 290 291 return 0; 292} 293 294static int fit_image_read_data(char *filename, unsigned char *data, 295 int expected_size) 296{ 297 struct stat sbuf; 298 int fd, ret = -1; 299 ssize_t n; 300 301 /* Open file */ 302 fd = open(filename, O_RDONLY | O_BINARY); 303 if (fd < 0) { 304 fprintf(stderr, "Can't open file %s (err=%d => %s)\n", 305 filename, errno, strerror(errno)); 306 return -1; 307 } 308 309 /* Compute file size */ 310 if (fstat(fd, &sbuf) < 0) { 311 fprintf(stderr, "Can't fstat file %s (err=%d => %s)\n", 312 filename, errno, strerror(errno)); 313 goto err; 314 } 315 316 /* Check file size */ 317 if (sbuf.st_size != expected_size) { 318 fprintf(stderr, "File %s don't have the expected size (size=%lld, expected=%d)\n", 319 filename, (long long)sbuf.st_size, expected_size); 320 goto err; 321 } 322 323 /* Read data */ 324 n = read(fd, data, sbuf.st_size); 325 if (n < 0) { 326 fprintf(stderr, "Can't read file %s (err=%d => %s)\n", 327 filename, errno, strerror(errno)); 328 goto err; 329 } 330 331 /* Check that we have read all the file */ 332 if (n != sbuf.st_size) { 333 fprintf(stderr, "Can't read all file %s (read %zd bytes, expected %lld)\n", 334 filename, n, (long long)sbuf.st_size); 335 goto err; 336 } 337 338 ret = 0; 339 340err: 341 close(fd); 342 return ret; 343} 344 345static int fit_image_read_key_iv_data(const char *keydir, const char *key_iv_name, 346 unsigned char *key_iv_data, int expected_size) 347{ 348 char filename[PATH_MAX]; 349 int ret; 350 351 ret = snprintf(filename, sizeof(filename), "%s/%s%s", 352 keydir, key_iv_name, ".bin"); 353 if (ret >= sizeof(filename)) { 354 fprintf(stderr, "Can't format the key or IV filename when setting up the cipher: insufficient buffer space\n"); 355 return -1; 356 } 357 if (ret < 0) { 358 fprintf(stderr, "Can't format the key or IV filename when setting up the cipher: snprintf error\n"); 359 return -1; 360 } 361 362 ret = fit_image_read_data(filename, key_iv_data, expected_size); 363 364 return ret; 365} 366 367static int get_random_data(void *data, int size) 368{ 369 unsigned char *tmp = data; 370 struct timespec date; 371 int i, ret; 372 373 if (!tmp) { 374 fprintf(stderr, "%s: pointer data is NULL\n", __func__); 375 ret = -1; 376 goto out; 377 } 378 379 ret = clock_gettime(CLOCK_MONOTONIC, &date); 380 if (ret) { 381 fprintf(stderr, "%s: clock_gettime has failed (%s)\n", __func__, 382 strerror(errno)); 383 goto out; 384 } 385 386 srandom(date.tv_nsec); 387 388 for (i = 0; i < size; i++) { 389 *tmp = random() & 0xff; 390 tmp++; 391 } 392 393 out: 394 return ret; 395} 396 397static int fit_image_setup_cipher(struct image_cipher_info *info, 398 const char *keydir, void *fit, 399 const char *image_name, int image_noffset, 400 int noffset) 401{ 402 char *algo_name; 403 int ret = -1; 404 405 if (fit_image_cipher_get_algo(fit, noffset, &algo_name)) { 406 fprintf(stderr, "Can't get algo name for cipher in image '%s'\n", 407 image_name); 408 goto out; 409 } 410 411 info->keydir = keydir; 412 413 /* Read the key name */ 414 info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL); 415 if (!info->keyname) { 416 fprintf(stderr, "Can't get key name for cipher in image '%s'\n", 417 image_name); 418 goto out; 419 } 420 421 /* 422 * Read the IV name 423 * 424 * If this property is not provided then mkimage will generate 425 * a random IV and store it in the FIT image 426 */ 427 info->ivname = fdt_getprop(fit, noffset, "iv-name-hint", NULL); 428 429 info->fit = fit; 430 info->node_noffset = noffset; 431 info->name = algo_name; 432 433 info->cipher = image_get_cipher_algo(algo_name); 434 if (!info->cipher) { 435 fprintf(stderr, "Can't get algo for cipher '%s'\n", image_name); 436 goto out; 437 } 438 439 info->key = malloc(info->cipher->key_len); 440 if (!info->key) { 441 fprintf(stderr, "Can't allocate memory for key\n"); 442 ret = -1; 443 goto out; 444 } 445 446 /* Read the key in the file */ 447 ret = fit_image_read_key_iv_data(info->keydir, info->keyname, 448 (unsigned char *)info->key, 449 info->cipher->key_len); 450 if (ret < 0) 451 goto out; 452 453 info->iv = malloc(info->cipher->iv_len); 454 if (!info->iv) { 455 fprintf(stderr, "Can't allocate memory for iv\n"); 456 ret = -1; 457 goto out; 458 } 459 460 if (info->ivname) { 461 /* Read the IV in the file */ 462 ret = fit_image_read_key_iv_data(info->keydir, info->ivname, 463 (unsigned char *)info->iv, 464 info->cipher->iv_len); 465 if (ret < 0) 466 goto out; 467 } else { 468 /* Generate an ramdom IV */ 469 ret = get_random_data((void *)info->iv, info->cipher->iv_len); 470 } 471 472 out: 473 return ret; 474} 475 476int fit_image_write_cipher(void *fit, int image_noffset, int noffset, 477 const void *data, size_t size, 478 unsigned char *data_ciphered, int data_ciphered_len) 479{ 480 int ret = -1; 481 482 /* Replace data with ciphered data */ 483 ret = fdt_setprop(fit, image_noffset, FIT_DATA_PROP, 484 data_ciphered, data_ciphered_len); 485 if (ret == -FDT_ERR_NOSPACE) { 486 ret = -ENOSPC; 487 goto out; 488 } 489 if (ret) { 490 fprintf(stderr, "Can't replace data with ciphered data (err = %d)\n", ret); 491 goto out; 492 } 493 494 /* add non ciphered data size */ 495 ret = fdt_setprop_u32(fit, image_noffset, "data-size-unciphered", size); 496 if (ret == -FDT_ERR_NOSPACE) { 497 ret = -ENOSPC; 498 goto out; 499 } 500 if (ret) { 501 fprintf(stderr, "Can't add unciphered data size (err = %d)\n", ret); 502 goto out; 503 } 504 505 out: 506 return ret; 507} 508 509static int 510fit_image_process_cipher(const char *keydir, void *keydest, void *fit, 511 const char *image_name, int image_noffset, 512 int node_noffset, const void *data, size_t size, 513 const char *cmdname) 514{ 515 struct image_cipher_info info; 516 unsigned char *data_ciphered = NULL; 517 int data_ciphered_len; 518 int ret; 519 520 memset(&info, 0, sizeof(info)); 521 522 ret = fit_image_setup_cipher(&info, keydir, fit, image_name, 523 image_noffset, node_noffset); 524 if (ret) 525 goto out; 526 527 ret = info.cipher->encrypt(&info, data, size, 528 &data_ciphered, &data_ciphered_len); 529 if (ret) 530 goto out; 531 532 /* 533 * Write the public key into the supplied FDT file; this might fail 534 * several times, since we try signing with successively increasing 535 * size values 536 * And, if needed, write the iv in the FIT file 537 */ 538 if (keydest) { 539 ret = info.cipher->add_cipher_data(&info, keydest, fit, node_noffset); 540 if (ret) { 541 fprintf(stderr, 542 "Failed to add verification data for cipher '%s' in image '%s'\n", 543 info.keyname, image_name); 544 goto out; 545 } 546 } 547 548 ret = fit_image_write_cipher(fit, image_noffset, node_noffset, 549 data, size, 550 data_ciphered, data_ciphered_len); 551 552 out: 553 free(data_ciphered); 554 free((void *)info.key); 555 free((void *)info.iv); 556 return ret; 557} 558 559int fit_image_cipher_data(const char *keydir, void *keydest, 560 void *fit, int image_noffset, const char *comment, 561 int require_keys, const char *engine_id, 562 const char *cmdname) 563{ 564 const char *image_name; 565 const void *data; 566 size_t size; 567 int cipher_node_offset, len; 568 569 /* Get image name */ 570 image_name = fit_get_name(fit, image_noffset, NULL); 571 if (!image_name) { 572 fprintf(stderr, "Can't get image name\n"); 573 return -1; 574 } 575 576 /* Get image data and data length */ 577 if (fit_image_get_data(fit, image_noffset, &data, &size)) { 578 fprintf(stderr, "Can't get image data/size\n"); 579 return -1; 580 } 581 582 /* 583 * Don't cipher ciphered data. 584 * 585 * If the data-size-unciphered property is present the data for this 586 * image is already encrypted. This is important as 'mkimage -F' can be 587 * run multiple times on a FIT image. 588 */ 589 if (fdt_getprop(fit, image_noffset, "data-size-unciphered", &len)) 590 return 0; 591 if (len != -FDT_ERR_NOTFOUND) { 592 fprintf(stderr, "Failure testing for data-size-unciphered\n"); 593 return -1; 594 } 595 596 /* Process cipher node if present */ 597 cipher_node_offset = fdt_subnode_offset(fit, image_noffset, 598 FIT_CIPHER_NODENAME); 599 if (cipher_node_offset == -FDT_ERR_NOTFOUND) 600 return 0; 601 if (cipher_node_offset < 0) { 602 fprintf(stderr, "Failure getting cipher node\n"); 603 return -1; 604 } 605 if (!IMAGE_ENABLE_ENCRYPT || !keydir) 606 return 0; 607 return fit_image_process_cipher(keydir, keydest, fit, image_name, 608 image_noffset, cipher_node_offset, data, size, cmdname); 609} 610 611/** 612 * fit_image_add_verification_data() - calculate/set verig. data for image node 613 * 614 * This adds hash and signature values for an component image node. 615 * 616 * All existing hash subnodes are checked, if algorithm property is set to 617 * one of the supported hash algorithms, hash value is computed and 618 * corresponding hash node property is set, for example: 619 * 620 * Input component image node structure: 621 * 622 * o image-1 (at image_noffset) 623 * | - data = [binary data] 624 * o hash-1 625 * |- algo = "sha1" 626 * 627 * Output component image node structure: 628 * 629 * o image-1 (at image_noffset) 630 * | - data = [binary data] 631 * o hash-1 632 * |- algo = "sha1" 633 * |- value = sha1(data) 634 * 635 * For signature details, please see doc/uImage.FIT/signature.txt 636 * 637 * @keydir Directory containing *.key and *.crt files (or NULL) 638 * @keydest FDT Blob to write public keys into (NULL if none) 639 * @fit: Pointer to the FIT format image header 640 * @image_noffset: Requested component image node 641 * @comment: Comment to add to signature nodes 642 * @require_keys: Mark all keys as 'required' 643 * @engine_id: Engine to use for signing 644 * @return: 0 on success, <0 on failure 645 */ 646int fit_image_add_verification_data(const char *keydir, const char *keyfile, 647 void *keydest, void *fit, int image_noffset, 648 const char *comment, int require_keys, const char *engine_id, 649 const char *cmdname, const char* algo_name) 650{ 651 const char *image_name; 652 const void *data; 653 size_t size; 654 int noffset; 655 656 /* Get image data and data length */ 657 if (fit_image_get_data(fit, image_noffset, &data, &size)) { 658 fprintf(stderr, "Can't get image data/size\n"); 659 return -1; 660 } 661 662 image_name = fit_get_name(fit, image_noffset, NULL); 663 664 /* Process all hash subnodes of the component image node */ 665 for (noffset = fdt_first_subnode(fit, image_noffset); 666 noffset >= 0; 667 noffset = fdt_next_subnode(fit, noffset)) { 668 const char *node_name; 669 int ret = 0; 670 671 /* 672 * Check subnode name, must be equal to "hash" or "signature". 673 * Multiple hash nodes require unique unit node 674 * names, e.g. hash-1, hash-2, signature-1, etc. 675 */ 676 node_name = fit_get_name(fit, noffset, NULL); 677 if (!strncmp(node_name, FIT_HASH_NODENAME, 678 strlen(FIT_HASH_NODENAME))) { 679 ret = fit_image_process_hash(fit, image_name, noffset, 680 data, size); 681 } else if (IMAGE_ENABLE_SIGN && (keydir || keyfile) && 682 !strncmp(node_name, FIT_SIG_NODENAME, 683 strlen(FIT_SIG_NODENAME))) { 684 ret = fit_image_process_sig(keydir, keyfile, keydest, 685 fit, image_name, noffset, data, size, 686 comment, require_keys, engine_id, cmdname, 687 algo_name); 688 } 689 if (ret < 0) 690 return ret; 691 } 692 693 return 0; 694} 695 696struct strlist { 697 int count; 698 char **strings; 699}; 700 701static void strlist_init(struct strlist *list) 702{ 703 memset(list, '\0', sizeof(*list)); 704} 705 706static void strlist_free(struct strlist *list) 707{ 708 int i; 709 710 for (i = 0; i < list->count; i++) 711 free(list->strings[i]); 712 free(list->strings); 713} 714 715static int strlist_add(struct strlist *list, const char *str) 716{ 717 char *dup; 718 719 dup = strdup(str); 720 list->strings = realloc(list->strings, 721 (list->count + 1) * sizeof(char *)); 722 if (!list || !str) 723 return -1; 724 list->strings[list->count++] = dup; 725 726 return 0; 727} 728 729static const char *fit_config_get_image_list(const void *fit, int noffset, 730 int *lenp, int *allow_missingp) 731{ 732 static const char default_list[] = FIT_KERNEL_PROP "\0" 733 FIT_FDT_PROP; 734 const char *prop; 735 736 /* If there is an "sign-image" property, use that */ 737 prop = fdt_getprop(fit, noffset, "sign-images", lenp); 738 if (prop) { 739 *allow_missingp = 0; 740 return *lenp ? prop : NULL; 741 } 742 743 /* Default image list */ 744 *allow_missingp = 1; 745 *lenp = sizeof(default_list); 746 747 return default_list; 748} 749 750/** 751 * fit_config_add_hash() - Add a list of nodes to hash for an image 752 * 753 * This adds a list of paths to image nodes (as referred to by a particular 754 * offset) that need to be hashed, to protect a configuration 755 * 756 * @fit: Pointer to the FIT format image header 757 * @image_noffset: Offset of image to process (e.g. /images/kernel-1) 758 * @node_inc: List of nodes to add to 759 * @conf_name Configuration-node name, child of /configurations node (only 760 * used for error messages) 761 * @sig_name Signature-node name (only used for error messages) 762 * @iname: Name of image being processed (e.g. "kernel-1" (only used 763 * for error messages) 764 */ 765static int fit_config_add_hash(const void *fit, int image_noffset, 766 struct strlist *node_inc, const char *conf_name, 767 const char *sig_name, const char *iname) 768{ 769 char path[200]; 770 int noffset; 771 int hash_count; 772 int ret; 773 774 ret = fdt_get_path(fit, image_noffset, path, sizeof(path)); 775 if (ret < 0) 776 goto err_path; 777 if (strlist_add(node_inc, path)) 778 goto err_mem; 779 780 /* Add all this image's hashes */ 781 hash_count = 0; 782 for (noffset = fdt_first_subnode(fit, image_noffset); 783 noffset >= 0; 784 noffset = fdt_next_subnode(fit, noffset)) { 785 const char *name = fit_get_name(fit, noffset, NULL); 786 787 if (strncmp(name, FIT_HASH_NODENAME, 788 strlen(FIT_HASH_NODENAME))) 789 continue; 790 ret = fdt_get_path(fit, noffset, path, sizeof(path)); 791 if (ret < 0) 792 goto err_path; 793 if (strlist_add(node_inc, path)) 794 goto err_mem; 795 hash_count++; 796 } 797 798 if (!hash_count) { 799 fprintf(stderr, 800 "Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n", 801 conf_name, sig_name, iname); 802 return -ENOMSG; 803 } 804 805 /* Add this image's cipher node if present */ 806 noffset = fdt_subnode_offset(fit, image_noffset, 807 FIT_CIPHER_NODENAME); 808 if (noffset != -FDT_ERR_NOTFOUND) { 809 if (noffset < 0) { 810 fprintf(stderr, 811 "Failed to get cipher node in configuration '%s/%s' image '%s': %s\n", 812 conf_name, sig_name, iname, 813 fdt_strerror(noffset)); 814 return -EIO; 815 } 816 ret = fdt_get_path(fit, noffset, path, sizeof(path)); 817 if (ret < 0) 818 goto err_path; 819 if (strlist_add(node_inc, path)) 820 goto err_mem; 821 } 822 823 return 0; 824 825err_mem: 826 fprintf(stderr, "Out of memory processing configuration '%s/%s'\n", conf_name, 827 sig_name); 828 return -ENOMEM; 829 830err_path: 831 fprintf(stderr, "Failed to get path for image '%s' in configuration '%s/%s': %s\n", 832 iname, conf_name, sig_name, fdt_strerror(ret)); 833 return -ENOENT; 834} 835 836/** 837 * fit_config_get_hash_list() - Get the regions to sign 838 * 839 * This calculates a list of nodes to hash for this particular configuration, 840 * returning it as a string list (struct strlist, not a devicetree string list) 841 * 842 * @fit: Pointer to the FIT format image header 843 * @conf_noffset: Offset of configuration node to sign (child of 844 * /configurations node) 845 * @sig_offset: Offset of signature node containing info about how to sign it 846 * (child of 'signatures' node) 847 * @return 0 if OK, -ENOENT if an image referred to by the configuration cannot 848 * be found, -ENOMSG if ther were no images in the configuration 849 */ 850static int fit_config_get_hash_list(const void *fit, int conf_noffset, 851 int sig_offset, struct strlist *node_inc) 852{ 853 int allow_missing; 854 const char *prop, *iname, *end; 855 const char *conf_name, *sig_name; 856 char name[200]; 857 int image_count; 858 int ret, len; 859 860 conf_name = fit_get_name(fit, conf_noffset, NULL); 861 sig_name = fit_get_name(fit, sig_offset, NULL); 862 863 /* 864 * Build a list of nodes we need to hash. We always need the root 865 * node and the configuration. 866 */ 867 strlist_init(node_inc); 868 snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name); 869 if (strlist_add(node_inc, "/") || 870 strlist_add(node_inc, name)) 871 goto err_mem; 872 873 /* Get a list of images that we intend to sign */ 874 prop = fit_config_get_image_list(fit, sig_offset, &len, 875 &allow_missing); 876 if (!prop) 877 return 0; 878 879 /* Locate the images */ 880 end = prop + len; 881 image_count = 0; 882 for (iname = prop; iname < end; iname += strlen(iname) + 1) { 883 int image_noffset; 884 int index, max_index; 885 886 max_index = fdt_stringlist_count(fit, conf_noffset, iname); 887 888 for (index = 0; index < max_index; index++) { 889 image_noffset = fit_conf_get_prop_node_index(fit, conf_noffset, 890 iname, index); 891 892 if (image_noffset < 0) { 893 fprintf(stderr, 894 "Failed to find image '%s' in configuration '%s/%s'\n", 895 iname, conf_name, sig_name); 896 if (allow_missing) 897 continue; 898 899 return -ENOENT; 900 } 901 902 ret = fit_config_add_hash(fit, image_noffset, node_inc, 903 conf_name, sig_name, iname); 904 if (ret < 0) 905 return ret; 906 907 image_count++; 908 } 909 } 910 911 if (!image_count) { 912 fprintf(stderr, "Failed to find any images for configuration '%s/%s'\n", 913 conf_name, sig_name); 914 return -ENOMSG; 915 } 916 917 return 0; 918 919err_mem: 920 fprintf(stderr, "Out of memory processing configuration '%s/%s'\n", conf_name, 921 sig_name); 922 return -ENOMEM; 923} 924 925/** 926 * fit_config_get_regions() - Get the regions to sign 927 * 928 * This calculates a list of node to hash for this particular configuration, 929 * then finds which regions of the devicetree they correspond to. 930 * 931 * @fit: Pointer to the FIT format image header 932 * @conf_noffset: Offset of configuration node to sign (child of 933 * /configurations node) 934 * @sig_offset: Offset of signature node containing info about how to sign it 935 * (child of 'signatures' node) 936 * @regionp: Returns list of regions that need to be hashed (allocated; must be 937 * freed by the caller) 938 * @region_count: Returns number of regions 939 * @region_propp: Returns string-list property containing the list of nodes 940 * that correspond to the regions. Each entry is a full path to the node. 941 * This is in devicetree format, i.e. a \0 between each string. This is 942 * allocated and must be freed by the caller. 943 * @region_proplen: Returns length of *@@region_propp in bytes 944 * @return 0 if OK, -ENOMEM if out of memory, -EIO if the regions to hash could 945 * not be found, -EINVAL if no registers were found to hash 946 */ 947static int fit_config_get_regions(const void *fit, int conf_noffset, 948 int sig_offset, struct image_region **regionp, 949 int *region_countp, char **region_propp, 950 int *region_proplen) 951{ 952 char * const exc_prop[] = { 953 FIT_DATA_PROP, 954 FIT_DATA_SIZE_PROP, 955 FIT_DATA_POSITION_PROP, 956 FIT_DATA_OFFSET_PROP, 957 }; 958 struct strlist node_inc; 959 struct image_region *region; 960 struct fdt_region fdt_regions[100]; 961 const char *conf_name, *sig_name; 962 char path[200]; 963 int count, i; 964 char *region_prop; 965 int ret, len; 966 967 conf_name = fit_get_name(fit, conf_noffset, NULL); 968 sig_name = fit_get_name(fit, sig_offset, NULL); 969 debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name); 970 971 /* Get a list of nodes we want to hash */ 972 ret = fit_config_get_hash_list(fit, conf_noffset, sig_offset, 973 &node_inc); 974 if (ret) 975 return ret; 976 977 /* Get a list of regions to hash */ 978 count = fdt_find_regions(fit, node_inc.strings, node_inc.count, 979 exc_prop, ARRAY_SIZE(exc_prop), 980 fdt_regions, ARRAY_SIZE(fdt_regions), 981 path, sizeof(path), 1); 982 if (count < 0) { 983 fprintf(stderr, "Failed to hash configuration '%s/%s': %s\n", conf_name, 984 sig_name, fdt_strerror(ret)); 985 return -EIO; 986 } 987 if (count == 0) { 988 fprintf(stderr, "No data to hash for configuration '%s/%s': %s\n", 989 conf_name, sig_name, fdt_strerror(ret)); 990 return -EINVAL; 991 } 992 993 /* Build our list of data blocks */ 994 region = fit_region_make_list(fit, fdt_regions, count, NULL); 995 if (!region) { 996 fprintf(stderr, "Out of memory hashing configuration '%s/%s'\n", 997 conf_name, sig_name); 998 return -ENOMEM; 999 } 1000 1001 /* Create a list of all hashed properties */ 1002 debug("Hash nodes:\n"); 1003 for (i = len = 0; i < node_inc.count; i++) { 1004 debug(" %s\n", node_inc.strings[i]); 1005 len += strlen(node_inc.strings[i]) + 1; 1006 } 1007 region_prop = malloc(len); 1008 if (!region_prop) { 1009 fprintf(stderr, "Out of memory setting up regions for configuration '%s/%s'\n", 1010 conf_name, sig_name); 1011 return -ENOMEM; 1012 } 1013 for (i = len = 0; i < node_inc.count; 1014 len += strlen(node_inc.strings[i]) + 1, i++) 1015 strcpy(region_prop + len, node_inc.strings[i]); 1016 strlist_free(&node_inc); 1017 1018 *region_countp = count; 1019 *regionp = region; 1020 *region_propp = region_prop; 1021 *region_proplen = len; 1022 1023 return 0; 1024} 1025 1026/** 1027 * fit_config_process_sig - Process a single subnode of the configurations/ node 1028 * 1029 * Generate a signed hash of the supplied data and store it in the node. 1030 * 1031 * @keydir: Directory containing keys to use for signing 1032 * @keydest: Destination FDT blob to write public keys into (NULL if none) 1033 * @fit: pointer to the FIT format image header 1034 * @conf_name name of config being processed (used to display errors) 1035 * @conf_noffset: Offset of configuration node, e.g. '/configurations/conf-1' 1036 * @noffset: subnode offset, e.g. '/configurations/conf-1/sig-1' 1037 * @comment: Comment to add to signature nodes 1038 * @require_keys: Mark all keys as 'required' 1039 * @engine_id: Engine to use for signing 1040 * @cmdname: Command name used when reporting errors 1041 * @return keydest node if @keydest is non-NULL, else 0 if none; -ve error code 1042 * on failure 1043 */ 1044static int fit_config_process_sig(const char *keydir, const char *keyfile, 1045 void *keydest, void *fit, const char *conf_name, 1046 int conf_noffset, int noffset, const char *comment, 1047 int require_keys, const char *engine_id, const char *cmdname, 1048 const char *algo_name) 1049{ 1050 struct image_sign_info info; 1051 const char *node_name; 1052 struct image_region *region; 1053 char *region_prop; 1054 int region_proplen; 1055 int region_count; 1056 uint8_t *value; 1057 uint value_len; 1058 int ret; 1059 1060 node_name = fit_get_name(fit, noffset, NULL); 1061 if (fit_config_get_regions(fit, conf_noffset, noffset, ®ion, 1062 ®ion_count, ®ion_prop, 1063 ®ion_proplen)) 1064 return -1; 1065 1066 if (fit_image_setup_sig(&info, keydir, keyfile, fit, conf_name, noffset, 1067 require_keys ? "conf" : NULL, engine_id, 1068 algo_name)) 1069 return -1; 1070 1071 ret = info.crypto->sign(&info, region, region_count, &value, 1072 &value_len); 1073 free(region); 1074 if (ret) { 1075 fprintf(stderr, "Failed to sign '%s' signature node in '%s' conf node\n", 1076 node_name, conf_name); 1077 1078 /* We allow keys to be missing */ 1079 if (ret == -ENOENT) 1080 return 0; 1081 return -1; 1082 } 1083 1084 ret = fit_image_write_sig(fit, noffset, value, value_len, comment, 1085 region_prop, region_proplen, cmdname, 1086 algo_name); 1087 if (ret) { 1088 if (ret == -FDT_ERR_NOSPACE) 1089 return -ENOSPC; 1090 fprintf(stderr, 1091 "Can't write signature for '%s' signature node in '%s' conf node: %s\n", 1092 node_name, conf_name, fdt_strerror(ret)); 1093 return -1; 1094 } 1095 free(value); 1096 free(region_prop); 1097 1098 /* Get keyname again, as FDT has changed and invalidated our pointer */ 1099 info.keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL); 1100 1101 /* Write the public key into the supplied FDT file */ 1102 if (keydest) { 1103 ret = info.crypto->add_verify_data(&info, keydest); 1104 if (ret < 0) { 1105 fprintf(stderr, 1106 "Failed to add verification data for '%s' signature node in '%s' configuration node\n", 1107 node_name, conf_name); 1108 } 1109 return ret; 1110 } 1111 1112 return 0; 1113} 1114 1115static int fit_config_add_verification_data(const char *keydir, 1116 const char *keyfile, void *keydest, void *fit, int conf_noffset, 1117 const char *comment, int require_keys, const char *engine_id, 1118 const char *cmdname, const char *algo_name, 1119 struct image_summary *summary) 1120{ 1121 const char *conf_name; 1122 int noffset; 1123 1124 conf_name = fit_get_name(fit, conf_noffset, NULL); 1125 1126 /* Process all hash subnodes of the configuration node */ 1127 for (noffset = fdt_first_subnode(fit, conf_noffset); 1128 noffset >= 0; 1129 noffset = fdt_next_subnode(fit, noffset)) { 1130 const char *node_name; 1131 int ret = 0; 1132 1133 node_name = fit_get_name(fit, noffset, NULL); 1134 if (!strncmp(node_name, FIT_SIG_NODENAME, 1135 strlen(FIT_SIG_NODENAME))) { 1136 ret = fit_config_process_sig(keydir, keyfile, keydest, 1137 fit, conf_name, conf_noffset, noffset, comment, 1138 require_keys, engine_id, cmdname, algo_name); 1139 if (ret < 0) 1140 return ret; 1141 1142 summary->sig_offset = noffset; 1143 fdt_get_path(fit, noffset, summary->sig_path, 1144 sizeof(summary->sig_path)); 1145 1146 if (keydest) { 1147 summary->keydest_offset = ret; 1148 fdt_get_path(keydest, ret, 1149 summary->keydest_path, 1150 sizeof(summary->keydest_path)); 1151 } 1152 } 1153 } 1154 1155 return 0; 1156} 1157 1158#if CONFIG_IS_ENABLED(FIT_SIGNATURE) 1159/* 1160 * 0) open file (open) 1161 * 1) read certificate (PEM_read_X509) 1162 * 2) get public key (X509_get_pubkey) 1163 * 3) provide der format (d2i_RSAPublicKey) 1164 */ 1165static int read_pub_key(const char *keydir, const void *name, 1166 unsigned char **pubkey, int *pubkey_len) 1167{ 1168 char path[1024]; 1169 EVP_PKEY *key = NULL; 1170 X509 *cert; 1171 FILE *f; 1172 int ret; 1173 1174 memset(path, 0, 1024); 1175 snprintf(path, sizeof(path), "%s/%s.crt", keydir, (char *)name); 1176 1177 /* Open certificate file */ 1178 f = fopen(path, "r"); 1179 if (!f) { 1180 fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n", 1181 path, strerror(errno)); 1182 return -EACCES; 1183 } 1184 1185 /* Read the certificate */ 1186 cert = NULL; 1187 if (!PEM_read_X509(f, &cert, NULL, NULL)) { 1188 fprintf(stderr, "Couldn't read certificate"); 1189 ret = -EINVAL; 1190 goto err_cert; 1191 } 1192 1193 /* Get the public key from the certificate. */ 1194 key = X509_get_pubkey(cert); 1195 if (!key) { 1196 fprintf(stderr, "Couldn't read public key\n"); 1197 ret = -EINVAL; 1198 goto err_pubkey; 1199 } 1200 1201 /* Get DER form */ 1202 ret = i2d_PublicKey(key, pubkey); 1203 if (ret < 0) { 1204 fprintf(stderr, "Couldn't get DER form\n"); 1205 ret = -EINVAL; 1206 goto err_pubkey; 1207 } 1208 1209 *pubkey_len = ret; 1210 ret = 0; 1211 1212err_pubkey: 1213 X509_free(cert); 1214err_cert: 1215 fclose(f); 1216 return ret; 1217} 1218 1219int fit_pre_load_data(const char *keydir, void *keydest, void *fit) 1220{ 1221 int pre_load_noffset; 1222 const void *algo_name; 1223 const void *key_name; 1224 unsigned char *pubkey = NULL; 1225 int ret, pubkey_len; 1226 1227 if (!keydir || !keydest || !fit) 1228 return 0; 1229 1230 /* Search node pre-load sig */ 1231 pre_load_noffset = fdt_path_offset(keydest, IMAGE_PRE_LOAD_PATH); 1232 if (pre_load_noffset < 0) { 1233 ret = 0; 1234 goto out; 1235 } 1236 1237 algo_name = fdt_getprop(keydest, pre_load_noffset, "algo-name", NULL); 1238 key_name = fdt_getprop(keydest, pre_load_noffset, "key-name", NULL); 1239 1240 /* Check that all mandatory properties are present */ 1241 if (!algo_name || !key_name) { 1242 if (!algo_name) 1243 fprintf(stderr, "The property algo-name is missing in the node %s\n", 1244 IMAGE_PRE_LOAD_PATH); 1245 if (!key_name) 1246 fprintf(stderr, "The property key-name is missing in the node %s\n", 1247 IMAGE_PRE_LOAD_PATH); 1248 ret = -EINVAL; 1249 goto out; 1250 } 1251 1252 /* Read public key */ 1253 ret = read_pub_key(keydir, key_name, &pubkey, &pubkey_len); 1254 if (ret < 0) 1255 goto out; 1256 1257 /* Add the public key to the device tree */ 1258 ret = fdt_setprop(keydest, pre_load_noffset, "public-key", 1259 pubkey, pubkey_len); 1260 if (ret) 1261 fprintf(stderr, "Can't set public-key in node %s (ret = %d)\n", 1262 IMAGE_PRE_LOAD_PATH, ret); 1263 1264 out: 1265 return ret; 1266} 1267#endif 1268 1269int fit_cipher_data(const char *keydir, void *keydest, void *fit, 1270 const char *comment, int require_keys, 1271 const char *engine_id, const char *cmdname) 1272{ 1273 int images_noffset; 1274 int noffset; 1275 int ret; 1276 1277 /* Find images parent node offset */ 1278 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 1279 if (images_noffset < 0) { 1280 fprintf(stderr, "Can't find images parent node '%s' (%s)\n", 1281 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 1282 return images_noffset; 1283 } 1284 1285 /* Process its subnodes, print out component images details */ 1286 for (noffset = fdt_first_subnode(fit, images_noffset); 1287 noffset >= 0; 1288 noffset = fdt_next_subnode(fit, noffset)) { 1289 /* 1290 * Direct child node of the images parent node, 1291 * i.e. component image node. 1292 */ 1293 ret = fit_image_cipher_data(keydir, keydest, 1294 fit, noffset, comment, 1295 require_keys, engine_id, 1296 cmdname); 1297 if (ret) 1298 return ret; 1299 } 1300 1301 return 0; 1302} 1303 1304int fit_add_verification_data(const char *keydir, const char *keyfile, 1305 void *keydest, void *fit, const char *comment, 1306 int require_keys, const char *engine_id, 1307 const char *cmdname, const char *algo_name, 1308 struct image_summary *summary) 1309{ 1310 int images_noffset, confs_noffset; 1311 int noffset; 1312 int ret; 1313 1314 /* Find images parent node offset */ 1315 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 1316 if (images_noffset < 0) { 1317 fprintf(stderr, "Can't find images parent node '%s' (%s)\n", 1318 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 1319 return images_noffset; 1320 } 1321 1322 /* Process its subnodes, print out component images details */ 1323 for (noffset = fdt_first_subnode(fit, images_noffset); 1324 noffset >= 0; 1325 noffset = fdt_next_subnode(fit, noffset)) { 1326 /* 1327 * Direct child node of the images parent node, 1328 * i.e. component image node. 1329 */ 1330 ret = fit_image_add_verification_data(keydir, keyfile, keydest, 1331 fit, noffset, comment, require_keys, engine_id, 1332 cmdname, algo_name); 1333 if (ret) { 1334 fprintf(stderr, "Can't add verification data for node '%s' (%s)\n", 1335 fdt_get_name(fit, noffset, NULL), 1336 fdt_strerror(ret)); 1337 return ret; 1338 } 1339 } 1340 1341 /* If there are no keys, we can't sign configurations */ 1342 if (!IMAGE_ENABLE_SIGN || !(keydir || keyfile)) 1343 return 0; 1344 1345 /* Find configurations parent node offset */ 1346 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); 1347 if (confs_noffset < 0) { 1348 fprintf(stderr, "Can't find images parent node '%s' (%s)\n", 1349 FIT_CONFS_PATH, fdt_strerror(confs_noffset)); 1350 return -ENOENT; 1351 } 1352 1353 /* Process its subnodes, print out component images details */ 1354 for (noffset = fdt_first_subnode(fit, confs_noffset); 1355 noffset >= 0; 1356 noffset = fdt_next_subnode(fit, noffset)) { 1357 ret = fit_config_add_verification_data(keydir, keyfile, keydest, 1358 fit, noffset, comment, 1359 require_keys, 1360 engine_id, cmdname, 1361 algo_name, summary); 1362 if (ret) 1363 return ret; 1364 } 1365 1366 return 0; 1367} 1368 1369#ifdef CONFIG_FIT_SIGNATURE 1370int fit_check_sign(const void *fit, const void *key, 1371 const char *fit_uname_config) 1372{ 1373 int cfg_noffset; 1374 int ret; 1375 1376 cfg_noffset = fit_conf_get_node(fit, fit_uname_config); 1377 if (!cfg_noffset) 1378 return -1; 1379 1380 printf("Verifying Hash Integrity for node '%s'... ", 1381 fdt_get_name(fit, cfg_noffset, NULL)); 1382 ret = fit_config_verify(fit, cfg_noffset); 1383 if (ret) 1384 return ret; 1385 printf("Verified OK, loading images\n"); 1386 ret = bootm_host_load_images(fit, cfg_noffset); 1387 1388 return ret; 1389} 1390#endif 1391