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