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