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