hash: Drop some #ifdefs in hash.c
[platform/kernel/u-boot.git] / common / hash.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2012 The Chromium OS Authors.
4  *
5  * (C) Copyright 2011
6  * Joe Hershberger, National Instruments, joe.hershberger@ni.com
7  *
8  * (C) Copyright 2000
9  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
10  */
11
12 #ifndef USE_HOSTCC
13 #include <common.h>
14 #include <command.h>
15 #include <env.h>
16 #include <log.h>
17 #include <malloc.h>
18 #include <mapmem.h>
19 #include <hw_sha.h>
20 #include <asm/cache.h>
21 #include <asm/global_data.h>
22 #include <asm/io.h>
23 #include <linux/errno.h>
24 #include <u-boot/crc.h>
25 #else
26 #include "mkimage.h"
27 #include <linux/compiler_attributes.h>
28 #include <time.h>
29 #include <linux/kconfig.h>
30 #endif /* !USE_HOSTCC*/
31
32 #include <hash.h>
33 #include <image.h>
34 #include <u-boot/crc.h>
35 #include <u-boot/sha1.h>
36 #include <u-boot/sha256.h>
37 #include <u-boot/sha512.h>
38 #include <u-boot/md5.h>
39
40 #if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC)
41 DECLARE_GLOBAL_DATA_PTR;
42 #endif
43
44 static void reloc_update(void);
45
46 static int __maybe_unused hash_init_sha1(struct hash_algo *algo, void **ctxp)
47 {
48         sha1_context *ctx = malloc(sizeof(sha1_context));
49         sha1_starts(ctx);
50         *ctxp = ctx;
51         return 0;
52 }
53
54 static int __maybe_unused hash_update_sha1(struct hash_algo *algo, void *ctx,
55                                            const void *buf, unsigned int size,
56                                            int is_last)
57 {
58         sha1_update((sha1_context *)ctx, buf, size);
59         return 0;
60 }
61
62 static int __maybe_unused hash_finish_sha1(struct hash_algo *algo, void *ctx,
63                                            void *dest_buf, int size)
64 {
65         if (size < algo->digest_size)
66                 return -1;
67
68         sha1_finish((sha1_context *)ctx, dest_buf);
69         free(ctx);
70         return 0;
71 }
72
73 static int __maybe_unused hash_init_sha256(struct hash_algo *algo, void **ctxp)
74 {
75         sha256_context *ctx = malloc(sizeof(sha256_context));
76         sha256_starts(ctx);
77         *ctxp = ctx;
78         return 0;
79 }
80
81 static int __maybe_unused hash_update_sha256(struct hash_algo *algo, void *ctx,
82                                              const void *buf, uint size,
83                                              int is_last)
84 {
85         sha256_update((sha256_context *)ctx, buf, size);
86         return 0;
87 }
88
89 static int __maybe_unused hash_finish_sha256(struct hash_algo *algo, void *ctx,
90                                              void *dest_buf, int size)
91 {
92         if (size < algo->digest_size)
93                 return -1;
94
95         sha256_finish((sha256_context *)ctx, dest_buf);
96         free(ctx);
97         return 0;
98 }
99
100 static int __maybe_unused hash_init_sha384(struct hash_algo *algo, void **ctxp)
101 {
102         sha512_context *ctx = malloc(sizeof(sha512_context));
103         sha384_starts(ctx);
104         *ctxp = ctx;
105         return 0;
106 }
107
108 static int __maybe_unused hash_update_sha384(struct hash_algo *algo, void *ctx,
109                                              const void *buf, uint size,
110                                              int is_last)
111 {
112         sha384_update((sha512_context *)ctx, buf, size);
113         return 0;
114 }
115
116 static int __maybe_unused hash_finish_sha384(struct hash_algo *algo, void *ctx,
117                                              void *dest_buf, int size)
118 {
119         if (size < algo->digest_size)
120                 return -1;
121
122         sha384_finish((sha512_context *)ctx, dest_buf);
123         free(ctx);
124         return 0;
125 }
126
127 static int __maybe_unused hash_init_sha512(struct hash_algo *algo, void **ctxp)
128 {
129         sha512_context *ctx = malloc(sizeof(sha512_context));
130         sha512_starts(ctx);
131         *ctxp = ctx;
132         return 0;
133 }
134
135 static int __maybe_unused hash_update_sha512(struct hash_algo *algo, void *ctx,
136                                              const void *buf, uint size,
137                                              int is_last)
138 {
139         sha512_update((sha512_context *)ctx, buf, size);
140         return 0;
141 }
142
143 static int __maybe_unused hash_finish_sha512(struct hash_algo *algo, void *ctx,
144                                              void *dest_buf, int size)
145 {
146         if (size < algo->digest_size)
147                 return -1;
148
149         sha512_finish((sha512_context *)ctx, dest_buf);
150         free(ctx);
151         return 0;
152 }
153
154 static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp)
155 {
156         uint16_t *ctx = malloc(sizeof(uint16_t));
157         *ctx = 0;
158         *ctxp = ctx;
159         return 0;
160 }
161
162 static int hash_update_crc16_ccitt(struct hash_algo *algo, void *ctx,
163                                    const void *buf, unsigned int size,
164                                    int is_last)
165 {
166         *((uint16_t *)ctx) = crc16_ccitt(*((uint16_t *)ctx), buf, size);
167         return 0;
168 }
169
170 static int hash_finish_crc16_ccitt(struct hash_algo *algo, void *ctx,
171                                    void *dest_buf, int size)
172 {
173         if (size < algo->digest_size)
174                 return -1;
175
176         *((uint16_t *)dest_buf) = *((uint16_t *)ctx);
177         free(ctx);
178         return 0;
179 }
180
181 static int hash_init_crc32(struct hash_algo *algo, void **ctxp)
182 {
183         uint32_t *ctx = malloc(sizeof(uint32_t));
184         *ctx = 0;
185         *ctxp = ctx;
186         return 0;
187 }
188
189 static int hash_update_crc32(struct hash_algo *algo, void *ctx,
190                              const void *buf, unsigned int size, int is_last)
191 {
192         *((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size);
193         return 0;
194 }
195
196 static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf,
197                              int size)
198 {
199         if (size < algo->digest_size)
200                 return -1;
201
202         *((uint32_t *)dest_buf) = *((uint32_t *)ctx);
203         free(ctx);
204         return 0;
205 }
206
207 /*
208  * These are the hash algorithms we support.  If we have hardware acceleration
209  * is enable we will use that, otherwise a software version of the algorithm.
210  * Note that algorithm names must be in lower case.
211  */
212 static struct hash_algo hash_algo[] = {
213 #if CONFIG_IS_ENABLED(MD5)
214         {
215                 .name           = "md5",
216                 .digest_size    = MD5_SUM_LEN,
217                 .chunk_size     = CHUNKSZ_MD5,
218                 .hash_func_ws   = md5_wd,
219         },
220 #endif
221 #if CONFIG_IS_ENABLED(SHA1)
222         {
223                 .name           = "sha1",
224                 .digest_size    = SHA1_SUM_LEN,
225                 .chunk_size     = CHUNKSZ_SHA1,
226 #if CONFIG_IS_ENABLED(SHA_HW_ACCEL)
227                 .hash_func_ws   = hw_sha1,
228 #else
229                 .hash_func_ws   = sha1_csum_wd,
230 #endif
231 #if CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL)
232                 .hash_init      = hw_sha_init,
233                 .hash_update    = hw_sha_update,
234                 .hash_finish    = hw_sha_finish,
235 #else
236                 .hash_init      = hash_init_sha1,
237                 .hash_update    = hash_update_sha1,
238                 .hash_finish    = hash_finish_sha1,
239 #endif
240         },
241 #endif
242 #if CONFIG_IS_ENABLED(SHA256)
243         {
244                 .name           = "sha256",
245                 .digest_size    = SHA256_SUM_LEN,
246                 .chunk_size     = CHUNKSZ_SHA256,
247 #if CONFIG_IS_ENABLED(SHA_HW_ACCEL)
248                 .hash_func_ws   = hw_sha256,
249 #else
250                 .hash_func_ws   = sha256_csum_wd,
251 #endif
252 #if CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL)
253                 .hash_init      = hw_sha_init,
254                 .hash_update    = hw_sha_update,
255                 .hash_finish    = hw_sha_finish,
256 #else
257                 .hash_init      = hash_init_sha256,
258                 .hash_update    = hash_update_sha256,
259                 .hash_finish    = hash_finish_sha256,
260 #endif
261         },
262 #endif
263 #if CONFIG_IS_ENABLED(SHA384)
264         {
265                 .name           = "sha384",
266                 .digest_size    = SHA384_SUM_LEN,
267                 .chunk_size     = CHUNKSZ_SHA384,
268 #if CONFIG_IS_ENABLED(SHA512_HW_ACCEL)
269                 .hash_func_ws   = hw_sha384,
270 #else
271                 .hash_func_ws   = sha384_csum_wd,
272 #endif
273 #if CONFIG_IS_ENABLED(SHA512_HW_ACCEL) && CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL)
274                 .hash_init      = hw_sha_init,
275                 .hash_update    = hw_sha_update,
276                 .hash_finish    = hw_sha_finish,
277 #else
278                 .hash_init      = hash_init_sha384,
279                 .hash_update    = hash_update_sha384,
280                 .hash_finish    = hash_finish_sha384,
281 #endif
282         },
283 #endif
284 #if CONFIG_IS_ENABLED(SHA512)
285         {
286                 .name           = "sha512",
287                 .digest_size    = SHA512_SUM_LEN,
288                 .chunk_size     = CHUNKSZ_SHA512,
289 #if CONFIG_IS_ENABLED(SHA512_HW_ACCEL)
290                 .hash_func_ws   = hw_sha512,
291 #else
292                 .hash_func_ws   = sha512_csum_wd,
293 #endif
294 #if CONFIG_IS_ENABLED(SHA512_HW_ACCEL) && CONFIG_IS_ENABLED(SHA_PROG_HW_ACCEL)
295                 .hash_init      = hw_sha_init,
296                 .hash_update    = hw_sha_update,
297                 .hash_finish    = hw_sha_finish,
298 #else
299                 .hash_init      = hash_init_sha512,
300                 .hash_update    = hash_update_sha512,
301                 .hash_finish    = hash_finish_sha512,
302 #endif
303         },
304 #endif
305         {
306                 .name           = "crc16-ccitt",
307                 .digest_size    = 2,
308                 .chunk_size     = CHUNKSZ,
309                 .hash_func_ws   = crc16_ccitt_wd_buf,
310                 .hash_init      = hash_init_crc16_ccitt,
311                 .hash_update    = hash_update_crc16_ccitt,
312                 .hash_finish    = hash_finish_crc16_ccitt,
313         },
314         {
315                 .name           = "crc32",
316                 .digest_size    = 4,
317                 .chunk_size     = CHUNKSZ_CRC32,
318                 .hash_func_ws   = crc32_wd_buf,
319                 .hash_init      = hash_init_crc32,
320                 .hash_update    = hash_update_crc32,
321                 .hash_finish    = hash_finish_crc32,
322         },
323 };
324
325 /* Try to minimize code size for boards that don't want much hashing */
326 #if CONFIG_IS_ENABLED(SHA256) || CONFIG_IS_ENABLED(CMD_SHA1SUM) || \
327         CONFIG_IS_ENABLED(CRC32_VERIFY) || CONFIG_IS_ENABLED(CMD_HASH) || \
328         CONFIG_IS_ENABLED(SHA384) || CONFIG_IS_ENABLED(SHA512)
329 #define multi_hash()    1
330 #else
331 #define multi_hash()    0
332 #endif
333
334 static void reloc_update(void)
335 {
336 #if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC)
337         int i;
338         static bool done;
339
340         if (!done) {
341                 done = true;
342                 for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
343                         hash_algo[i].name += gd->reloc_off;
344                         hash_algo[i].hash_func_ws += gd->reloc_off;
345                         hash_algo[i].hash_init += gd->reloc_off;
346                         hash_algo[i].hash_update += gd->reloc_off;
347                         hash_algo[i].hash_finish += gd->reloc_off;
348                 }
349         }
350 #endif
351 }
352
353 int hash_lookup_algo(const char *algo_name, struct hash_algo **algop)
354 {
355         int i;
356
357         reloc_update();
358
359         for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
360                 if (!strcmp(algo_name, hash_algo[i].name)) {
361                         *algop = &hash_algo[i];
362                         return 0;
363                 }
364         }
365
366         debug("Unknown hash algorithm '%s'\n", algo_name);
367         return -EPROTONOSUPPORT;
368 }
369
370 int hash_progressive_lookup_algo(const char *algo_name,
371                                  struct hash_algo **algop)
372 {
373         int i;
374
375         reloc_update();
376
377         for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
378                 if (!strcmp(algo_name, hash_algo[i].name)) {
379                         if (hash_algo[i].hash_init) {
380                                 *algop = &hash_algo[i];
381                                 return 0;
382                         }
383                 }
384         }
385
386         debug("Unknown hash algorithm '%s'\n", algo_name);
387         return -EPROTONOSUPPORT;
388 }
389
390 #ifndef USE_HOSTCC
391 int hash_parse_string(const char *algo_name, const char *str, uint8_t *result)
392 {
393         struct hash_algo *algo;
394         int ret;
395         int i;
396
397         ret = hash_lookup_algo(algo_name, &algo);
398         if (ret)
399                 return ret;
400
401         for (i = 0; i < algo->digest_size; i++) {
402                 char chr[3];
403
404                 strlcpy(chr, &str[i * 2], 3);
405                 result[i] = hextoul(chr, NULL);
406         }
407
408         return 0;
409 }
410
411 int hash_block(const char *algo_name, const void *data, unsigned int len,
412                uint8_t *output, int *output_size)
413 {
414         struct hash_algo *algo;
415         int ret;
416
417         ret = hash_lookup_algo(algo_name, &algo);
418         if (ret)
419                 return ret;
420
421         if (output_size && *output_size < algo->digest_size) {
422                 debug("Output buffer size %d too small (need %d bytes)",
423                       *output_size, algo->digest_size);
424                 return -ENOSPC;
425         }
426         if (output_size)
427                 *output_size = algo->digest_size;
428         algo->hash_func_ws(data, len, output, algo->chunk_size);
429
430         return 0;
431 }
432
433 #if !defined(CONFIG_SPL_BUILD) && (defined(CONFIG_CMD_HASH) || \
434         defined(CONFIG_CMD_SHA1SUM) || defined(CONFIG_CMD_CRC32))
435 /**
436  * store_result: Store the resulting sum to an address or variable
437  *
438  * @algo:               Hash algorithm being used
439  * @sum:                Hash digest (algo->digest_size bytes)
440  * @dest:               Destination, interpreted as a hex address if it starts
441  *                      with * (or allow_env_vars is 0) or otherwise as an
442  *                      environment variable.
443  * @allow_env_vars:     non-zero to permit storing the result to an
444  *                      variable environment
445  */
446 static void store_result(struct hash_algo *algo, const uint8_t *sum,
447                          const char *dest, int allow_env_vars)
448 {
449         unsigned int i;
450         int env_var = 0;
451
452         /*
453          * If environment variables are allowed, then we assume that 'dest'
454          * is an environment variable, unless it starts with *, in which
455          * case we assume it is an address. If not allowed, it is always an
456          * address. This is to support the crc32 command.
457          */
458         if (allow_env_vars) {
459                 if (*dest == '*')
460                         dest++;
461                 else
462                         env_var = 1;
463         }
464
465         if (env_var) {
466                 char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1];
467                 char *str_ptr = str_output;
468
469                 for (i = 0; i < algo->digest_size; i++) {
470                         sprintf(str_ptr, "%02x", sum[i]);
471                         str_ptr += 2;
472                 }
473                 *str_ptr = '\0';
474                 env_set(dest, str_output);
475         } else {
476                 ulong addr;
477                 void *buf;
478
479                 addr = hextoul(dest, NULL);
480                 buf = map_sysmem(addr, algo->digest_size);
481                 memcpy(buf, sum, algo->digest_size);
482                 unmap_sysmem(buf);
483         }
484 }
485
486 /**
487  * parse_verify_sum: Parse a hash verification parameter
488  *
489  * @algo:               Hash algorithm being used
490  * @verify_str:         Argument to parse. If it starts with * then it is
491  *                      interpreted as a hex address containing the hash.
492  *                      If the length is exactly the right number of hex digits
493  *                      for the digest size, then we assume it is a hex digest.
494  *                      Otherwise we assume it is an environment variable, and
495  *                      look up its value (it must contain a hex digest).
496  * @vsum:               Returns binary digest value (algo->digest_size bytes)
497  * @allow_env_vars:     non-zero to permit storing the result to an environment
498  *                      variable. If 0 then verify_str is assumed to be an
499  *                      address, and the * prefix is not expected.
500  * @return 0 if ok, non-zero on error
501  */
502 static int parse_verify_sum(struct hash_algo *algo, char *verify_str,
503                             uint8_t *vsum, int allow_env_vars)
504 {
505         int env_var = 0;
506
507         /* See comment above in store_result() */
508         if (allow_env_vars) {
509                 if (*verify_str == '*')
510                         verify_str++;
511                 else
512                         env_var = 1;
513         }
514
515         if (!env_var) {
516                 ulong addr;
517                 void *buf;
518
519                 addr = hextoul(verify_str, NULL);
520                 buf = map_sysmem(addr, algo->digest_size);
521                 memcpy(vsum, buf, algo->digest_size);
522         } else {
523                 char *vsum_str;
524                 int digits = algo->digest_size * 2;
525
526                 /*
527                  * As with the original code from sha1sum.c, we assume that a
528                  * string which matches the digest size exactly is a hex
529                  * string and not an environment variable.
530                  */
531                 if (strlen(verify_str) == digits)
532                         vsum_str = verify_str;
533                 else {
534                         vsum_str = env_get(verify_str);
535                         if (vsum_str == NULL || strlen(vsum_str) != digits) {
536                                 printf("Expected %d hex digits in env var\n",
537                                        digits);
538                                 return 1;
539                         }
540                 }
541
542                 hash_parse_string(algo->name, vsum_str, vsum);
543         }
544         return 0;
545 }
546
547 static void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output)
548 {
549         int i;
550
551         printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1);
552         for (i = 0; i < algo->digest_size; i++)
553                 printf("%02x", output[i]);
554 }
555
556 int hash_command(const char *algo_name, int flags, struct cmd_tbl *cmdtp,
557                  int flag, int argc, char *const argv[])
558 {
559         ulong addr, len;
560
561         if ((argc < 2) || ((flags & HASH_FLAG_VERIFY) && (argc < 3)))
562                 return CMD_RET_USAGE;
563
564         addr = hextoul(*argv++, NULL);
565         len = hextoul(*argv++, NULL);
566
567         if (multi_hash()) {
568                 struct hash_algo *algo;
569                 u8 *output;
570                 uint8_t vsum[HASH_MAX_DIGEST_SIZE];
571                 void *buf;
572
573                 if (hash_lookup_algo(algo_name, &algo)) {
574                         printf("Unknown hash algorithm '%s'\n", algo_name);
575                         return CMD_RET_USAGE;
576                 }
577                 argc -= 2;
578
579                 if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
580                         puts("HASH_MAX_DIGEST_SIZE exceeded\n");
581                         return 1;
582                 }
583
584                 output = memalign(ARCH_DMA_MINALIGN,
585                                   sizeof(uint32_t) * HASH_MAX_DIGEST_SIZE);
586
587                 buf = map_sysmem(addr, len);
588                 algo->hash_func_ws(buf, len, output, algo->chunk_size);
589                 unmap_sysmem(buf);
590
591                 /* Try to avoid code bloat when verify is not needed */
592 #if defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_SHA1SUM_VERIFY) || \
593         defined(CONFIG_HASH_VERIFY)
594                 if (flags & HASH_FLAG_VERIFY) {
595 #else
596                 if (0) {
597 #endif
598                         if (parse_verify_sum(algo, *argv, vsum,
599                                         flags & HASH_FLAG_ENV)) {
600                                 printf("ERROR: %s does not contain a valid "
601                                         "%s sum\n", *argv, algo->name);
602                                 return 1;
603                         }
604                         if (memcmp(output, vsum, algo->digest_size) != 0) {
605                                 int i;
606
607                                 hash_show(algo, addr, len, output);
608                                 printf(" != ");
609                                 for (i = 0; i < algo->digest_size; i++)
610                                         printf("%02x", vsum[i]);
611                                 puts(" ** ERROR **\n");
612                                 return 1;
613                         }
614                 } else {
615                         hash_show(algo, addr, len, output);
616                         printf("\n");
617
618                         if (argc) {
619                                 store_result(algo, output, *argv,
620                                         flags & HASH_FLAG_ENV);
621                         }
622                 unmap_sysmem(output);
623
624                 }
625
626         /* Horrible code size hack for boards that just want crc32 */
627         } else {
628                 ulong crc;
629                 ulong *ptr;
630
631                 crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32);
632
633                 printf("CRC32 for %08lx ... %08lx ==> %08lx\n",
634                                 addr, addr + len - 1, crc);
635
636                 if (argc >= 3) {
637                         ptr = (ulong *)hextoul(argv[0], NULL);
638                         *ptr = crc;
639                 }
640         }
641
642         return 0;
643 }
644 #endif /* CONFIG_CMD_HASH || CONFIG_CMD_SHA1SUM || CONFIG_CMD_CRC32) */
645 #endif /* !USE_HOSTCC */