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