Blame view
common/hash.c
12.4 KB
83d290c56 SPDX: Convert all... |
1 |
// SPDX-License-Identifier: GPL-2.0+ |
460408ef9 Add generic hash API |
2 3 4 5 6 7 8 9 |
/* * Copyright (c) 2012 The Chromium OS Authors. * * (C) Copyright 2011 * Joe Hershberger, National Instruments, joe.hershberger@ni.com * * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
460408ef9 Add generic hash API |
10 |
*/ |
2dd900271 Use hash.c in mki... |
11 |
#ifndef USE_HOSTCC |
460408ef9 Add generic hash API |
12 13 |
#include <common.h> #include <command.h> |
9fb625ce0 env: Move env_set... |
14 |
#include <env.h> |
bf007ebb6 gen: Add progress... |
15 |
#include <malloc.h> |
0eb25b619 common: Make sure... |
16 |
#include <mapmem.h> |
1f9c92808 gen: Add sha h/w ... |
17 |
#include <hw_sha.h> |
2dd900271 Use hash.c in mki... |
18 |
#include <asm/io.h> |
1221ce459 treewide: replace... |
19 |
#include <linux/errno.h> |
3db711085 crc32: Use the cr... |
20 |
#include <u-boot/crc.h> |
2dd900271 Use hash.c in mki... |
21 22 23 24 25 |
#else #include "mkimage.h" #include <time.h> #include <image.h> #endif /* !USE_HOSTCC*/ |
460408ef9 Add generic hash API |
26 |
#include <hash.h> |
2dd900271 Use hash.c in mki... |
27 |
#include <u-boot/crc.h> |
2b9912e6a includes: move op... |
28 29 |
#include <u-boot/sha1.h> #include <u-boot/sha256.h> |
2dd900271 Use hash.c in mki... |
30 |
#include <u-boot/md5.h> |
460408ef9 Add generic hash API |
31 |
|
10088fb03 common: hash: Man... |
32 33 34 35 36 |
#if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC) DECLARE_GLOBAL_DATA_PTR; #endif static void reloc_update(void); |
78eda89e9 hash: Compile onl... |
37 |
#if defined(CONFIG_SHA1) && !defined(CONFIG_SHA_PROG_HW_ACCEL) |
bf007ebb6 gen: Add progress... |
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
static int hash_init_sha1(struct hash_algo *algo, void **ctxp) { sha1_context *ctx = malloc(sizeof(sha1_context)); sha1_starts(ctx); *ctxp = ctx; return 0; } static int hash_update_sha1(struct hash_algo *algo, void *ctx, const void *buf, unsigned int size, int is_last) { sha1_update((sha1_context *)ctx, buf, size); return 0; } static int hash_finish_sha1(struct hash_algo *algo, void *ctx, void *dest_buf, int size) { if (size < algo->digest_size) return -1; sha1_finish((sha1_context *)ctx, dest_buf); free(ctx); return 0; } #endif |
78eda89e9 hash: Compile onl... |
64 |
#if defined(CONFIG_SHA256) && !defined(CONFIG_SHA_PROG_HW_ACCEL) |
bf007ebb6 gen: Add progress... |
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
static int hash_init_sha256(struct hash_algo *algo, void **ctxp) { sha256_context *ctx = malloc(sizeof(sha256_context)); sha256_starts(ctx); *ctxp = ctx; return 0; } static int hash_update_sha256(struct hash_algo *algo, void *ctx, const void *buf, unsigned int size, int is_last) { sha256_update((sha256_context *)ctx, buf, size); return 0; } static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void *dest_buf, int size) { if (size < algo->digest_size) return -1; sha256_finish((sha256_context *)ctx, dest_buf); free(ctx); return 0; } #endif |
51c2345bd Roll CRC16-CCITT ... |
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp) { uint16_t *ctx = malloc(sizeof(uint16_t)); *ctx = 0; *ctxp = ctx; return 0; } static int hash_update_crc16_ccitt(struct hash_algo *algo, void *ctx, const void *buf, unsigned int size, int is_last) { *((uint16_t *)ctx) = crc16_ccitt(*((uint16_t *)ctx), buf, size); return 0; } static int hash_finish_crc16_ccitt(struct hash_algo *algo, void *ctx, void *dest_buf, int size) { if (size < algo->digest_size) return -1; *((uint16_t *)dest_buf) = *((uint16_t *)ctx); free(ctx); return 0; } |
bf007ebb6 gen: Add progress... |
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
static int hash_init_crc32(struct hash_algo *algo, void **ctxp) { uint32_t *ctx = malloc(sizeof(uint32_t)); *ctx = 0; *ctxp = ctx; return 0; } static int hash_update_crc32(struct hash_algo *algo, void *ctx, const void *buf, unsigned int size, int is_last) { *((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size); return 0; } static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf, int size) { if (size < algo->digest_size) return -1; *((uint32_t *)dest_buf) = *((uint32_t *)ctx); free(ctx); return 0; } |
460408ef9 Add generic hash API |
142 |
/* |
78eda89e9 hash: Compile onl... |
143 144 145 |
* These are the hash algorithms we support. If we have hardware acceleration * is enable we will use that, otherwise a software version of the algorithm. * Note that algorithm names must be in lower case. |
460408ef9 Add generic hash API |
146 147 |
*/ static struct hash_algo hash_algo[] = { |
78eda89e9 hash: Compile onl... |
148 |
#ifdef CONFIG_SHA1 |
1f9c92808 gen: Add sha h/w ... |
149 |
{ |
78eda89e9 hash: Compile onl... |
150 151 152 153 154 155 156 |
.name = "sha1", .digest_size = SHA1_SUM_LEN, .chunk_size = CHUNKSZ_SHA1, #ifdef CONFIG_SHA_HW_ACCEL .hash_func_ws = hw_sha1, #else .hash_func_ws = sha1_csum_wd, |
94e3c8c4f crypto/fsl - Add ... |
157 |
#endif |
94e3c8c4f crypto/fsl - Add ... |
158 |
#ifdef CONFIG_SHA_PROG_HW_ACCEL |
78eda89e9 hash: Compile onl... |
159 160 161 162 163 164 165 |
.hash_init = hw_sha_init, .hash_update = hw_sha_update, .hash_finish = hw_sha_finish, #else .hash_init = hash_init_sha1, .hash_update = hash_update_sha1, .hash_finish = hash_finish_sha1, |
1f9c92808 gen: Add sha h/w ... |
166 |
#endif |
460408ef9 Add generic hash API |
167 168 169 170 |
}, #endif #ifdef CONFIG_SHA256 { |
78eda89e9 hash: Compile onl... |
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
.name = "sha256", .digest_size = SHA256_SUM_LEN, .chunk_size = CHUNKSZ_SHA256, #ifdef CONFIG_SHA_HW_ACCEL .hash_func_ws = hw_sha256, #else .hash_func_ws = sha256_csum_wd, #endif #ifdef CONFIG_SHA_PROG_HW_ACCEL .hash_init = hw_sha_init, .hash_update = hw_sha_update, .hash_finish = hw_sha_finish, #else .hash_init = hash_init_sha256, .hash_update = hash_update_sha256, .hash_finish = hash_finish_sha256, #endif |
460408ef9 Add generic hash API |
188 189 |
}, #endif |
d20a40de9 Roll crc32 into h... |
190 |
{ |
51c2345bd Roll CRC16-CCITT ... |
191 192 193 194 195 196 197 198 199 |
.name = "crc16-ccitt", .digest_size = 2, .chunk_size = CHUNKSZ, .hash_func_ws = crc16_ccitt_wd_buf, .hash_init = hash_init_crc16_ccitt, .hash_update = hash_update_crc16_ccitt, .hash_finish = hash_finish_crc16_ccitt, }, { |
78eda89e9 hash: Compile onl... |
200 201 202 203 204 205 206 |
.name = "crc32", .digest_size = 4, .chunk_size = CHUNKSZ_CRC32, .hash_func_ws = crc32_wd_buf, .hash_init = hash_init_crc32, .hash_update = hash_update_crc32, .hash_finish = hash_finish_crc32, |
d20a40de9 Roll crc32 into h... |
207 |
}, |
460408ef9 Add generic hash API |
208 |
}; |
d20a40de9 Roll crc32 into h... |
209 |
/* Try to minimize code size for boards that don't want much hashing */ |
221a949eb Kconfig: Finish m... |
210 211 |
#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) || \ defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH) |
d20a40de9 Roll crc32 into h... |
212 213 214 215 |
#define multi_hash() 1 #else #define multi_hash() 0 #endif |
10088fb03 common: hash: Man... |
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
static void reloc_update(void) { #if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC) int i; static bool done; if (!done) { done = true; for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { hash_algo[i].name += gd->reloc_off; hash_algo[i].hash_func_ws += gd->reloc_off; hash_algo[i].hash_init += gd->reloc_off; hash_algo[i].hash_update += gd->reloc_off; hash_algo[i].hash_finish += gd->reloc_off; } } #endif } |
2dd900271 Use hash.c in mki... |
234 235 236 |
int hash_lookup_algo(const char *algo_name, struct hash_algo **algop) { int i; |
10088fb03 common: hash: Man... |
237 |
reloc_update(); |
2dd900271 Use hash.c in mki... |
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { if (!strcmp(algo_name, hash_algo[i].name)) { *algop = &hash_algo[i]; return 0; } } debug("Unknown hash algorithm '%s' ", algo_name); return -EPROTONOSUPPORT; } int hash_progressive_lookup_algo(const char *algo_name, struct hash_algo **algop) { int i; |
10088fb03 common: hash: Man... |
254 |
reloc_update(); |
2dd900271 Use hash.c in mki... |
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { if (!strcmp(algo_name, hash_algo[i].name)) { if (hash_algo[i].hash_init) { *algop = &hash_algo[i]; return 0; } } } debug("Unknown hash algorithm '%s' ", algo_name); return -EPROTONOSUPPORT; } #ifndef USE_HOSTCC |
8f0b1e24e autoboot.c: Add f... |
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
int hash_parse_string(const char *algo_name, const char *str, uint8_t *result) { struct hash_algo *algo; int ret; int i; ret = hash_lookup_algo(algo_name, &algo); if (ret) return ret; for (i = 0; i < algo->digest_size; i++) { char chr[3]; strncpy(chr, &str[i * 2], 2); result[i] = simple_strtoul(chr, NULL, 16); } return 0; } |
48ad68deb hash.c: Condition... |
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
int hash_block(const char *algo_name, const void *data, unsigned int len, uint8_t *output, int *output_size) { struct hash_algo *algo; int ret; ret = hash_lookup_algo(algo_name, &algo); if (ret) return ret; if (output_size && *output_size < algo->digest_size) { debug("Output buffer size %d too small (need %d bytes)", *output_size, algo->digest_size); return -ENOSPC; } if (output_size) *output_size = algo->digest_size; algo->hash_func_ws(data, len, output, algo->chunk_size); return 0; } #if defined(CONFIG_CMD_HASH) || defined(CONFIG_CMD_SHA1SUM) || defined(CONFIG_CMD_CRC32) |
460408ef9 Add generic hash API |
312 313 314 315 316 317 |
/** * store_result: Store the resulting sum to an address or variable * * @algo: Hash algorithm being used * @sum: Hash digest (algo->digest_size bytes) * @dest: Destination, interpreted as a hex address if it starts |
d5b76673a hash: Add a flag ... |
318 319 320 321 |
* with * (or allow_env_vars is 0) or otherwise as an * environment variable. * @allow_env_vars: non-zero to permit storing the result to an * variable environment |
460408ef9 Add generic hash API |
322 |
*/ |
04819a4ff hash: Use uint8_t... |
323 |
static void store_result(struct hash_algo *algo, const uint8_t *sum, |
d5b76673a hash: Add a flag ... |
324 |
const char *dest, int allow_env_vars) |
460408ef9 Add generic hash API |
325 326 |
{ unsigned int i; |
d5b76673a hash: Add a flag ... |
327 |
int env_var = 0; |
460408ef9 Add generic hash API |
328 |
|
d5b76673a hash: Add a flag ... |
329 330 331 332 333 334 335 336 337 338 339 340 |
/* * If environment variables are allowed, then we assume that 'dest' * is an environment variable, unless it starts with *, in which * case we assume it is an address. If not allowed, it is always an * address. This is to support the crc32 command. */ if (allow_env_vars) { if (*dest == '*') dest++; else env_var = 1; } |
460408ef9 Add generic hash API |
341 |
|
d5b76673a hash: Add a flag ... |
342 |
if (env_var) { |
460408ef9 Add generic hash API |
343 344 345 346 347 348 349 |
char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1]; char *str_ptr = str_output; for (i = 0; i < algo->digest_size; i++) { sprintf(str_ptr, "%02x", sum[i]); str_ptr += 2; } |
8b9cc866c common: hash: zer... |
350 |
*str_ptr = '\0'; |
382bee57f env: Rename seten... |
351 |
env_set(dest, str_output); |
d5b76673a hash: Add a flag ... |
352 |
} else { |
bd091b67d sandbox: Allow ha... |
353 354 |
ulong addr; void *buf; |
d5b76673a hash: Add a flag ... |
355 |
|
bd091b67d sandbox: Allow ha... |
356 357 358 359 |
addr = simple_strtoul(dest, NULL, 16); buf = map_sysmem(addr, algo->digest_size); memcpy(buf, sum, algo->digest_size); unmap_sysmem(buf); |
460408ef9 Add generic hash API |
360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
} } /** * parse_verify_sum: Parse a hash verification parameter * * @algo: Hash algorithm being used * @verify_str: Argument to parse. If it starts with * then it is * interpreted as a hex address containing the hash. * If the length is exactly the right number of hex digits * for the digest size, then we assume it is a hex digest. * Otherwise we assume it is an environment variable, and * look up its value (it must contain a hex digest). * @vsum: Returns binary digest value (algo->digest_size bytes) |
d5b76673a hash: Add a flag ... |
374 375 376 |
* @allow_env_vars: non-zero to permit storing the result to an environment * variable. If 0 then verify_str is assumed to be an * address, and the * prefix is not expected. |
460408ef9 Add generic hash API |
377 378 |
* @return 0 if ok, non-zero on error */ |
04819a4ff hash: Use uint8_t... |
379 380 |
static int parse_verify_sum(struct hash_algo *algo, char *verify_str, uint8_t *vsum, int allow_env_vars) |
460408ef9 Add generic hash API |
381 |
{ |
d5b76673a hash: Add a flag ... |
382 383 384 385 386 387 388 389 390 |
int env_var = 0; /* See comment above in store_result() */ if (allow_env_vars) { if (*verify_str == '*') verify_str++; else env_var = 1; } |
3ef46a998 Fix hash verifica... |
391 |
if (!env_var) { |
bd091b67d sandbox: Allow ha... |
392 393 |
ulong addr; void *buf; |
460408ef9 Add generic hash API |
394 |
|
bd091b67d sandbox: Allow ha... |
395 396 397 |
addr = simple_strtoul(verify_str, NULL, 16); buf = map_sysmem(addr, algo->digest_size); memcpy(vsum, buf, algo->digest_size); |
460408ef9 Add generic hash API |
398 |
} else { |
460408ef9 Add generic hash API |
399 400 401 402 403 404 405 406 407 408 409 |
char *vsum_str; int digits = algo->digest_size * 2; /* * As with the original code from sha1sum.c, we assume that a * string which matches the digest size exactly is a hex * string and not an environment variable. */ if (strlen(verify_str) == digits) vsum_str = verify_str; else { |
00caae6d4 env: Rename geten... |
410 |
vsum_str = env_get(verify_str); |
460408ef9 Add generic hash API |
411 412 413 414 415 416 417 |
if (vsum_str == NULL || strlen(vsum_str) != digits) { printf("Expected %d hex digits in env var ", digits); return 1; } } |
8f0b1e24e autoboot.c: Add f... |
418 |
hash_parse_string(algo->name, vsum_str, vsum); |
460408ef9 Add generic hash API |
419 420 421 |
} return 0; } |
48ad68deb hash.c: Condition... |
422 |
static void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output) |
460408ef9 Add generic hash API |
423 424 425 426 427 428 429 |
{ int i; printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1); for (i = 0; i < algo->digest_size; i++) printf("%02x", output[i]); } |
d5b76673a hash: Add a flag ... |
430 |
int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, |
460408ef9 Add generic hash API |
431 432 |
int argc, char * const argv[]) { |
460408ef9 Add generic hash API |
433 |
ulong addr, len; |
460408ef9 Add generic hash API |
434 |
|
3ef46a998 Fix hash verifica... |
435 |
if ((argc < 2) || ((flags & HASH_FLAG_VERIFY) && (argc < 3))) |
460408ef9 Add generic hash API |
436 |
return CMD_RET_USAGE; |
d5b76673a hash: Add a flag ... |
437 438 |
addr = simple_strtoul(*argv++, NULL, 16); len = simple_strtoul(*argv++, NULL, 16); |
d20a40de9 Roll crc32 into h... |
439 440 |
if (multi_hash()) { struct hash_algo *algo; |
d7af2baa4 crypto/fsl: Fix H... |
441 |
u8 *output; |
04819a4ff hash: Use uint8_t... |
442 |
uint8_t vsum[HASH_MAX_DIGEST_SIZE]; |
bd091b67d sandbox: Allow ha... |
443 |
void *buf; |
460408ef9 Add generic hash API |
444 |
|
bf007ebb6 gen: Add progress... |
445 |
if (hash_lookup_algo(algo_name, &algo)) { |
d20a40de9 Roll crc32 into h... |
446 447 448 449 450 451 452 453 454 455 456 |
printf("Unknown hash algorithm '%s' ", algo_name); return CMD_RET_USAGE; } argc -= 2; if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { puts("HASH_MAX_DIGEST_SIZE exceeded "); return 1; } |
460408ef9 Add generic hash API |
457 |
|
d7af2baa4 crypto/fsl: Fix H... |
458 459 |
output = memalign(ARCH_DMA_MINALIGN, sizeof(uint32_t) * HASH_MAX_DIGEST_SIZE); |
bd091b67d sandbox: Allow ha... |
460 461 462 |
buf = map_sysmem(addr, len); algo->hash_func_ws(buf, len, output, algo->chunk_size); unmap_sysmem(buf); |
460408ef9 Add generic hash API |
463 |
|
d20a40de9 Roll crc32 into h... |
464 |
/* Try to avoid code bloat when verify is not needed */ |
221a949eb Kconfig: Finish m... |
465 466 |
#if defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_SHA1SUM_VERIFY) || \ defined(CONFIG_HASH_VERIFY) |
d20a40de9 Roll crc32 into h... |
467 |
if (flags & HASH_FLAG_VERIFY) { |
460408ef9 Add generic hash API |
468 |
#else |
d20a40de9 Roll crc32 into h... |
469 |
if (0) { |
460408ef9 Add generic hash API |
470 |
#endif |
d20a40de9 Roll crc32 into h... |
471 |
if (parse_verify_sum(algo, *argv, vsum, |
d5b76673a hash: Add a flag ... |
472 |
flags & HASH_FLAG_ENV)) { |
d20a40de9 Roll crc32 into h... |
473 474 475 476 477 478 479 |
printf("ERROR: %s does not contain a valid " "%s sum ", *argv, algo->name); return 1; } if (memcmp(output, vsum, algo->digest_size) != 0) { int i; |
460408ef9 Add generic hash API |
480 |
|
31890ae29 hash: Export the ... |
481 |
hash_show(algo, addr, len, output); |
d20a40de9 Roll crc32 into h... |
482 483 484 485 486 487 488 489 |
printf(" != "); for (i = 0; i < algo->digest_size; i++) printf("%02x", vsum[i]); puts(" ** ERROR ** "); return 1; } } else { |
31890ae29 hash: Export the ... |
490 |
hash_show(algo, addr, len, output); |
d20a40de9 Roll crc32 into h... |
491 492 493 494 495 496 497 |
printf(" "); if (argc) { store_result(algo, output, *argv, flags & HASH_FLAG_ENV); } |
d7af2baa4 crypto/fsl: Fix H... |
498 |
unmap_sysmem(output); |
460408ef9 Add generic hash API |
499 |
} |
d20a40de9 Roll crc32 into h... |
500 501 |
/* Horrible code size hack for boards that just want crc32 */ |
460408ef9 Add generic hash API |
502 |
} else { |
d20a40de9 Roll crc32 into h... |
503 504 505 506 507 508 509 510 |
ulong crc; ulong *ptr; crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32); printf("CRC32 for %08lx ... %08lx ==> %08lx ", addr, addr + len - 1, crc); |
460408ef9 Add generic hash API |
511 |
|
4b756b013 hash.c: Correct n... |
512 513 |
if (argc >= 3) { ptr = (ulong *)simple_strtoul(argv[0], NULL, 16); |
d20a40de9 Roll crc32 into h... |
514 |
*ptr = crc; |
d5b76673a hash: Add a flag ... |
515 |
} |
460408ef9 Add generic hash API |
516 517 518 519 |
} return 0; } |
d70f919e4 Kconfig: Add CONF... |
520 521 |
#endif /* CONFIG_CMD_HASH || CONFIG_CMD_SHA1SUM || CONFIG_CMD_CRC32) */ #endif /* !USE_HOSTCC */ |