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