Blame view
common/hash.c
10.4 KB
460408ef9 Add generic hash API |
1 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. * |
1a4596601 Add GPL-2.0+ SPDX... |
10 |
* SPDX-License-Identifier: GPL-2.0+ |
460408ef9 Add generic hash API |
11 |
*/ |
2dd900271 Use hash.c in mki... |
12 |
#ifndef USE_HOSTCC |
460408ef9 Add generic hash API |
13 14 |
#include <common.h> #include <command.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 19 20 21 22 23 24 |
#include <asm/io.h> #include <asm/errno.h> #else #include "mkimage.h" #include <time.h> #include <image.h> #endif /* !USE_HOSTCC*/ |
460408ef9 Add generic hash API |
25 |
#include <hash.h> |
2dd900271 Use hash.c in mki... |
26 |
#include <u-boot/crc.h> |
2b9912e6a includes: move op... |
27 28 |
#include <u-boot/sha1.h> #include <u-boot/sha256.h> |
2dd900271 Use hash.c in mki... |
29 |
#include <u-boot/md5.h> |
460408ef9 Add generic hash API |
30 |
|
46fe2c044 hash: Add functio... |
31 |
#ifdef CONFIG_SHA1 |
bf007ebb6 gen: Add progress... |
32 33 34 35 36 37 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 64 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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
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 #ifdef CONFIG_SHA256 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 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 |
112 113 |
/* * These are the hash algorithms we support. Chips which support accelerated |
218da0f35 hash: Use lower c... |
114 115 |
* crypto could perhaps add named version of these algorithms here. Note that * algorithm names must be in lower case. |
460408ef9 Add generic hash API |
116 117 |
*/ static struct hash_algo hash_algo[] = { |
d20a40de9 Roll crc32 into h... |
118 |
/* |
1f9c92808 gen: Add sha h/w ... |
119 120 121 122 123 124 125 126 127 |
* CONFIG_SHA_HW_ACCEL is defined if hardware acceleration is * available. */ #ifdef CONFIG_SHA_HW_ACCEL { "sha1", SHA1_SUM_LEN, hw_sha1, CHUNKSZ_SHA1, |
94e3c8c4f crypto/fsl - Add ... |
128 129 130 131 132 |
#ifdef CONFIG_SHA_PROG_HW_ACCEL hw_sha_init, hw_sha_update, hw_sha_finish, #endif |
1f9c92808 gen: Add sha h/w ... |
133 134 135 136 137 |
}, { "sha256", SHA256_SUM_LEN, hw_sha256, CHUNKSZ_SHA256, |
94e3c8c4f crypto/fsl - Add ... |
138 139 140 141 142 |
#ifdef CONFIG_SHA_PROG_HW_ACCEL hw_sha_init, hw_sha_update, hw_sha_finish, #endif |
1f9c92808 gen: Add sha h/w ... |
143 144 |
}, #endif |
46fe2c044 hash: Add functio... |
145 |
#ifdef CONFIG_SHA1 |
460408ef9 Add generic hash API |
146 |
{ |
218da0f35 hash: Use lower c... |
147 |
"sha1", |
460408ef9 Add generic hash API |
148 149 150 |
SHA1_SUM_LEN, sha1_csum_wd, CHUNKSZ_SHA1, |
bf007ebb6 gen: Add progress... |
151 152 153 |
hash_init_sha1, hash_update_sha1, hash_finish_sha1, |
460408ef9 Add generic hash API |
154 155 156 157 |
}, #endif #ifdef CONFIG_SHA256 { |
218da0f35 hash: Use lower c... |
158 |
"sha256", |
460408ef9 Add generic hash API |
159 160 161 |
SHA256_SUM_LEN, sha256_csum_wd, CHUNKSZ_SHA256, |
bf007ebb6 gen: Add progress... |
162 163 164 |
hash_init_sha256, hash_update_sha256, hash_finish_sha256, |
460408ef9 Add generic hash API |
165 166 |
}, #endif |
d20a40de9 Roll crc32 into h... |
167 |
{ |
218da0f35 hash: Use lower c... |
168 |
"crc32", |
d20a40de9 Roll crc32 into h... |
169 170 171 |
4, crc32_wd_buf, CHUNKSZ_CRC32, |
bf007ebb6 gen: Add progress... |
172 173 174 |
hash_init_crc32, hash_update_crc32, hash_finish_crc32, |
d20a40de9 Roll crc32 into h... |
175 |
}, |
460408ef9 Add generic hash API |
176 |
}; |
46fe2c044 hash: Add functio... |
177 178 179 |
#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) #define MULTI_HASH #endif |
d20a40de9 Roll crc32 into h... |
180 181 182 183 184 185 186 187 188 189 |
#if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH) #define MULTI_HASH #endif /* Try to minimize code size for boards that don't want much hashing */ #ifdef MULTI_HASH #define multi_hash() 1 #else #define multi_hash() 0 #endif |
2dd900271 Use hash.c in mki... |
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
int hash_lookup_algo(const char *algo_name, struct hash_algo **algop) { int i; 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; 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... |
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
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; } |
460408ef9 Add generic hash API |
245 246 247 248 249 250 |
/** * 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 ... |
251 252 253 254 |
* 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 |
255 |
*/ |
04819a4ff hash: Use uint8_t... |
256 |
static void store_result(struct hash_algo *algo, const uint8_t *sum, |
d5b76673a hash: Add a flag ... |
257 |
const char *dest, int allow_env_vars) |
460408ef9 Add generic hash API |
258 259 |
{ unsigned int i; |
d5b76673a hash: Add a flag ... |
260 |
int env_var = 0; |
460408ef9 Add generic hash API |
261 |
|
d5b76673a hash: Add a flag ... |
262 263 264 265 266 267 268 269 270 271 272 273 |
/* * 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 |
274 |
|
d5b76673a hash: Add a flag ... |
275 |
if (env_var) { |
460408ef9 Add generic hash API |
276 277 278 279 280 281 282 |
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... |
283 |
*str_ptr = '\0'; |
460408ef9 Add generic hash API |
284 |
setenv(dest, str_output); |
d5b76673a hash: Add a flag ... |
285 |
} else { |
bd091b67d sandbox: Allow ha... |
286 287 |
ulong addr; void *buf; |
d5b76673a hash: Add a flag ... |
288 |
|
bd091b67d sandbox: Allow ha... |
289 290 291 292 |
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 |
293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
} } /** * 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 ... |
307 308 309 |
* @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 |
310 311 |
* @return 0 if ok, non-zero on error */ |
04819a4ff hash: Use uint8_t... |
312 313 |
static int parse_verify_sum(struct hash_algo *algo, char *verify_str, uint8_t *vsum, int allow_env_vars) |
460408ef9 Add generic hash API |
314 |
{ |
d5b76673a hash: Add a flag ... |
315 316 317 318 319 320 321 322 323 |
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... |
324 |
if (!env_var) { |
bd091b67d sandbox: Allow ha... |
325 326 |
ulong addr; void *buf; |
460408ef9 Add generic hash API |
327 |
|
bd091b67d sandbox: Allow ha... |
328 329 330 |
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 |
331 |
} else { |
460408ef9 Add generic hash API |
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
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 { vsum_str = getenv(verify_str); if (vsum_str == NULL || strlen(vsum_str) != digits) { printf("Expected %d hex digits in env var ", digits); return 1; } } |
8f0b1e24e autoboot.c: Add f... |
351 |
hash_parse_string(algo->name, vsum_str, vsum); |
460408ef9 Add generic hash API |
352 353 354 |
} return 0; } |
04819a4ff hash: Use uint8_t... |
355 |
void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output) |
460408ef9 Add generic hash API |
356 357 358 359 360 361 362 |
{ 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]); } |
6f907b422 hash: Add a way t... |
363 364 365 366 |
int hash_block(const char *algo_name, const void *data, unsigned int len, uint8_t *output, int *output_size) { struct hash_algo *algo; |
bf007ebb6 gen: Add progress... |
367 368 369 370 371 |
int ret; ret = hash_lookup_algo(algo_name, &algo); if (ret) return ret; |
6f907b422 hash: Add a way t... |
372 |
|
6f907b422 hash: Add a way t... |
373 374 375 376 377 378 379 380 381 382 383 |
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; } |
d5b76673a hash: Add a flag ... |
384 |
int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, |
460408ef9 Add generic hash API |
385 386 |
int argc, char * const argv[]) { |
460408ef9 Add generic hash API |
387 |
ulong addr, len; |
460408ef9 Add generic hash API |
388 |
|
3ef46a998 Fix hash verifica... |
389 |
if ((argc < 2) || ((flags & HASH_FLAG_VERIFY) && (argc < 3))) |
460408ef9 Add generic hash API |
390 |
return CMD_RET_USAGE; |
d5b76673a hash: Add a flag ... |
391 392 |
addr = simple_strtoul(*argv++, NULL, 16); len = simple_strtoul(*argv++, NULL, 16); |
d20a40de9 Roll crc32 into h... |
393 394 |
if (multi_hash()) { struct hash_algo *algo; |
04819a4ff hash: Use uint8_t... |
395 396 |
uint8_t output[HASH_MAX_DIGEST_SIZE]; uint8_t vsum[HASH_MAX_DIGEST_SIZE]; |
bd091b67d sandbox: Allow ha... |
397 |
void *buf; |
460408ef9 Add generic hash API |
398 |
|
bf007ebb6 gen: Add progress... |
399 |
if (hash_lookup_algo(algo_name, &algo)) { |
d20a40de9 Roll crc32 into h... |
400 401 402 403 404 405 406 407 408 409 410 |
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 |
411 |
|
bd091b67d sandbox: Allow ha... |
412 413 414 |
buf = map_sysmem(addr, len); algo->hash_func_ws(buf, len, output, algo->chunk_size); unmap_sysmem(buf); |
460408ef9 Add generic hash API |
415 |
|
d20a40de9 Roll crc32 into h... |
416 |
/* Try to avoid code bloat when verify is not needed */ |
460408ef9 Add generic hash API |
417 |
#ifdef CONFIG_HASH_VERIFY |
d20a40de9 Roll crc32 into h... |
418 |
if (flags & HASH_FLAG_VERIFY) { |
460408ef9 Add generic hash API |
419 |
#else |
d20a40de9 Roll crc32 into h... |
420 |
if (0) { |
460408ef9 Add generic hash API |
421 |
#endif |
d20a40de9 Roll crc32 into h... |
422 |
if (parse_verify_sum(algo, *argv, vsum, |
d5b76673a hash: Add a flag ... |
423 |
flags & HASH_FLAG_ENV)) { |
d20a40de9 Roll crc32 into h... |
424 425 426 427 428 429 430 |
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 |
431 |
|
31890ae29 hash: Export the ... |
432 |
hash_show(algo, addr, len, output); |
d20a40de9 Roll crc32 into h... |
433 434 435 436 437 438 439 440 |
printf(" != "); for (i = 0; i < algo->digest_size; i++) printf("%02x", vsum[i]); puts(" ** ERROR ** "); return 1; } } else { |
31890ae29 hash: Export the ... |
441 |
hash_show(algo, addr, len, output); |
d20a40de9 Roll crc32 into h... |
442 443 444 445 446 447 448 |
printf(" "); if (argc) { store_result(algo, output, *argv, flags & HASH_FLAG_ENV); } |
460408ef9 Add generic hash API |
449 |
} |
d20a40de9 Roll crc32 into h... |
450 451 |
/* Horrible code size hack for boards that just want crc32 */ |
460408ef9 Add generic hash API |
452 |
} else { |
d20a40de9 Roll crc32 into h... |
453 454 455 456 457 458 459 460 |
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 |
461 |
|
4b756b013 hash.c: Correct n... |
462 463 |
if (argc >= 3) { ptr = (ulong *)simple_strtoul(argv[0], NULL, 16); |
d20a40de9 Roll crc32 into h... |
464 |
*ptr = crc; |
d5b76673a hash: Add a flag ... |
465 |
} |
460408ef9 Add generic hash API |
466 467 468 469 |
} return 0; } |
2dd900271 Use hash.c in mki... |
470 |
#endif |