uboot/tools/image-host.c
<<
>>
Prefs
   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/**
  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 */
  31static 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 */
  60static 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 */
 108static 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, const char *cmdname)
 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                time_t timestamp = imagetool_get_source_date(cmdname,
 134                                                             time(NULL));
 135                uint32_t t = cpu_to_uimage(timestamp);
 136
 137                ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
 138                        sizeof(uint32_t));
 139        }
 140        if (region_prop && !ret) {
 141                uint32_t strdata[2];
 142
 143                ret = fdt_setprop(fit, noffset, "hashed-nodes",
 144                                   region_prop, region_proplen);
 145                /* This is a legacy offset, it is unused, and must remain 0. */
 146                strdata[0] = 0;
 147                strdata[1] = cpu_to_fdt32(string_size);
 148                if (!ret) {
 149                        ret = fdt_setprop(fit, noffset, "hashed-strings",
 150                                          strdata, sizeof(strdata));
 151                }
 152        }
 153
 154        return ret;
 155}
 156
 157static int fit_image_setup_sig(struct image_sign_info *info,
 158                const char *keydir, const char *keyfile, void *fit,
 159                const char *image_name, int noffset, const char *require_keys,
 160                const char *engine_id)
 161{
 162        const char *node_name;
 163        char *algo_name;
 164        const char *padding_name;
 165
 166        node_name = fit_get_name(fit, noffset, NULL);
 167        if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
 168                printf("Can't get algo property for '%s' signature node in '%s' image node\n",
 169                       node_name, image_name);
 170                return -1;
 171        }
 172
 173        padding_name = fdt_getprop(fit, noffset, "padding", NULL);
 174
 175        memset(info, '\0', sizeof(*info));
 176        info->keydir = keydir;
 177        info->keyfile = keyfile;
 178        info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
 179        info->fit = fit;
 180        info->node_offset = noffset;
 181        info->name = strdup(algo_name);
 182        info->checksum = image_get_checksum_algo(algo_name);
 183        info->crypto = image_get_crypto_algo(algo_name);
 184        info->padding = image_get_padding_algo(padding_name);
 185        info->require_keys = require_keys;
 186        info->engine_id = engine_id;
 187        if (!info->checksum || !info->crypto) {
 188                printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
 189                       algo_name, node_name, image_name);
 190                return -1;
 191        }
 192
 193        return 0;
 194}
 195
 196/**
 197 * fit_image_process_sig- Process a single subnode of the images/ node
 198 *
 199 * Check each subnode and process accordingly. For signature nodes we
 200 * generate a signed hash of the supplised data and store it in the node.
 201 *
 202 * @keydir:     Directory containing keys to use for signing
 203 * @keydest:    Destination FDT blob to write public keys into
 204 * @fit:        pointer to the FIT format image header
 205 * @image_name: name of image being processes (used to display errors)
 206 * @noffset:    subnode offset
 207 * @data:       data to process
 208 * @size:       size of data in bytes
 209 * @comment:    Comment to add to signature nodes
 210 * @require_keys: Mark all keys as 'required'
 211 * @engine_id:  Engine to use for signing
 212 * @return 0 if ok, -1 on error
 213 */
 214static int fit_image_process_sig(const char *keydir, const char *keyfile,
 215                void *keydest, void *fit, const char *image_name,
 216                int noffset, const void *data, size_t size,
 217                const char *comment, int require_keys, const char *engine_id,
 218                const char *cmdname)
 219{
 220        struct image_sign_info info;
 221        struct image_region region;
 222        const char *node_name;
 223        uint8_t *value;
 224        uint value_len;
 225        int ret;
 226
 227        if (fit_image_setup_sig(&info, keydir, keyfile, fit, image_name,
 228                                noffset, require_keys ? "image" : NULL,
 229                                engine_id))
 230                return -1;
 231
 232        node_name = fit_get_name(fit, noffset, NULL);
 233        region.data = data;
 234        region.size = size;
 235        ret = info.crypto->sign(&info, &region, 1, &value, &value_len);
 236        if (ret) {
 237                printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
 238                       node_name, image_name, ret);
 239
 240                /* We allow keys to be missing */
 241                if (ret == -ENOENT)
 242                        return 0;
 243                return -1;
 244        }
 245
 246        ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
 247                        NULL, 0, cmdname);
 248        if (ret) {
 249                if (ret == -FDT_ERR_NOSPACE)
 250                        return -ENOSPC;
 251                printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
 252                       node_name, image_name, fdt_strerror(ret));
 253                return -1;
 254        }
 255        free(value);
 256
 257        /* Get keyname again, as FDT has changed and invalidated our pointer */
 258        info.keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
 259
 260        /*
 261         * Write the public key into the supplied FDT file; this might fail
 262         * several times, since we try signing with successively increasing
 263         * size values
 264         */
 265        if (keydest) {
 266                ret = info.crypto->add_verify_data(&info, keydest);
 267                if (ret) {
 268                        printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
 269                               node_name, image_name);
 270                        return ret;
 271                }
 272        }
 273
 274        return 0;
 275}
 276
 277static int fit_image_read_data(char *filename, unsigned char *data,
 278                               int expected_size)
 279{
 280        struct stat sbuf;
 281        int fd, ret = -1;
 282        ssize_t n;
 283
 284        /* Open file */
 285        fd = open(filename, O_RDONLY | O_BINARY);
 286        if (fd < 0) {
 287                printf("Can't open file %s (err=%d => %s)\n",
 288                       filename, errno, strerror(errno));
 289                return -1;
 290        }
 291
 292        /* Compute file size */
 293        if (fstat(fd, &sbuf) < 0) {
 294                printf("Can't fstat file %s (err=%d => %s)\n",
 295                       filename, errno, strerror(errno));
 296                goto err;
 297        }
 298
 299        /* Check file size */
 300        if (sbuf.st_size != expected_size) {
 301                printf("File %s don't have the expected size (size=%lld, expected=%d)\n",
 302                       filename, (long long)sbuf.st_size, expected_size);
 303                goto err;
 304        }
 305
 306        /* Read data */
 307        n = read(fd, data, sbuf.st_size);
 308        if (n < 0) {
 309                printf("Can't read file %s (err=%d => %s)\n",
 310                       filename, errno, strerror(errno));
 311                goto err;
 312        }
 313
 314        /* Check that we have read all the file */
 315        if (n != sbuf.st_size) {
 316                printf("Can't read all file %s (read %zd bytes, expected %lld)\n",
 317                       filename, n, (long long)sbuf.st_size);
 318                goto err;
 319        }
 320
 321        ret = 0;
 322
 323err:
 324        close(fd);
 325        return ret;
 326}
 327
 328static int get_random_data(void *data, int size)
 329{
 330        unsigned char *tmp = data;
 331        struct timespec date;
 332        int i, ret;
 333
 334        if (!tmp) {
 335                printf("%s: pointer data is NULL\n", __func__);
 336                ret = -1;
 337                goto out;
 338        }
 339
 340        ret = clock_gettime(CLOCK_MONOTONIC, &date);
 341        if (ret) {
 342                printf("%s: clock_gettime has failed (%s)\n", __func__,
 343                       strerror(errno));
 344                goto out;
 345        }
 346
 347        srandom(date.tv_nsec);
 348
 349        for (i = 0; i < size; i++) {
 350                *tmp = random() & 0xff;
 351                tmp++;
 352        }
 353
 354 out:
 355        return ret;
 356}
 357
 358static int fit_image_setup_cipher(struct image_cipher_info *info,
 359                                  const char *keydir, void *fit,
 360                                  const char *image_name, int image_noffset,
 361                                  int noffset)
 362{
 363        char *algo_name;
 364        char filename[128];
 365        int ret = -1;
 366
 367        if (fit_image_cipher_get_algo(fit, noffset, &algo_name)) {
 368                printf("Can't get algo name for cipher in image '%s'\n",
 369                       image_name);
 370                goto out;
 371        }
 372
 373        info->keydir = keydir;
 374
 375        /* Read the key name */
 376        info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
 377        if (!info->keyname) {
 378                printf("Can't get key name for cipher in image '%s'\n",
 379                       image_name);
 380                goto out;
 381        }
 382
 383        /*
 384         * Read the IV name
 385         *
 386         * If this property is not provided then mkimage will generate
 387         * a random IV and store it in the FIT image
 388         */
 389        info->ivname = fdt_getprop(fit, noffset, "iv-name-hint", NULL);
 390
 391        info->fit = fit;
 392        info->node_noffset = noffset;
 393        info->name = algo_name;
 394
 395        info->cipher = image_get_cipher_algo(algo_name);
 396        if (!info->cipher) {
 397                printf("Can't get algo for cipher '%s'\n", image_name);
 398                goto out;
 399        }
 400
 401        /* Read the key in the file */
 402        snprintf(filename, sizeof(filename), "%s/%s%s",
 403                 info->keydir, info->keyname, ".bin");
 404        info->key = malloc(info->cipher->key_len);
 405        if (!info->key) {
 406                printf("Can't allocate memory for key\n");
 407                ret = -1;
 408                goto out;
 409        }
 410        ret = fit_image_read_data(filename, (unsigned char *)info->key,
 411                                  info->cipher->key_len);
 412        if (ret < 0)
 413                goto out;
 414
 415        info->iv = malloc(info->cipher->iv_len);
 416        if (!info->iv) {
 417                printf("Can't allocate memory for iv\n");
 418                ret = -1;
 419                goto out;
 420        }
 421
 422        if (info->ivname) {
 423                /* Read the IV in the file */
 424                snprintf(filename, sizeof(filename), "%s/%s%s",
 425                         info->keydir, info->ivname, ".bin");
 426                ret = fit_image_read_data(filename, (unsigned char *)info->iv,
 427                                          info->cipher->iv_len);
 428        } else {
 429                /* Generate an ramdom IV */
 430                ret = get_random_data((void *)info->iv, info->cipher->iv_len);
 431        }
 432
 433 out:
 434        return ret;
 435}
 436
 437int fit_image_write_cipher(void *fit, int image_noffset, int noffset,
 438                           const void *data, size_t size,
 439                           unsigned char *data_ciphered, int data_ciphered_len)
 440{
 441        int ret = -1;
 442
 443        /* Replace data with ciphered data */
 444        ret = fdt_setprop(fit, image_noffset, FIT_DATA_PROP,
 445                          data_ciphered, data_ciphered_len);
 446        if (ret == -FDT_ERR_NOSPACE) {
 447                ret = -ENOSPC;
 448                goto out;
 449        }
 450        if (ret) {
 451                printf("Can't replace data with ciphered data (err = %d)\n", ret);
 452                goto out;
 453        }
 454
 455        /* add non ciphered data size */
 456        ret = fdt_setprop_u32(fit, image_noffset, "data-size-unciphered", size);
 457        if (ret == -FDT_ERR_NOSPACE) {
 458                ret = -ENOSPC;
 459                goto out;
 460        }
 461        if (ret) {
 462                printf("Can't add unciphered data size (err = %d)\n", ret);
 463                goto out;
 464        }
 465
 466 out:
 467        return ret;
 468}
 469
 470static int
 471fit_image_process_cipher(const char *keydir, void *keydest, void *fit,
 472                         const char *image_name, int image_noffset,
 473                         int node_noffset, const void *data, size_t size,
 474                         const char *cmdname)
 475{
 476        struct image_cipher_info info;
 477        unsigned char *data_ciphered = NULL;
 478        int data_ciphered_len;
 479        int ret;
 480
 481        memset(&info, 0, sizeof(info));
 482
 483        ret = fit_image_setup_cipher(&info, keydir, fit, image_name,
 484                                     image_noffset, node_noffset);
 485        if (ret)
 486                goto out;
 487
 488        ret = info.cipher->encrypt(&info, data, size,
 489                                    &data_ciphered, &data_ciphered_len);
 490        if (ret)
 491                goto out;
 492
 493        /*
 494         * Write the public key into the supplied FDT file; this might fail
 495         * several times, since we try signing with successively increasing
 496         * size values
 497         * And, if needed, write the iv in the FIT file
 498         */
 499        if (keydest) {
 500                ret = info.cipher->add_cipher_data(&info, keydest, fit, node_noffset);
 501                if (ret) {
 502                        printf("Failed to add verification data for cipher '%s' in image '%s'\n",
 503                               info.keyname, image_name);
 504                        goto out;
 505                }
 506        }
 507
 508        ret = fit_image_write_cipher(fit, image_noffset, node_noffset,
 509                                     data, size,
 510                                     data_ciphered, data_ciphered_len);
 511
 512 out:
 513        free(data_ciphered);
 514        free((void *)info.key);
 515        free((void *)info.iv);
 516        return ret;
 517}
 518
 519int fit_image_cipher_data(const char *keydir, void *keydest,
 520                          void *fit, int image_noffset, const char *comment,
 521                          int require_keys, const char *engine_id,
 522                          const char *cmdname)
 523{
 524        const char *image_name;
 525        const void *data;
 526        size_t size;
 527        int cipher_node_offset, len;
 528
 529        /* Get image name */
 530        image_name = fit_get_name(fit, image_noffset, NULL);
 531        if (!image_name) {
 532                printf("Can't get image name\n");
 533                return -1;
 534        }
 535
 536        /* Get image data and data length */
 537        if (fit_image_get_data(fit, image_noffset, &data, &size)) {
 538                printf("Can't get image data/size\n");
 539                return -1;
 540        }
 541
 542        /*
 543         * Don't cipher ciphered data.
 544         *
 545         * If the data-size-unciphered property is present the data for this
 546         * image is already encrypted. This is important as 'mkimage -F' can be
 547         * run multiple times on a FIT image.
 548         */
 549        if (fdt_getprop(fit, image_noffset, "data-size-unciphered", &len))
 550                return 0;
 551        if (len != -FDT_ERR_NOTFOUND) {
 552                printf("Failure testing for data-size-unciphered\n");
 553                return -1;
 554        }
 555
 556        /* Process cipher node if present */
 557        cipher_node_offset = fdt_subnode_offset(fit, image_noffset,
 558                                                FIT_CIPHER_NODENAME);
 559        if (cipher_node_offset == -FDT_ERR_NOTFOUND)
 560                return 0;
 561        if (cipher_node_offset < 0) {
 562                printf("Failure getting cipher node\n");
 563                return -1;
 564        }
 565        if (!IMAGE_ENABLE_ENCRYPT || !keydir)
 566                return 0;
 567        return fit_image_process_cipher(keydir, keydest, fit, image_name,
 568                image_noffset, cipher_node_offset, data, size, cmdname);
 569}
 570
 571/**
 572 * fit_image_add_verification_data() - calculate/set verig. data for image node
 573 *
 574 * This adds hash and signature values for an component image node.
 575 *
 576 * All existing hash subnodes are checked, if algorithm property is set to
 577 * one of the supported hash algorithms, hash value is computed and
 578 * corresponding hash node property is set, for example:
 579 *
 580 * Input component image node structure:
 581 *
 582 * o image-1 (at image_noffset)
 583 *   | - data = [binary data]
 584 *   o hash-1
 585 *     |- algo = "sha1"
 586 *
 587 * Output component image node structure:
 588 *
 589 * o image-1 (at image_noffset)
 590 *   | - data = [binary data]
 591 *   o hash-1
 592 *     |- algo = "sha1"
 593 *     |- value = sha1(data)
 594 *
 595 * For signature details, please see doc/uImage.FIT/signature.txt
 596 *
 597 * @keydir      Directory containing *.key and *.crt files (or NULL)
 598 * @keydest     FDT Blob to write public keys into (NULL if none)
 599 * @fit:        Pointer to the FIT format image header
 600 * @image_noffset: Requested component image node
 601 * @comment:    Comment to add to signature nodes
 602 * @require_keys: Mark all keys as 'required'
 603 * @engine_id:  Engine to use for signing
 604 * @return: 0 on success, <0 on failure
 605 */
 606int fit_image_add_verification_data(const char *keydir, const char *keyfile,
 607                void *keydest, void *fit, int image_noffset,
 608                const char *comment, int require_keys, const char *engine_id,
 609                const char *cmdname)
 610{
 611        const char *image_name;
 612        const void *data;
 613        size_t size;
 614        int noffset;
 615
 616        /* Get image data and data length */
 617        if (fit_image_get_data(fit, image_noffset, &data, &size)) {
 618                printf("Can't get image data/size\n");
 619                return -1;
 620        }
 621
 622        image_name = fit_get_name(fit, image_noffset, NULL);
 623
 624        /* Process all hash subnodes of the component image node */
 625        for (noffset = fdt_first_subnode(fit, image_noffset);
 626             noffset >= 0;
 627             noffset = fdt_next_subnode(fit, noffset)) {
 628                const char *node_name;
 629                int ret = 0;
 630
 631                /*
 632                 * Check subnode name, must be equal to "hash" or "signature".
 633                 * Multiple hash nodes require unique unit node
 634                 * names, e.g. hash-1, hash-2, signature-1, etc.
 635                 */
 636                node_name = fit_get_name(fit, noffset, NULL);
 637                if (!strncmp(node_name, FIT_HASH_NODENAME,
 638                             strlen(FIT_HASH_NODENAME))) {
 639                        ret = fit_image_process_hash(fit, image_name, noffset,
 640                                                data, size);
 641                } else if (IMAGE_ENABLE_SIGN && (keydir || keyfile) &&
 642                           !strncmp(node_name, FIT_SIG_NODENAME,
 643                                strlen(FIT_SIG_NODENAME))) {
 644                        ret = fit_image_process_sig(keydir, keyfile, keydest,
 645                                fit, image_name, noffset, data, size,
 646                                comment, require_keys, engine_id, cmdname);
 647                }
 648                if (ret)
 649                        return ret;
 650        }
 651
 652        return 0;
 653}
 654
 655struct strlist {
 656        int count;
 657        char **strings;
 658};
 659
 660static void strlist_init(struct strlist *list)
 661{
 662        memset(list, '\0', sizeof(*list));
 663}
 664
 665static void strlist_free(struct strlist *list)
 666{
 667        int i;
 668
 669        for (i = 0; i < list->count; i++)
 670                free(list->strings[i]);
 671        free(list->strings);
 672}
 673
 674static int strlist_add(struct strlist *list, const char *str)
 675{
 676        char *dup;
 677
 678        dup = strdup(str);
 679        list->strings = realloc(list->strings,
 680                                (list->count + 1) * sizeof(char *));
 681        if (!list || !str)
 682                return -1;
 683        list->strings[list->count++] = dup;
 684
 685        return 0;
 686}
 687
 688static const char *fit_config_get_image_list(void *fit, int noffset,
 689                int *lenp, int *allow_missingp)
 690{
 691        static const char default_list[] = FIT_KERNEL_PROP "\0"
 692                        FIT_FDT_PROP;
 693        const char *prop;
 694
 695        /* If there is an "image" property, use that */
 696        prop = fdt_getprop(fit, noffset, "sign-images", lenp);
 697        if (prop) {
 698                *allow_missingp = 0;
 699                return *lenp ? prop : NULL;
 700        }
 701
 702        /* Default image list */
 703        *allow_missingp = 1;
 704        *lenp = sizeof(default_list);
 705
 706        return default_list;
 707}
 708
 709static int fit_config_add_hash(void *fit, const char *conf_name, const char *sig_name,
 710                               struct strlist *node_inc, const char *iname, int image_noffset)
 711{
 712        char name[200], path[200];
 713        int noffset;
 714        int hash_count;
 715        int ret;
 716
 717        ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
 718        if (ret < 0)
 719                goto err_path;
 720        if (strlist_add(node_inc, path))
 721                goto err_mem;
 722
 723        snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH,
 724                 conf_name);
 725
 726        /* Add all this image's hashes */
 727        hash_count = 0;
 728        for (noffset = fdt_first_subnode(fit, image_noffset);
 729             noffset >= 0;
 730             noffset = fdt_next_subnode(fit, noffset)) {
 731                const char *name = fit_get_name(fit, noffset, NULL);
 732
 733                if (strncmp(name, FIT_HASH_NODENAME,
 734                            strlen(FIT_HASH_NODENAME)))
 735                        continue;
 736                ret = fdt_get_path(fit, noffset, path, sizeof(path));
 737                if (ret < 0)
 738                        goto err_path;
 739                if (strlist_add(node_inc, path))
 740                        goto err_mem;
 741                hash_count++;
 742        }
 743
 744        if (!hash_count) {
 745                printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
 746                       conf_name, sig_name, iname);
 747                return -ENOMSG;
 748        }
 749
 750        /* Add this image's cipher node if present */
 751        noffset = fdt_subnode_offset(fit, image_noffset,
 752                                     FIT_CIPHER_NODENAME);
 753        if (noffset != -FDT_ERR_NOTFOUND) {
 754                if (noffset < 0) {
 755                        printf("Failed to get cipher node in configuration '%s/%s' image '%s': %s\n",
 756                               conf_name, sig_name, iname,
 757                               fdt_strerror(noffset));
 758                        return -EIO;
 759                }
 760                ret = fdt_get_path(fit, noffset, path, sizeof(path));
 761                if (ret < 0)
 762                        goto err_path;
 763                if (strlist_add(node_inc, path))
 764                        goto err_mem;
 765        }
 766
 767        return 0;
 768
 769err_mem:
 770        printf("Out of memory processing configuration '%s/%s'\n", conf_name,
 771               sig_name);
 772        return -ENOMEM;
 773
 774err_path:
 775        printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n",
 776               iname, conf_name, sig_name, fdt_strerror(ret));
 777        return -ENOENT;
 778}
 779
 780static int fit_config_get_hash_list(void *fit, int conf_noffset,
 781                                    int sig_offset, struct strlist *node_inc)
 782{
 783        int allow_missing;
 784        const char *prop, *iname, *end;
 785        const char *conf_name, *sig_name;
 786        char name[200];
 787        int image_count;
 788        int ret, len;
 789
 790        conf_name = fit_get_name(fit, conf_noffset, NULL);
 791        sig_name = fit_get_name(fit, sig_offset, NULL);
 792
 793        /*
 794         * Build a list of nodes we need to hash. We always need the root
 795         * node and the configuration.
 796         */
 797        strlist_init(node_inc);
 798        snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name);
 799        if (strlist_add(node_inc, "/") ||
 800            strlist_add(node_inc, name))
 801                goto err_mem;
 802
 803        /* Get a list of images that we intend to sign */
 804        prop = fit_config_get_image_list(fit, sig_offset, &len,
 805                                        &allow_missing);
 806        if (!prop)
 807                return 0;
 808
 809        /* Locate the images */
 810        end = prop + len;
 811        image_count = 0;
 812        for (iname = prop; iname < end; iname += strlen(iname) + 1) {
 813                int image_noffset;
 814                int index, max_index;
 815
 816                max_index = fdt_stringlist_count(fit, conf_noffset, iname);
 817
 818                for (index = 0; index < max_index; index++) {
 819                        image_noffset = fit_conf_get_prop_node_index(fit, conf_noffset,
 820                                                                     iname, index);
 821
 822                        if (image_noffset < 0) {
 823                                printf("Failed to find image '%s' in  configuration '%s/%s'\n",
 824                                       iname, conf_name, sig_name);
 825                                if (allow_missing)
 826                                        continue;
 827
 828                                return -ENOENT;
 829                        }
 830
 831                        ret = fit_config_add_hash(fit, conf_name,
 832                                                  sig_name, node_inc,
 833                                                  iname, image_noffset);
 834                        if (ret < 0)
 835                                return ret;
 836
 837                        image_count++;
 838                }
 839        }
 840
 841        if (!image_count) {
 842                printf("Failed to find any images for configuration '%s/%s'\n",
 843                       conf_name, sig_name);
 844                return -ENOMSG;
 845        }
 846
 847        return 0;
 848
 849err_mem:
 850        printf("Out of memory processing configuration '%s/%s'\n", conf_name,
 851               sig_name);
 852        return -ENOMEM;
 853}
 854
 855static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
 856                struct image_region **regionp, int *region_countp,
 857                char **region_propp, int *region_proplen)
 858{
 859        char * const exc_prop[] = {"data"};
 860        struct strlist node_inc;
 861        struct image_region *region;
 862        struct fdt_region fdt_regions[100];
 863        const char *conf_name, *sig_name;
 864        char path[200];
 865        int count, i;
 866        char *region_prop;
 867        int ret, len;
 868
 869        conf_name = fit_get_name(fit, conf_noffset, NULL);
 870        sig_name = fit_get_name(fit, noffset, NULL);
 871        debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
 872
 873        /* Get a list of nodes we want to hash */
 874        ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc);
 875        if (ret)
 876                return ret;
 877
 878        /* Get a list of regions to hash */
 879        count = fdt_find_regions(fit, node_inc.strings, node_inc.count,
 880                        exc_prop, ARRAY_SIZE(exc_prop),
 881                        fdt_regions, ARRAY_SIZE(fdt_regions),
 882                        path, sizeof(path), 1);
 883        if (count < 0) {
 884                printf("Failed to hash configuration '%s/%s': %s\n", conf_name,
 885                       sig_name, fdt_strerror(ret));
 886                return -EIO;
 887        }
 888        if (count == 0) {
 889                printf("No data to hash for configuration '%s/%s': %s\n",
 890                       conf_name, sig_name, fdt_strerror(ret));
 891                return -EINVAL;
 892        }
 893
 894        /* Build our list of data blocks */
 895        region = fit_region_make_list(fit, fdt_regions, count, NULL);
 896        if (!region) {
 897                printf("Out of memory hashing configuration '%s/%s'\n",
 898                       conf_name, sig_name);
 899                return -ENOMEM;
 900        }
 901
 902        /* Create a list of all hashed properties */
 903        debug("Hash nodes:\n");
 904        for (i = len = 0; i < node_inc.count; i++) {
 905                debug("   %s\n", node_inc.strings[i]);
 906                len += strlen(node_inc.strings[i]) + 1;
 907        }
 908        region_prop = malloc(len);
 909        if (!region_prop) {
 910                printf("Out of memory setting up regions for configuration '%s/%s'\n",
 911                       conf_name, sig_name);
 912                return -ENOMEM;
 913        }
 914        for (i = len = 0; i < node_inc.count;
 915             len += strlen(node_inc.strings[i]) + 1, i++)
 916                strcpy(region_prop + len, node_inc.strings[i]);
 917        strlist_free(&node_inc);
 918
 919        *region_countp = count;
 920        *regionp = region;
 921        *region_propp = region_prop;
 922        *region_proplen = len;
 923
 924        return 0;
 925}
 926
 927static int fit_config_process_sig(const char *keydir, const char *keyfile,
 928                void *keydest,  void *fit, const char *conf_name,
 929                int conf_noffset, int noffset, const char *comment,
 930                int require_keys, const char *engine_id, const char *cmdname)
 931{
 932        struct image_sign_info info;
 933        const char *node_name;
 934        struct image_region *region;
 935        char *region_prop;
 936        int region_proplen;
 937        int region_count;
 938        uint8_t *value;
 939        uint value_len;
 940        int ret;
 941
 942        node_name = fit_get_name(fit, noffset, NULL);
 943        if (fit_config_get_data(fit, conf_noffset, noffset, &region,
 944                                &region_count, &region_prop, &region_proplen))
 945                return -1;
 946
 947        if (fit_image_setup_sig(&info, keydir, keyfile, fit, conf_name, noffset,
 948                                require_keys ? "conf" : NULL, engine_id))
 949                return -1;
 950
 951        ret = info.crypto->sign(&info, region, region_count, &value,
 952                                &value_len);
 953        free(region);
 954        if (ret) {
 955                printf("Failed to sign '%s' signature node in '%s' conf node\n",
 956                       node_name, conf_name);
 957
 958                /* We allow keys to be missing */
 959                if (ret == -ENOENT)
 960                        return 0;
 961                return -1;
 962        }
 963
 964        ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
 965                                region_prop, region_proplen, cmdname);
 966        if (ret) {
 967                if (ret == -FDT_ERR_NOSPACE)
 968                        return -ENOSPC;
 969                printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
 970                       node_name, conf_name, fdt_strerror(ret));
 971                return -1;
 972        }
 973        free(value);
 974        free(region_prop);
 975
 976        /* Get keyname again, as FDT has changed and invalidated our pointer */
 977        info.keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
 978
 979        /* Write the public key into the supplied FDT file */
 980        if (keydest) {
 981                ret = info.crypto->add_verify_data(&info, keydest);
 982                if (ret) {
 983                        printf("Failed to add verification data for '%s' signature node in '%s' configuration node\n",
 984                               node_name, conf_name);
 985                }
 986                return ret;
 987        }
 988
 989        return 0;
 990}
 991
 992static int fit_config_add_verification_data(const char *keydir,
 993                const char *keyfile, void *keydest, void *fit, int conf_noffset,
 994                const char *comment, int require_keys, const char *engine_id,
 995                const char *cmdname)
 996{
 997        const char *conf_name;
 998        int noffset;
 999
1000        conf_name = fit_get_name(fit, conf_noffset, NULL);
1001
1002        /* Process all hash subnodes of the configuration node */
1003        for (noffset = fdt_first_subnode(fit, conf_noffset);
1004             noffset >= 0;
1005             noffset = fdt_next_subnode(fit, noffset)) {
1006                const char *node_name;
1007                int ret = 0;
1008
1009                node_name = fit_get_name(fit, noffset, NULL);
1010                if (!strncmp(node_name, FIT_SIG_NODENAME,
1011                             strlen(FIT_SIG_NODENAME))) {
1012                        ret = fit_config_process_sig(keydir, keyfile, keydest,
1013                                fit, conf_name, conf_noffset, noffset, comment,
1014                                require_keys, engine_id, cmdname);
1015                }
1016                if (ret)
1017                        return ret;
1018        }
1019
1020        return 0;
1021}
1022
1023int fit_cipher_data(const char *keydir, void *keydest, void *fit,
1024                    const char *comment, int require_keys,
1025                    const char *engine_id, const char *cmdname)
1026{
1027        int images_noffset;
1028        int noffset;
1029        int ret;
1030
1031        /* Find images parent node offset */
1032        images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1033        if (images_noffset < 0) {
1034                printf("Can't find images parent node '%s' (%s)\n",
1035                       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
1036                return images_noffset;
1037        }
1038
1039        /* Process its subnodes, print out component images details */
1040        for (noffset = fdt_first_subnode(fit, images_noffset);
1041             noffset >= 0;
1042             noffset = fdt_next_subnode(fit, noffset)) {
1043                /*
1044                 * Direct child node of the images parent node,
1045                 * i.e. component image node.
1046                 */
1047                ret = fit_image_cipher_data(keydir, keydest,
1048                                            fit, noffset, comment,
1049                                            require_keys, engine_id,
1050                                            cmdname);
1051                if (ret)
1052                        return ret;
1053        }
1054
1055        return 0;
1056}
1057
1058int fit_add_verification_data(const char *keydir, const char *keyfile,
1059                              void *keydest, void *fit, const char *comment,
1060                              int require_keys, const char *engine_id,
1061                              const char *cmdname)
1062{
1063        int images_noffset, confs_noffset;
1064        int noffset;
1065        int ret;
1066
1067        /* Find images parent node offset */
1068        images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1069        if (images_noffset < 0) {
1070                printf("Can't find images parent node '%s' (%s)\n",
1071                       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
1072                return images_noffset;
1073        }
1074
1075        /* Process its subnodes, print out component images details */
1076        for (noffset = fdt_first_subnode(fit, images_noffset);
1077             noffset >= 0;
1078             noffset = fdt_next_subnode(fit, noffset)) {
1079                /*
1080                 * Direct child node of the images parent node,
1081                 * i.e. component image node.
1082                 */
1083                ret = fit_image_add_verification_data(keydir, keyfile, keydest,
1084                                fit, noffset, comment, require_keys, engine_id,
1085                                cmdname);
1086                if (ret)
1087                        return ret;
1088        }
1089
1090        /* If there are no keys, we can't sign configurations */
1091        if (!IMAGE_ENABLE_SIGN || !(keydir || keyfile))
1092                return 0;
1093
1094        /* Find configurations parent node offset */
1095        confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1096        if (confs_noffset < 0) {
1097                printf("Can't find images parent node '%s' (%s)\n",
1098                       FIT_CONFS_PATH, fdt_strerror(confs_noffset));
1099                return -ENOENT;
1100        }
1101
1102        /* Process its subnodes, print out component images details */
1103        for (noffset = fdt_first_subnode(fit, confs_noffset);
1104             noffset >= 0;
1105             noffset = fdt_next_subnode(fit, noffset)) {
1106                ret = fit_config_add_verification_data(keydir, keyfile, keydest,
1107                                                       fit, noffset, comment,
1108                                                       require_keys,
1109                                                       engine_id, cmdname);
1110                if (ret)
1111                        return ret;
1112        }
1113
1114        return 0;
1115}
1116
1117#ifdef CONFIG_FIT_SIGNATURE
1118int fit_check_sign(const void *fit, const void *key,
1119                   const char *fit_uname_config)
1120{
1121        int cfg_noffset;
1122        int ret;
1123
1124        cfg_noffset = fit_conf_get_node(fit, fit_uname_config);
1125        if (!cfg_noffset)
1126                return -1;
1127
1128        printf("Verifying Hash Integrity for node '%s'... ",
1129               fdt_get_name(fit, cfg_noffset, NULL));
1130        ret = fit_config_verify(fit, cfg_noffset);
1131        if (ret)
1132                return ret;
1133        printf("Verified OK, loading images\n");
1134        ret = bootm_host_load_images(fit, cfg_noffset);
1135
1136        return ret;
1137}
1138#endif
1139