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