hash.c 9.6 KB

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