uboot/common/hash.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2012 The Chromium OS Authors.
   4 *
   5 * (C) Copyright 2011
   6 * Joe Hershberger, National Instruments, joe.hershberger@ni.com
   7 *
   8 * (C) Copyright 2000
   9 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  10 */
  11
  12#ifndef USE_HOSTCC
  13#include <common.h>
  14#include <command.h>
  15#include <env.h>
  16#include <log.h>
  17#include <malloc.h>
  18#include <mapmem.h>
  19#include <hw_sha.h>
  20#include <asm/cache.h>
  21#include <asm/global_data.h>
  22#include <asm/io.h>
  23#include <linux/errno.h>
  24#include <u-boot/crc.h>
  25#else
  26#include "mkimage.h"
  27#include <linux/compiler_attributes.h>
  28#include <time.h>
  29#include <linux/kconfig.h>
  30#endif /* !USE_HOSTCC*/
  31
  32#include <hash.h>
  33#include <image.h>
  34#include <u-boot/crc.h>
  35#include <u-boot/sha1.h>
  36#include <u-boot/sha256.h>
  37#include <u-boot/sha512.h>
  38#include <u-boot/md5.h>
  39
  40#if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC)
  41DECLARE_GLOBAL_DATA_PTR;
  42#endif
  43
  44static void reloc_update(void);
  45
  46static int __maybe_unused hash_init_sha1(struct hash_algo *algo, void **ctxp)
  47{
  48        sha1_context *ctx = malloc(sizeof(sha1_context));
  49        sha1_starts(ctx);
  50        *ctxp = ctx;
  51        return 0;
  52}
  53
  54static int __maybe_unused hash_update_sha1(struct hash_algo *algo, void *ctx,
  55                                           const void *buf, unsigned int size,
  56                                           int is_last)
  57{
  58        sha1_update((sha1_context *)ctx, buf, size);
  59        return 0;
  60}
  61
  62static int __maybe_unused hash_finish_sha1(struct hash_algo *algo, void *ctx,
  63                                           void *dest_buf, int size)
  64{
  65        if (size < algo->digest_size)
  66                return -1;
  67
  68        sha1_finish((sha1_context *)ctx, dest_buf);
  69        free(ctx);
  70        return 0;
  71}
  72
  73static int __maybe_unused hash_init_sha256(struct hash_algo *algo, void **ctxp)
  74{
  75        sha256_context *ctx = malloc(sizeof(sha256_context));
  76        sha256_starts(ctx);
  77        *ctxp = ctx;
  78        return 0;
  79}
  80
  81static int __maybe_unused hash_update_sha256(struct hash_algo *algo, void *ctx,
  82                                             const void *buf, uint size,
  83                                             int is_last)
  84{
  85        sha256_update((sha256_context *)ctx, buf, size);
  86        return 0;
  87}
  88
  89static int __maybe_unused hash_finish_sha256(struct hash_algo *algo, void *ctx,
  90                                             void *dest_buf, int size)
  91{
  92        if (size < algo->digest_size)
  93                return -1;
  94
  95        sha256_finish((sha256_context *)ctx, dest_buf);
  96        free(ctx);
  97        return 0;
  98}
  99
 100static int __maybe_unused hash_init_sha384(struct hash_algo *algo, void **ctxp)
 101{
 102        sha512_context *ctx = malloc(sizeof(sha512_context));
 103        sha384_starts(ctx);
 104        *ctxp = ctx;
 105        return 0;
 106}
 107
 108static int __maybe_unused hash_update_sha384(struct hash_algo *algo, void *ctx,
 109                                             const void *buf, uint size,
 110                                             int is_last)
 111{
 112        sha384_update((sha512_context *)ctx, buf, size);
 113        return 0;
 114}
 115
 116static int __maybe_unused hash_finish_sha384(struct hash_algo *algo, void *ctx,
 117                                             void *dest_buf, int size)
 118{
 119        if (size < algo->digest_size)
 120                return -1;
 121
 122        sha384_finish((sha512_context *)ctx, dest_buf);
 123        free(ctx);
 124        return 0;
 125}
 126
 127static int __maybe_unused hash_init_sha512(struct hash_algo *algo, void **ctxp)
 128{
 129        sha512_context *ctx = malloc(sizeof(sha512_context));
 130        sha512_starts(ctx);
 131        *ctxp = ctx;
 132        return 0;
 133}
 134
 135static int __maybe_unused hash_update_sha512(struct hash_algo *algo, void *ctx,
 136                                             const void *buf, uint size,
 137                                             int is_last)
 138{
 139        sha512_update((sha512_context *)ctx, buf, size);
 140        return 0;
 141}
 142
 143static int __maybe_unused hash_finish_sha512(struct hash_algo *algo, void *ctx,
 144                                             void *dest_buf, int size)
 145{
 146        if (size < algo->digest_size)
 147                return -1;
 148
 149        sha512_finish((sha512_context *)ctx, dest_buf);
 150        free(ctx);
 151        return 0;
 152}
 153
 154static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp)
 155{
 156        uint16_t *ctx = malloc(sizeof(uint16_t));
 157        *ctx = 0;
 158        *ctxp = ctx;
 159        return 0;
 160}
 161
 162static int hash_update_crc16_ccitt(struct hash_algo *algo, void *ctx,
 163                                   const void *buf, unsigned int size,
 164                                   int is_last)
 165{
 166        *((uint16_t *)ctx) = crc16_ccitt(*((uint16_t *)ctx), buf, size);
 167        return 0;
 168}
 169
 170static int hash_finish_crc16_ccitt(struct hash_algo *algo, void *ctx,
 171                                   void *dest_buf, int size)
 172{
 173        if (size < algo->digest_size)
 174                return -1;
 175
 176        *((uint16_t *)dest_buf) = *((uint16_t *)ctx);
 177        free(ctx);
 178        return 0;
 179}
 180
 181static int __maybe_unused hash_init_crc32(struct hash_algo *algo, void **ctxp)
 182{
 183        uint32_t *ctx = malloc(sizeof(uint32_t));
 184        *ctx = 0;
 185        *ctxp = ctx;
 186        return 0;
 187}
 188
 189static int __maybe_unused hash_update_crc32(struct hash_algo *algo, void *ctx,
 190                                            const void *buf, unsigned int size,
 191                                            int is_last)
 192{
 193        *((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size);
 194        return 0;
 195}
 196
 197static int __maybe_unused hash_finish_crc32(struct hash_algo *algo, void *ctx,
 198                                            void *dest_buf, int size)
 199{
 200        if (size < algo->digest_size)
 201                return -1;
 202
 203        *((uint32_t *)dest_buf) = *((uint32_t *)ctx);
 204        free(ctx);
 205        return 0;
 206}
 207
 208/*
 209 * These are the hash algorithms we support.  If we have hardware acceleration
 210 * is enable we will use that, otherwise a software version of the algorithm.
 211 * Note that algorithm names must be in lower case.
 212 */
 213static struct hash_algo hash_algo[] = {
 214#if CONFIG_IS_ENABLED(MD5)
 215        {
 216                .name           = "md5",
 217                .digest_size    = MD5_SUM_LEN,
 218                .chunk_size     = CHUNKSZ_MD5,
 219                .hash_func_ws   = md5_wd,
 220        },
 221#endif
 222#if CONFIG_IS_ENABLED(SHA1)
 223        {
 224                .name           = "sha1",
 225                .digest_size    = SHA1_SUM_LEN,
 226                .chunk_size     = CHUNKSZ_SHA1,
 227#if CONFIG_IS_ENABLED(SHA_HW_ACCEL)
 228                .hash_func_ws   = hw_sha1,
 229#else
 230                .hash_func_ws   = sha1_csum_wd,
 231#endif
 232#if CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL)
 233                .hash_init      = hw_sha_init,
 234                .hash_update    = hw_sha_update,
 235                .hash_finish    = hw_sha_finish,
 236#else
 237                .hash_init      = hash_init_sha1,
 238                .hash_update    = hash_update_sha1,
 239                .hash_finish    = hash_finish_sha1,
 240#endif
 241        },
 242#endif
 243#if CONFIG_IS_ENABLED(SHA256)
 244        {
 245                .name           = "sha256",
 246                .digest_size    = SHA256_SUM_LEN,
 247                .chunk_size     = CHUNKSZ_SHA256,
 248#if CONFIG_IS_ENABLED(SHA_HW_ACCEL)
 249                .hash_func_ws   = hw_sha256,
 250#else
 251                .hash_func_ws   = sha256_csum_wd,
 252#endif
 253#if CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL)
 254                .hash_init      = hw_sha_init,
 255                .hash_update    = hw_sha_update,
 256                .hash_finish    = hw_sha_finish,
 257#else
 258                .hash_init      = hash_init_sha256,
 259                .hash_update    = hash_update_sha256,
 260                .hash_finish    = hash_finish_sha256,
 261#endif
 262        },
 263#endif
 264#if CONFIG_IS_ENABLED(SHA384)
 265        {
 266                .name           = "sha384",
 267                .digest_size    = SHA384_SUM_LEN,
 268                .chunk_size     = CHUNKSZ_SHA384,
 269#if CONFIG_IS_ENABLED(SHA512_HW_ACCEL)
 270                .hash_func_ws   = hw_sha384,
 271#else
 272                .hash_func_ws   = sha384_csum_wd,
 273#endif
 274#if CONFIG_IS_ENABLED(SHA512_HW_ACCEL) && CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL)
 275                .hash_init      = hw_sha_init,
 276                .hash_update    = hw_sha_update,
 277                .hash_finish    = hw_sha_finish,
 278#else
 279                .hash_init      = hash_init_sha384,
 280                .hash_update    = hash_update_sha384,
 281                .hash_finish    = hash_finish_sha384,
 282#endif
 283        },
 284#endif
 285#if CONFIG_IS_ENABLED(SHA512)
 286        {
 287                .name           = "sha512",
 288                .digest_size    = SHA512_SUM_LEN,
 289                .chunk_size     = CHUNKSZ_SHA512,
 290#if CONFIG_IS_ENABLED(SHA512_HW_ACCEL)
 291                .hash_func_ws   = hw_sha512,
 292#else
 293                .hash_func_ws   = sha512_csum_wd,
 294#endif
 295#if CONFIG_IS_ENABLED(SHA512_HW_ACCEL) && CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL)
 296                .hash_init      = hw_sha_init,
 297                .hash_update    = hw_sha_update,
 298                .hash_finish    = hw_sha_finish,
 299#else
 300                .hash_init      = hash_init_sha512,
 301                .hash_update    = hash_update_sha512,
 302                .hash_finish    = hash_finish_sha512,
 303#endif
 304        },
 305#endif
 306        {
 307                .name           = "crc16-ccitt",
 308                .digest_size    = 2,
 309                .chunk_size     = CHUNKSZ,
 310                .hash_func_ws   = crc16_ccitt_wd_buf,
 311                .hash_init      = hash_init_crc16_ccitt,
 312                .hash_update    = hash_update_crc16_ccitt,
 313                .hash_finish    = hash_finish_crc16_ccitt,
 314        },
 315#if CONFIG_IS_ENABLED(CRC32)
 316        {
 317                .name           = "crc32",
 318                .digest_size    = 4,
 319                .chunk_size     = CHUNKSZ_CRC32,
 320                .hash_func_ws   = crc32_wd_buf,
 321                .hash_init      = hash_init_crc32,
 322                .hash_update    = hash_update_crc32,
 323                .hash_finish    = hash_finish_crc32,
 324        },
 325#endif
 326};
 327
 328/* Try to minimize code size for boards that don't want much hashing */
 329#if CONFIG_IS_ENABLED(SHA256) || CONFIG_IS_ENABLED(CMD_SHA1SUM) || \
 330        CONFIG_IS_ENABLED(CRC32_VERIFY) || CONFIG_IS_ENABLED(CMD_HASH) || \
 331        CONFIG_IS_ENABLED(SHA384) || CONFIG_IS_ENABLED(SHA512)
 332#define multi_hash()    1
 333#else
 334#define multi_hash()    0
 335#endif
 336
 337static void reloc_update(void)
 338{
 339#if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC)
 340        int i;
 341        static bool done;
 342
 343        if (!done) {
 344                done = true;
 345                for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
 346                        hash_algo[i].name += gd->reloc_off;
 347                        hash_algo[i].hash_func_ws += gd->reloc_off;
 348                        hash_algo[i].hash_init += gd->reloc_off;
 349                        hash_algo[i].hash_update += gd->reloc_off;
 350                        hash_algo[i].hash_finish += gd->reloc_off;
 351                }
 352        }
 353#endif
 354}
 355
 356int hash_lookup_algo(const char *algo_name, struct hash_algo **algop)
 357{
 358        int i;
 359
 360        reloc_update();
 361
 362        for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
 363                if (!strcmp(algo_name, hash_algo[i].name)) {
 364                        *algop = &hash_algo[i];
 365                        return 0;
 366                }
 367        }
 368
 369        debug("Unknown hash algorithm '%s'\n", algo_name);
 370        return -EPROTONOSUPPORT;
 371}
 372
 373int hash_progressive_lookup_algo(const char *algo_name,
 374                                 struct hash_algo **algop)
 375{
 376        int i;
 377
 378        reloc_update();
 379
 380        for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
 381                if (!strcmp(algo_name, hash_algo[i].name)) {
 382                        if (hash_algo[i].hash_init) {
 383                                *algop = &hash_algo[i];
 384                                return 0;
 385                        }
 386                }
 387        }
 388
 389        debug("Unknown hash algorithm '%s'\n", algo_name);
 390        return -EPROTONOSUPPORT;
 391}
 392
 393#ifndef USE_HOSTCC
 394int hash_parse_string(const char *algo_name, const char *str, uint8_t *result)
 395{
 396        struct hash_algo *algo;
 397        int ret;
 398        int i;
 399
 400        ret = hash_lookup_algo(algo_name, &algo);
 401        if (ret)
 402                return ret;
 403
 404        for (i = 0; i < algo->digest_size; i++) {
 405                char chr[3];
 406
 407                strlcpy(chr, &str[i * 2], 3);
 408                result[i] = hextoul(chr, NULL);
 409        }
 410
 411        return 0;
 412}
 413
 414int hash_block(const char *algo_name, const void *data, unsigned int len,
 415               uint8_t *output, int *output_size)
 416{
 417        struct hash_algo *algo;
 418        int ret;
 419
 420        ret = hash_lookup_algo(algo_name, &algo);
 421        if (ret)
 422                return ret;
 423
 424        if (output_size && *output_size < algo->digest_size) {
 425                debug("Output buffer size %d too small (need %d bytes)",
 426                      *output_size, algo->digest_size);
 427                return -ENOSPC;
 428        }
 429        if (output_size)
 430                *output_size = algo->digest_size;
 431        algo->hash_func_ws(data, len, output, algo->chunk_size);
 432
 433        return 0;
 434}
 435
 436#if !defined(CONFIG_SPL_BUILD) && (defined(CONFIG_CMD_HASH) || \
 437        defined(CONFIG_CMD_SHA1SUM) || defined(CONFIG_CMD_CRC32))
 438/**
 439 * store_result: Store the resulting sum to an address or variable
 440 *
 441 * @algo:               Hash algorithm being used
 442 * @sum:                Hash digest (algo->digest_size bytes)
 443 * @dest:               Destination, interpreted as a hex address if it starts
 444 *                      with * (or allow_env_vars is 0) or otherwise as an
 445 *                      environment variable.
 446 * @allow_env_vars:     non-zero to permit storing the result to an
 447 *                      variable environment
 448 */
 449static void store_result(struct hash_algo *algo, const uint8_t *sum,
 450                         const char *dest, int allow_env_vars)
 451{
 452        unsigned int i;
 453        int env_var = 0;
 454
 455        /*
 456         * If environment variables are allowed, then we assume that 'dest'
 457         * is an environment variable, unless it starts with *, in which
 458         * case we assume it is an address. If not allowed, it is always an
 459         * address. This is to support the crc32 command.
 460         */
 461        if (allow_env_vars) {
 462                if (*dest == '*')
 463                        dest++;
 464                else
 465                        env_var = 1;
 466        }
 467
 468        if (env_var) {
 469                char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1];
 470                char *str_ptr = str_output;
 471
 472                for (i = 0; i < algo->digest_size; i++) {
 473                        sprintf(str_ptr, "%02x", sum[i]);
 474                        str_ptr += 2;
 475                }
 476                *str_ptr = '\0';
 477                env_set(dest, str_output);
 478        } else {
 479                ulong addr;
 480                void *buf;
 481
 482                addr = hextoul(dest, NULL);
 483                buf = map_sysmem(addr, algo->digest_size);
 484                memcpy(buf, sum, algo->digest_size);
 485                unmap_sysmem(buf);
 486        }
 487}
 488
 489/**
 490 * parse_verify_sum: Parse a hash verification parameter
 491 *
 492 * @algo:               Hash algorithm being used
 493 * @verify_str:         Argument to parse. If it starts with * then it is
 494 *                      interpreted as a hex address containing the hash.
 495 *                      If the length is exactly the right number of hex digits
 496 *                      for the digest size, then we assume it is a hex digest.
 497 *                      Otherwise we assume it is an environment variable, and
 498 *                      look up its value (it must contain a hex digest).
 499 * @vsum:               Returns binary digest value (algo->digest_size bytes)
 500 * @allow_env_vars:     non-zero to permit storing the result to an environment
 501 *                      variable. If 0 then verify_str is assumed to be an
 502 *                      address, and the * prefix is not expected.
 503 * @return 0 if ok, non-zero on error
 504 */
 505static int parse_verify_sum(struct hash_algo *algo, char *verify_str,
 506                            uint8_t *vsum, int allow_env_vars)
 507{
 508        int env_var = 0;
 509
 510        /* See comment above in store_result() */
 511        if (allow_env_vars) {
 512                if (*verify_str == '*')
 513                        verify_str++;
 514                else
 515                        env_var = 1;
 516        }
 517
 518        if (!env_var) {
 519                ulong addr;
 520                void *buf;
 521
 522                addr = hextoul(verify_str, NULL);
 523                buf = map_sysmem(addr, algo->digest_size);
 524                memcpy(vsum, buf, algo->digest_size);
 525        } else {
 526                char *vsum_str;
 527                int digits = algo->digest_size * 2;
 528
 529                /*
 530                 * As with the original code from sha1sum.c, we assume that a
 531                 * string which matches the digest size exactly is a hex
 532                 * string and not an environment variable.
 533                 */
 534                if (strlen(verify_str) == digits)
 535                        vsum_str = verify_str;
 536                else {
 537                        vsum_str = env_get(verify_str);
 538                        if (vsum_str == NULL || strlen(vsum_str) != digits) {
 539                                printf("Expected %d hex digits in env var\n",
 540                                       digits);
 541                                return 1;
 542                        }
 543                }
 544
 545                hash_parse_string(algo->name, vsum_str, vsum);
 546        }
 547        return 0;
 548}
 549
 550static void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output)
 551{
 552        int i;
 553
 554        printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1);
 555        for (i = 0; i < algo->digest_size; i++)
 556                printf("%02x", output[i]);
 557}
 558
 559int hash_command(const char *algo_name, int flags, struct cmd_tbl *cmdtp,
 560                 int flag, int argc, char *const argv[])
 561{
 562        ulong addr, len;
 563
 564        if ((argc < 2) || ((flags & HASH_FLAG_VERIFY) && (argc < 3)))
 565                return CMD_RET_USAGE;
 566
 567        addr = hextoul(*argv++, NULL);
 568        len = hextoul(*argv++, NULL);
 569
 570        if (multi_hash()) {
 571                struct hash_algo *algo;
 572                u8 *output;
 573                uint8_t vsum[HASH_MAX_DIGEST_SIZE];
 574                void *buf;
 575
 576                if (hash_lookup_algo(algo_name, &algo)) {
 577                        printf("Unknown hash algorithm '%s'\n", algo_name);
 578                        return CMD_RET_USAGE;
 579                }
 580                argc -= 2;
 581
 582                if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
 583                        puts("HASH_MAX_DIGEST_SIZE exceeded\n");
 584                        return 1;
 585                }
 586
 587                output = memalign(ARCH_DMA_MINALIGN,
 588                                  sizeof(uint32_t) * HASH_MAX_DIGEST_SIZE);
 589
 590                buf = map_sysmem(addr, len);
 591                algo->hash_func_ws(buf, len, output, algo->chunk_size);
 592                unmap_sysmem(buf);
 593
 594                /* Try to avoid code bloat when verify is not needed */
 595#if defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_SHA1SUM_VERIFY) || \
 596        defined(CONFIG_HASH_VERIFY)
 597                if (flags & HASH_FLAG_VERIFY) {
 598#else
 599                if (0) {
 600#endif
 601                        if (parse_verify_sum(algo, *argv, vsum,
 602                                        flags & HASH_FLAG_ENV)) {
 603                                printf("ERROR: %s does not contain a valid "
 604                                        "%s sum\n", *argv, algo->name);
 605                                return 1;
 606                        }
 607                        if (memcmp(output, vsum, algo->digest_size) != 0) {
 608                                int i;
 609
 610                                hash_show(algo, addr, len, output);
 611                                printf(" != ");
 612                                for (i = 0; i < algo->digest_size; i++)
 613                                        printf("%02x", vsum[i]);
 614                                puts(" ** ERROR **\n");
 615                                return 1;
 616                        }
 617                } else {
 618                        hash_show(algo, addr, len, output);
 619                        printf("\n");
 620
 621                        if (argc) {
 622                                store_result(algo, output, *argv,
 623                                        flags & HASH_FLAG_ENV);
 624                        }
 625                unmap_sysmem(output);
 626
 627                }
 628
 629        /* Horrible code size hack for boards that just want crc32 */
 630        } else {
 631                ulong crc;
 632                ulong *ptr;
 633
 634                crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32);
 635
 636                printf("CRC32 for %08lx ... %08lx ==> %08lx\n",
 637                                addr, addr + len - 1, crc);
 638
 639                if (argc >= 3) {
 640                        ptr = (ulong *)hextoul(argv[0], NULL);
 641                        *ptr = crc;
 642                }
 643        }
 644
 645        return 0;
 646}
 647#endif /* CONFIG_CMD_HASH || CONFIG_CMD_SHA1SUM || CONFIG_CMD_CRC32) */
 648#endif /* !USE_HOSTCC */
 649