uboot/common/image-sig.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013, Google Inc.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#ifdef USE_HOSTCC
   8#include "mkimage.h"
   9#include <time.h>
  10#else
  11#include <common.h>
  12#include <malloc.h>
  13DECLARE_GLOBAL_DATA_PTR;
  14#endif /* !USE_HOSTCC*/
  15#include <image.h>
  16#include <u-boot/rsa.h>
  17#include <u-boot/rsa-checksum.h>
  18
  19#define IMAGE_MAX_HASHED_NODES          100
  20
  21#ifdef USE_HOSTCC
  22void *host_blob;
  23void image_set_host_blob(void *blob)
  24{
  25        host_blob = blob;
  26}
  27void *image_get_host_blob(void)
  28{
  29        return host_blob;
  30}
  31#endif
  32
  33struct checksum_algo checksum_algos[] = {
  34        {
  35                "sha1",
  36                SHA1_SUM_LEN,
  37                RSA2048_BYTES,
  38#if IMAGE_ENABLE_SIGN
  39                EVP_sha1,
  40#endif
  41                hash_calculate,
  42                padding_sha1_rsa2048,
  43        },
  44        {
  45                "sha256",
  46                SHA256_SUM_LEN,
  47                RSA2048_BYTES,
  48#if IMAGE_ENABLE_SIGN
  49                EVP_sha256,
  50#endif
  51                hash_calculate,
  52                padding_sha256_rsa2048,
  53        },
  54        {
  55                "sha256",
  56                SHA256_SUM_LEN,
  57                RSA4096_BYTES,
  58#if IMAGE_ENABLE_SIGN
  59                EVP_sha256,
  60#endif
  61                hash_calculate,
  62                padding_sha256_rsa4096,
  63        }
  64
  65};
  66
  67struct image_sig_algo image_sig_algos[] = {
  68        {
  69                "sha1,rsa2048",
  70                rsa_sign,
  71                rsa_add_verify_data,
  72                rsa_verify,
  73                &checksum_algos[0],
  74        },
  75        {
  76                "sha256,rsa2048",
  77                rsa_sign,
  78                rsa_add_verify_data,
  79                rsa_verify,
  80                &checksum_algos[1],
  81        },
  82        {
  83                "sha256,rsa4096",
  84                rsa_sign,
  85                rsa_add_verify_data,
  86                rsa_verify,
  87                &checksum_algos[2],
  88        }
  89
  90};
  91
  92struct image_sig_algo *image_get_sig_algo(const char *name)
  93{
  94        int i;
  95
  96        for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) {
  97                if (!strcmp(image_sig_algos[i].name, name))
  98                        return &image_sig_algos[i];
  99        }
 100
 101        return NULL;
 102}
 103
 104/**
 105 * fit_region_make_list() - Make a list of image regions
 106 *
 107 * Given a list of fdt_regions, create a list of image_regions. This is a
 108 * simple conversion routine since the FDT and image code use different
 109 * structures.
 110 *
 111 * @fit: FIT image
 112 * @fdt_regions: Pointer to FDT regions
 113 * @count: Number of FDT regions
 114 * @region: Pointer to image regions, which must hold @count records. If
 115 * region is NULL, then (except for an SPL build) the array will be
 116 * allocated.
 117 * @return: Pointer to image regions
 118 */
 119struct image_region *fit_region_make_list(const void *fit,
 120                struct fdt_region *fdt_regions, int count,
 121                struct image_region *region)
 122{
 123        int i;
 124
 125        debug("Hash regions:\n");
 126        debug("%10s %10s\n", "Offset", "Size");
 127
 128        /*
 129         * Use malloc() except in SPL (to save code size). In SPL the caller
 130         * must allocate the array.
 131         */
 132#ifndef CONFIG_SPL_BUILD
 133        if (!region)
 134                region = calloc(sizeof(*region), count);
 135#endif
 136        if (!region)
 137                return NULL;
 138        for (i = 0; i < count; i++) {
 139                debug("%10x %10x\n", fdt_regions[i].offset,
 140                      fdt_regions[i].size);
 141                region[i].data = fit + fdt_regions[i].offset;
 142                region[i].size = fdt_regions[i].size;
 143        }
 144
 145        return region;
 146}
 147
 148static int fit_image_setup_verify(struct image_sign_info *info,
 149                const void *fit, int noffset, int required_keynode,
 150                char **err_msgp)
 151{
 152        char *algo_name;
 153
 154        if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
 155                *err_msgp = "Can't get hash algo property";
 156                return -1;
 157        }
 158        memset(info, '\0', sizeof(*info));
 159        info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
 160        info->fit = (void *)fit;
 161        info->node_offset = noffset;
 162        info->algo = image_get_sig_algo(algo_name);
 163        info->fdt_blob = gd_fdt_blob();
 164        info->required_keynode = required_keynode;
 165        printf("%s:%s", algo_name, info->keyname);
 166
 167        if (!info->algo) {
 168                *err_msgp = "Unknown signature algorithm";
 169                return -1;
 170        }
 171
 172        return 0;
 173}
 174
 175int fit_image_check_sig(const void *fit, int noffset, const void *data,
 176                size_t size, int required_keynode, char **err_msgp)
 177{
 178        struct image_sign_info info;
 179        struct image_region region;
 180        uint8_t *fit_value;
 181        int fit_value_len;
 182
 183        *err_msgp = NULL;
 184        if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
 185                                   err_msgp))
 186                return -1;
 187
 188        if (fit_image_hash_get_value(fit, noffset, &fit_value,
 189                                     &fit_value_len)) {
 190                *err_msgp = "Can't get hash value property";
 191                return -1;
 192        }
 193
 194        region.data = data;
 195        region.size = size;
 196
 197        if (info.algo->verify(&info, &region, 1, fit_value, fit_value_len)) {
 198                *err_msgp = "Verification failed";
 199                return -1;
 200        }
 201
 202        return 0;
 203}
 204
 205static int fit_image_verify_sig(const void *fit, int image_noffset,
 206                const char *data, size_t size, const void *sig_blob,
 207                int sig_offset)
 208{
 209        int noffset;
 210        char *err_msg = "";
 211        int verified = 0;
 212        int ret;
 213
 214        /* Process all hash subnodes of the component image node */
 215        fdt_for_each_subnode(fit, noffset, image_noffset) {
 216                const char *name = fit_get_name(fit, noffset, NULL);
 217
 218                if (!strncmp(name, FIT_SIG_NODENAME,
 219                             strlen(FIT_SIG_NODENAME))) {
 220                        ret = fit_image_check_sig(fit, noffset, data,
 221                                                        size, -1, &err_msg);
 222                        if (ret) {
 223                                puts("- ");
 224                        } else {
 225                                puts("+ ");
 226                                verified = 1;
 227                                break;
 228                        }
 229                }
 230        }
 231
 232        if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
 233                err_msg = "Corrupted or truncated tree";
 234                goto error;
 235        }
 236
 237        return verified ? 0 : -EPERM;
 238
 239error:
 240        printf(" error!\n%s for '%s' hash node in '%s' image node\n",
 241               err_msg, fit_get_name(fit, noffset, NULL),
 242               fit_get_name(fit, image_noffset, NULL));
 243        return -1;
 244}
 245
 246int fit_image_verify_required_sigs(const void *fit, int image_noffset,
 247                const char *data, size_t size, const void *sig_blob,
 248                int *no_sigsp)
 249{
 250        int verify_count = 0;
 251        int noffset;
 252        int sig_node;
 253
 254        /* Work out what we need to verify */
 255        *no_sigsp = 1;
 256        sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
 257        if (sig_node < 0) {
 258                debug("%s: No signature node found: %s\n", __func__,
 259                      fdt_strerror(sig_node));
 260                return 0;
 261        }
 262
 263        fdt_for_each_subnode(sig_blob, noffset, sig_node) {
 264                const char *required;
 265                int ret;
 266
 267                required = fdt_getprop(sig_blob, noffset, "required", NULL);
 268                if (!required || strcmp(required, "image"))
 269                        continue;
 270                ret = fit_image_verify_sig(fit, image_noffset, data, size,
 271                                        sig_blob, noffset);
 272                if (ret) {
 273                        printf("Failed to verify required signature '%s'\n",
 274                               fit_get_name(sig_blob, noffset, NULL));
 275                        return ret;
 276                }
 277                verify_count++;
 278        }
 279
 280        if (verify_count)
 281                *no_sigsp = 0;
 282
 283        return 0;
 284}
 285
 286int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
 287                         char **err_msgp)
 288{
 289        char * const exc_prop[] = {"data"};
 290        const char *prop, *end, *name;
 291        struct image_sign_info info;
 292        const uint32_t *strings;
 293        uint8_t *fit_value;
 294        int fit_value_len;
 295        int max_regions;
 296        int i, prop_len;
 297        char path[200];
 298        int count;
 299
 300        debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
 301              fit_get_name(fit, noffset, NULL),
 302              fit_get_name(gd_fdt_blob(), required_keynode, NULL));
 303        *err_msgp = NULL;
 304        if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
 305                                   err_msgp))
 306                return -1;
 307
 308        if (fit_image_hash_get_value(fit, noffset, &fit_value,
 309                                     &fit_value_len)) {
 310                *err_msgp = "Can't get hash value property";
 311                return -1;
 312        }
 313
 314        /* Count the number of strings in the property */
 315        prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
 316        end = prop ? prop + prop_len : prop;
 317        for (name = prop, count = 0; name < end; name++)
 318                if (!*name)
 319                        count++;
 320        if (!count) {
 321                *err_msgp = "Can't get hashed-nodes property";
 322                return -1;
 323        }
 324
 325        /* Add a sanity check here since we are using the stack */
 326        if (count > IMAGE_MAX_HASHED_NODES) {
 327                *err_msgp = "Number of hashed nodes exceeds maximum";
 328                return -1;
 329        }
 330
 331        /* Create a list of node names from those strings */
 332        char *node_inc[count];
 333
 334        debug("Hash nodes (%d):\n", count);
 335        for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
 336                debug("   '%s'\n", name);
 337                node_inc[i] = (char *)name;
 338        }
 339
 340        /*
 341         * Each node can generate one region for each sub-node. Allow for
 342         * 7 sub-nodes (hash@1, signature@1, etc.) and some extra.
 343         */
 344        max_regions = 20 + count * 7;
 345        struct fdt_region fdt_regions[max_regions];
 346
 347        /* Get a list of regions to hash */
 348        count = fdt_find_regions(fit, node_inc, count,
 349                        exc_prop, ARRAY_SIZE(exc_prop),
 350                        fdt_regions, max_regions - 1,
 351                        path, sizeof(path), 0);
 352        if (count < 0) {
 353                *err_msgp = "Failed to hash configuration";
 354                return -1;
 355        }
 356        if (count == 0) {
 357                *err_msgp = "No data to hash";
 358                return -1;
 359        }
 360        if (count >= max_regions - 1) {
 361                *err_msgp = "Too many hash regions";
 362                return -1;
 363        }
 364
 365        /* Add the strings */
 366        strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
 367        if (strings) {
 368                fdt_regions[count].offset = fdt_off_dt_strings(fit) +
 369                                fdt32_to_cpu(strings[0]);
 370                fdt_regions[count].size = fdt32_to_cpu(strings[1]);
 371                count++;
 372        }
 373
 374        /* Allocate the region list on the stack */
 375        struct image_region region[count];
 376
 377        fit_region_make_list(fit, fdt_regions, count, region);
 378        if (info.algo->verify(&info, region, count, fit_value,
 379                              fit_value_len)) {
 380                *err_msgp = "Verification failed";
 381                return -1;
 382        }
 383
 384        return 0;
 385}
 386
 387static int fit_config_verify_sig(const void *fit, int conf_noffset,
 388                const void *sig_blob, int sig_offset)
 389{
 390        int noffset;
 391        char *err_msg = "";
 392        int verified = 0;
 393        int ret;
 394
 395        /* Process all hash subnodes of the component conf node */
 396        fdt_for_each_subnode(fit, noffset, conf_noffset) {
 397                const char *name = fit_get_name(fit, noffset, NULL);
 398
 399                if (!strncmp(name, FIT_SIG_NODENAME,
 400                             strlen(FIT_SIG_NODENAME))) {
 401                        ret = fit_config_check_sig(fit, noffset, sig_offset,
 402                                                   &err_msg);
 403                        if (ret) {
 404                                puts("- ");
 405                        } else {
 406                                puts("+ ");
 407                                verified = 1;
 408                                break;
 409                        }
 410                }
 411        }
 412
 413        if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
 414                err_msg = "Corrupted or truncated tree";
 415                goto error;
 416        }
 417
 418        return verified ? 0 : -EPERM;
 419
 420error:
 421        printf(" error!\n%s for '%s' hash node in '%s' config node\n",
 422               err_msg, fit_get_name(fit, noffset, NULL),
 423               fit_get_name(fit, conf_noffset, NULL));
 424        return -1;
 425}
 426
 427int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
 428                const void *sig_blob)
 429{
 430        int noffset;
 431        int sig_node;
 432
 433        /* Work out what we need to verify */
 434        sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
 435        if (sig_node < 0) {
 436                debug("%s: No signature node found: %s\n", __func__,
 437                      fdt_strerror(sig_node));
 438                return 0;
 439        }
 440
 441        fdt_for_each_subnode(sig_blob, noffset, sig_node) {
 442                const char *required;
 443                int ret;
 444
 445                required = fdt_getprop(sig_blob, noffset, "required", NULL);
 446                if (!required || strcmp(required, "conf"))
 447                        continue;
 448                ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
 449                                            noffset);
 450                if (ret) {
 451                        printf("Failed to verify required signature '%s'\n",
 452                               fit_get_name(sig_blob, noffset, NULL));
 453                        return ret;
 454                }
 455        }
 456
 457        return 0;
 458}
 459
 460int fit_config_verify(const void *fit, int conf_noffset)
 461{
 462        return fit_config_verify_required_sigs(fit, conf_noffset,
 463                                               gd_fdt_blob());
 464}
 465