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