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