xref: /openbmc/u-boot/common/hash.c (revision 83bf0057)
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 <asm/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 #if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM)
182 #define MULTI_HASH
183 #endif
184 
185 #if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH)
186 #define MULTI_HASH
187 #endif
188 
189 /* Try to minimize code size for boards that don't want much hashing */
190 #ifdef MULTI_HASH
191 #define multi_hash()	1
192 #else
193 #define multi_hash()	0
194 #endif
195 
196 int hash_lookup_algo(const char *algo_name, struct hash_algo **algop)
197 {
198 	int i;
199 
200 	for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
201 		if (!strcmp(algo_name, hash_algo[i].name)) {
202 			*algop = &hash_algo[i];
203 			return 0;
204 		}
205 	}
206 
207 	debug("Unknown hash algorithm '%s'\n", algo_name);
208 	return -EPROTONOSUPPORT;
209 }
210 
211 int hash_progressive_lookup_algo(const char *algo_name,
212 				 struct hash_algo **algop)
213 {
214 	int i;
215 
216 	for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
217 		if (!strcmp(algo_name, hash_algo[i].name)) {
218 			if (hash_algo[i].hash_init) {
219 				*algop = &hash_algo[i];
220 				return 0;
221 			}
222 		}
223 	}
224 
225 	debug("Unknown hash algorithm '%s'\n", algo_name);
226 	return -EPROTONOSUPPORT;
227 }
228 
229 #ifndef USE_HOSTCC
230 int hash_parse_string(const char *algo_name, const char *str, uint8_t *result)
231 {
232 	struct hash_algo *algo;
233 	int ret;
234 	int i;
235 
236 	ret = hash_lookup_algo(algo_name, &algo);
237 	if (ret)
238 		return ret;
239 
240 	for (i = 0; i < algo->digest_size; i++) {
241 		char chr[3];
242 
243 		strncpy(chr, &str[i * 2], 2);
244 		result[i] = simple_strtoul(chr, NULL, 16);
245 	}
246 
247 	return 0;
248 }
249 
250 /**
251  * store_result: Store the resulting sum to an address or variable
252  *
253  * @algo:		Hash algorithm being used
254  * @sum:		Hash digest (algo->digest_size bytes)
255  * @dest:		Destination, interpreted as a hex address if it starts
256  *			with * (or allow_env_vars is 0) or otherwise as an
257  *			environment variable.
258  * @allow_env_vars:	non-zero to permit storing the result to an
259  *			variable environment
260  */
261 static void store_result(struct hash_algo *algo, const uint8_t *sum,
262 			 const char *dest, int allow_env_vars)
263 {
264 	unsigned int i;
265 	int env_var = 0;
266 
267 	/*
268 	 * If environment variables are allowed, then we assume that 'dest'
269 	 * is an environment variable, unless it starts with *, in which
270 	 * case we assume it is an address. If not allowed, it is always an
271 	 * address. This is to support the crc32 command.
272 	 */
273 	if (allow_env_vars) {
274 		if (*dest == '*')
275 			dest++;
276 		else
277 			env_var = 1;
278 	}
279 
280 	if (env_var) {
281 		char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1];
282 		char *str_ptr = str_output;
283 
284 		for (i = 0; i < algo->digest_size; i++) {
285 			sprintf(str_ptr, "%02x", sum[i]);
286 			str_ptr += 2;
287 		}
288 		*str_ptr = '\0';
289 		setenv(dest, str_output);
290 	} else {
291 		ulong addr;
292 		void *buf;
293 
294 		addr = simple_strtoul(dest, NULL, 16);
295 		buf = map_sysmem(addr, algo->digest_size);
296 		memcpy(buf, sum, algo->digest_size);
297 		unmap_sysmem(buf);
298 	}
299 }
300 
301 /**
302  * parse_verify_sum: Parse a hash verification parameter
303  *
304  * @algo:		Hash algorithm being used
305  * @verify_str:		Argument to parse. If it starts with * then it is
306  *			interpreted as a hex address containing the hash.
307  *			If the length is exactly the right number of hex digits
308  *			for the digest size, then we assume it is a hex digest.
309  *			Otherwise we assume it is an environment variable, and
310  *			look up its value (it must contain a hex digest).
311  * @vsum:		Returns binary digest value (algo->digest_size bytes)
312  * @allow_env_vars:	non-zero to permit storing the result to an environment
313  *			variable. If 0 then verify_str is assumed to be an
314  *			address, and the * prefix is not expected.
315  * @return 0 if ok, non-zero on error
316  */
317 static int parse_verify_sum(struct hash_algo *algo, char *verify_str,
318 			    uint8_t *vsum, int allow_env_vars)
319 {
320 	int env_var = 0;
321 
322 	/* See comment above in store_result() */
323 	if (allow_env_vars) {
324 		if (*verify_str == '*')
325 			verify_str++;
326 		else
327 			env_var = 1;
328 	}
329 
330 	if (!env_var) {
331 		ulong addr;
332 		void *buf;
333 
334 		addr = simple_strtoul(verify_str, NULL, 16);
335 		buf = map_sysmem(addr, algo->digest_size);
336 		memcpy(vsum, buf, algo->digest_size);
337 	} else {
338 		char *vsum_str;
339 		int digits = algo->digest_size * 2;
340 
341 		/*
342 		 * As with the original code from sha1sum.c, we assume that a
343 		 * string which matches the digest size exactly is a hex
344 		 * string and not an environment variable.
345 		 */
346 		if (strlen(verify_str) == digits)
347 			vsum_str = verify_str;
348 		else {
349 			vsum_str = getenv(verify_str);
350 			if (vsum_str == NULL || strlen(vsum_str) != digits) {
351 				printf("Expected %d hex digits in env var\n",
352 				       digits);
353 				return 1;
354 			}
355 		}
356 
357 		hash_parse_string(algo->name, vsum_str, vsum);
358 	}
359 	return 0;
360 }
361 
362 void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output)
363 {
364 	int i;
365 
366 	printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1);
367 	for (i = 0; i < algo->digest_size; i++)
368 		printf("%02x", output[i]);
369 }
370 
371 int hash_block(const char *algo_name, const void *data, unsigned int len,
372 	       uint8_t *output, int *output_size)
373 {
374 	struct hash_algo *algo;
375 	int ret;
376 
377 	ret = hash_lookup_algo(algo_name, &algo);
378 	if (ret)
379 		return ret;
380 
381 	if (output_size && *output_size < algo->digest_size) {
382 		debug("Output buffer size %d too small (need %d bytes)",
383 		      *output_size, algo->digest_size);
384 		return -ENOSPC;
385 	}
386 	if (output_size)
387 		*output_size = algo->digest_size;
388 	algo->hash_func_ws(data, len, output, algo->chunk_size);
389 
390 	return 0;
391 }
392 
393 int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
394 		 int argc, char * const argv[])
395 {
396 	ulong addr, len;
397 
398 	if ((argc < 2) || ((flags & HASH_FLAG_VERIFY) && (argc < 3)))
399 		return CMD_RET_USAGE;
400 
401 	addr = simple_strtoul(*argv++, NULL, 16);
402 	len = simple_strtoul(*argv++, NULL, 16);
403 
404 	if (multi_hash()) {
405 		struct hash_algo *algo;
406 		uint8_t output[HASH_MAX_DIGEST_SIZE];
407 		uint8_t vsum[HASH_MAX_DIGEST_SIZE];
408 		void *buf;
409 
410 		if (hash_lookup_algo(algo_name, &algo)) {
411 			printf("Unknown hash algorithm '%s'\n", algo_name);
412 			return CMD_RET_USAGE;
413 		}
414 		argc -= 2;
415 
416 		if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
417 			puts("HASH_MAX_DIGEST_SIZE exceeded\n");
418 			return 1;
419 		}
420 
421 		buf = map_sysmem(addr, len);
422 		algo->hash_func_ws(buf, len, output, algo->chunk_size);
423 		unmap_sysmem(buf);
424 
425 		/* Try to avoid code bloat when verify is not needed */
426 #ifdef CONFIG_HASH_VERIFY
427 		if (flags & HASH_FLAG_VERIFY) {
428 #else
429 		if (0) {
430 #endif
431 			if (parse_verify_sum(algo, *argv, vsum,
432 					flags & HASH_FLAG_ENV)) {
433 				printf("ERROR: %s does not contain a valid "
434 					"%s sum\n", *argv, algo->name);
435 				return 1;
436 			}
437 			if (memcmp(output, vsum, algo->digest_size) != 0) {
438 				int i;
439 
440 				hash_show(algo, addr, len, output);
441 				printf(" != ");
442 				for (i = 0; i < algo->digest_size; i++)
443 					printf("%02x", vsum[i]);
444 				puts(" ** ERROR **\n");
445 				return 1;
446 			}
447 		} else {
448 			hash_show(algo, addr, len, output);
449 			printf("\n");
450 
451 			if (argc) {
452 				store_result(algo, output, *argv,
453 					flags & HASH_FLAG_ENV);
454 			}
455 		}
456 
457 	/* Horrible code size hack for boards that just want crc32 */
458 	} else {
459 		ulong crc;
460 		ulong *ptr;
461 
462 		crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32);
463 
464 		printf("CRC32 for %08lx ... %08lx ==> %08lx\n",
465 				addr, addr + len - 1, crc);
466 
467 		if (argc >= 3) {
468 			ptr = (ulong *)simple_strtoul(argv[0], NULL, 16);
469 			*ptr = crc;
470 		}
471 	}
472 
473 	return 0;
474 }
475 #endif
476