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 <sha1.h> 19 #include <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 u8 *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, u8 *vsum, 247 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 static void show_hash(struct hash_algo *algo, ulong addr, ulong len, 315 u8 *output) 316 { 317 int i; 318 319 printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1); 320 for (i = 0; i < algo->digest_size; i++) 321 printf("%02x", output[i]); 322 } 323 324 int hash_block(const char *algo_name, const void *data, unsigned int len, 325 uint8_t *output, int *output_size) 326 { 327 struct hash_algo *algo; 328 int ret; 329 330 ret = hash_lookup_algo(algo_name, &algo); 331 if (ret) 332 return ret; 333 334 if (output_size && *output_size < algo->digest_size) { 335 debug("Output buffer size %d too small (need %d bytes)", 336 *output_size, algo->digest_size); 337 return -ENOSPC; 338 } 339 if (output_size) 340 *output_size = algo->digest_size; 341 algo->hash_func_ws(data, len, output, algo->chunk_size); 342 343 return 0; 344 } 345 346 int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, 347 int argc, char * const argv[]) 348 { 349 ulong addr, len; 350 351 if (argc < 2) 352 return CMD_RET_USAGE; 353 354 addr = simple_strtoul(*argv++, NULL, 16); 355 len = simple_strtoul(*argv++, NULL, 16); 356 357 if (multi_hash()) { 358 struct hash_algo *algo; 359 u8 output[HASH_MAX_DIGEST_SIZE]; 360 u8 vsum[HASH_MAX_DIGEST_SIZE]; 361 void *buf; 362 363 if (hash_lookup_algo(algo_name, &algo)) { 364 printf("Unknown hash algorithm '%s'\n", algo_name); 365 return CMD_RET_USAGE; 366 } 367 argc -= 2; 368 369 if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { 370 puts("HASH_MAX_DIGEST_SIZE exceeded\n"); 371 return 1; 372 } 373 374 buf = map_sysmem(addr, len); 375 algo->hash_func_ws(buf, len, output, algo->chunk_size); 376 unmap_sysmem(buf); 377 378 /* Try to avoid code bloat when verify is not needed */ 379 #ifdef CONFIG_HASH_VERIFY 380 if (flags & HASH_FLAG_VERIFY) { 381 #else 382 if (0) { 383 #endif 384 if (!argc) 385 return CMD_RET_USAGE; 386 if (parse_verify_sum(algo, *argv, vsum, 387 flags & HASH_FLAG_ENV)) { 388 printf("ERROR: %s does not contain a valid " 389 "%s sum\n", *argv, algo->name); 390 return 1; 391 } 392 if (memcmp(output, vsum, algo->digest_size) != 0) { 393 int i; 394 395 show_hash(algo, addr, len, output); 396 printf(" != "); 397 for (i = 0; i < algo->digest_size; i++) 398 printf("%02x", vsum[i]); 399 puts(" ** ERROR **\n"); 400 return 1; 401 } 402 } else { 403 show_hash(algo, addr, len, output); 404 printf("\n"); 405 406 if (argc) { 407 store_result(algo, output, *argv, 408 flags & HASH_FLAG_ENV); 409 } 410 } 411 412 /* Horrible code size hack for boards that just want crc32 */ 413 } else { 414 ulong crc; 415 ulong *ptr; 416 417 crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32); 418 419 printf("CRC32 for %08lx ... %08lx ==> %08lx\n", 420 addr, addr + len - 1, crc); 421 422 if (argc >= 3) { 423 ptr = (ulong *)simple_strtoul(argv[0], NULL, 16); 424 *ptr = crc; 425 } 426 } 427 428 return 0; 429 } 430