• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013, Google Inc.
4  */
5 
6 #ifdef USE_HOSTCC
7 #include "mkimage.h"
8 #include <time.h>
9 #else
10 #include <common.h>
11 #include <malloc.h>
12 DECLARE_GLOBAL_DATA_PTR;
13 #endif /* !USE_HOSTCC*/
14 #include <image.h>
15 #include <u-boot/rsa.h>
16 #include <u-boot/rsa-checksum.h>
17 
18 #define IMAGE_MAX_HASHED_NODES		100
19 
20 #ifdef USE_HOSTCC
21 void *host_blob;
image_set_host_blob(void * blob)22 void image_set_host_blob(void *blob)
23 {
24 	host_blob = blob;
25 }
image_get_host_blob(void)26 void *image_get_host_blob(void)
27 {
28 	return host_blob;
29 }
30 #endif
31 
32 struct checksum_algo checksum_algos[] = {
33 	{
34 		.name = "sha1",
35 		.checksum_len = SHA1_SUM_LEN,
36 		.der_len = SHA1_DER_LEN,
37 		.der_prefix = sha1_der_prefix,
38 #if IMAGE_ENABLE_SIGN
39 		.calculate_sign = EVP_sha1,
40 #endif
41 		.calculate = hash_calculate,
42 	},
43 	{
44 		.name = "sha256",
45 		.checksum_len = SHA256_SUM_LEN,
46 		.der_len = SHA256_DER_LEN,
47 		.der_prefix = sha256_der_prefix,
48 #if IMAGE_ENABLE_SIGN
49 		.calculate_sign = EVP_sha256,
50 #endif
51 		.calculate = hash_calculate,
52 	}
53 
54 };
55 
56 struct crypto_algo crypto_algos[] = {
57 	{
58 		.name = "rsa2048",
59 		.key_len = RSA2048_BYTES,
60 		.sign = rsa_sign,
61 		.add_verify_data = rsa_add_verify_data,
62 		.verify = rsa_verify,
63 	},
64 	{
65 		.name = "rsa4096",
66 		.key_len = RSA4096_BYTES,
67 		.sign = rsa_sign,
68 		.add_verify_data = rsa_add_verify_data,
69 		.verify = rsa_verify,
70 	}
71 
72 };
73 
74 struct padding_algo padding_algos[] = {
75 	{
76 		.name = "pkcs-1.5",
77 		.verify = padding_pkcs_15_verify,
78 	},
79 #ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
80 	{
81 		.name = "pss",
82 		.verify = padding_pss_verify,
83 	}
84 #endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
85 };
86 
image_get_checksum_algo(const char * full_name)87 struct checksum_algo *image_get_checksum_algo(const char *full_name)
88 {
89 	int i;
90 	const char *name;
91 
92 #if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC)
93 	static bool done;
94 
95 	if (!done) {
96 		done = true;
97 		for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) {
98 			checksum_algos[i].name += gd->reloc_off;
99 #if IMAGE_ENABLE_SIGN
100 			checksum_algos[i].calculate_sign += gd->reloc_off;
101 #endif
102 			checksum_algos[i].calculate += gd->reloc_off;
103 		}
104 	}
105 #endif
106 
107 	for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) {
108 		name = checksum_algos[i].name;
109 		/* Make sure names match and next char is a comma */
110 		if (!strncmp(name, full_name, strlen(name)) &&
111 		    full_name[strlen(name)] == ',')
112 			return &checksum_algos[i];
113 	}
114 
115 	return NULL;
116 }
117 
image_get_crypto_algo(const char * full_name)118 struct crypto_algo *image_get_crypto_algo(const char *full_name)
119 {
120 	int i;
121 	const char *name;
122 
123 #if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC)
124 	static bool done;
125 
126 	if (!done) {
127 		done = true;
128 		for (i = 0; i < ARRAY_SIZE(crypto_algos); i++) {
129 			crypto_algos[i].name += gd->reloc_off;
130 			crypto_algos[i].sign += gd->reloc_off;
131 			crypto_algos[i].add_verify_data += gd->reloc_off;
132 			crypto_algos[i].verify += gd->reloc_off;
133 		}
134 	}
135 #endif
136 
137 	/* Move name to after the comma */
138 	name = strchr(full_name, ',');
139 	if (!name)
140 		return NULL;
141 	name += 1;
142 
143 	for (i = 0; i < ARRAY_SIZE(crypto_algos); i++) {
144 		if (!strcmp(crypto_algos[i].name, name))
145 			return &crypto_algos[i];
146 	}
147 
148 	return NULL;
149 }
150 
image_get_padding_algo(const char * name)151 struct padding_algo *image_get_padding_algo(const char *name)
152 {
153 	int i;
154 
155 	if (!name)
156 		return NULL;
157 
158 	for (i = 0; i < ARRAY_SIZE(padding_algos); i++) {
159 		if (!strcmp(padding_algos[i].name, name))
160 			return &padding_algos[i];
161 	}
162 
163 	return NULL;
164 }
165 
166 /**
167  * fit_region_make_list() - Make a list of image regions
168  *
169  * Given a list of fdt_regions, create a list of image_regions. This is a
170  * simple conversion routine since the FDT and image code use different
171  * structures.
172  *
173  * @fit: FIT image
174  * @fdt_regions: Pointer to FDT regions
175  * @count: Number of FDT regions
176  * @region: Pointer to image regions, which must hold @count records. If
177  * region is NULL, then (except for an SPL build) the array will be
178  * allocated.
179  * @return: Pointer to image regions
180  */
fit_region_make_list(const void * fit,struct fdt_region * fdt_regions,int count,struct image_region * region)181 struct image_region *fit_region_make_list(const void *fit,
182 		struct fdt_region *fdt_regions, int count,
183 		struct image_region *region)
184 {
185 	int i;
186 
187 	debug("Hash regions:\n");
188 	debug("%10s %10s\n", "Offset", "Size");
189 
190 	/*
191 	 * Use malloc() except in SPL (to save code size). In SPL the caller
192 	 * must allocate the array.
193 	 */
194 #ifndef CONFIG_SPL_BUILD
195 	if (!region)
196 		region = calloc(sizeof(*region), count);
197 #endif
198 	if (!region)
199 		return NULL;
200 	for (i = 0; i < count; i++) {
201 		debug("%10x %10x\n", fdt_regions[i].offset,
202 		      fdt_regions[i].size);
203 		region[i].data = fit + fdt_regions[i].offset;
204 		region[i].size = fdt_regions[i].size;
205 	}
206 
207 	return region;
208 }
209 
fit_image_setup_verify(struct image_sign_info * info,const void * fit,int noffset,int required_keynode,char ** err_msgp)210 static int fit_image_setup_verify(struct image_sign_info *info,
211 		const void *fit, int noffset, int required_keynode,
212 		char **err_msgp)
213 {
214 	char *algo_name;
215 	const char *padding_name;
216 
217 	if (fdt_totalsize(fit) > CONFIG_FIT_SIGNATURE_MAX_SIZE) {
218 		*err_msgp = "Total size too large";
219 		return 1;
220 	}
221 
222 	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
223 		*err_msgp = "Can't get hash algo property";
224 		return -1;
225 	}
226 
227 	padding_name = fdt_getprop(fit, noffset, "padding", NULL);
228 	if (!padding_name)
229 		padding_name = RSA_DEFAULT_PADDING_NAME;
230 
231 	memset(info, '\0', sizeof(*info));
232 	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
233 	info->fit = (void *)fit;
234 	info->node_offset = noffset;
235 	info->name = algo_name;
236 	info->checksum = image_get_checksum_algo(algo_name);
237 	info->crypto = image_get_crypto_algo(algo_name);
238 	info->padding = image_get_padding_algo(padding_name);
239 	info->fdt_blob = gd_fdt_blob();
240 	info->required_keynode = required_keynode;
241 	printf("%s:%s", algo_name, info->keyname);
242 
243 	if (!info->checksum || !info->crypto || !info->padding) {
244 		*err_msgp = "Unknown signature algorithm";
245 		return -1;
246 	}
247 
248 	return 0;
249 }
250 
fit_image_check_sig(const void * fit,int noffset,const void * data,size_t size,int required_keynode,char ** err_msgp)251 int fit_image_check_sig(const void *fit, int noffset, const void *data,
252 		size_t size, int required_keynode, char **err_msgp)
253 {
254 	struct image_sign_info info;
255 	struct image_region region;
256 	uint8_t *fit_value;
257 	int fit_value_len;
258 
259 	*err_msgp = NULL;
260 	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
261 				   err_msgp))
262 		return -1;
263 
264 	if (fit_image_hash_get_value(fit, noffset, &fit_value,
265 				     &fit_value_len)) {
266 		*err_msgp = "Can't get hash value property";
267 		return -1;
268 	}
269 
270 	region.data = data;
271 	region.size = size;
272 
273 	if (info.crypto->verify(&info, &region, 1, fit_value, fit_value_len)) {
274 		*err_msgp = "Verification failed";
275 		return -1;
276 	}
277 
278 	return 0;
279 }
280 
fit_image_verify_sig(const void * fit,int image_noffset,const char * data,size_t size,const void * sig_blob,int sig_offset)281 static int fit_image_verify_sig(const void *fit, int image_noffset,
282 		const char *data, size_t size, const void *sig_blob,
283 		int sig_offset)
284 {
285 	int noffset;
286 	char *err_msg = "";
287 	int verified = 0;
288 	int ret;
289 
290 	/* Process all hash subnodes of the component image node */
291 	fdt_for_each_subnode(noffset, fit, image_noffset) {
292 		const char *name = fit_get_name(fit, noffset, NULL);
293 
294 		if (!strncmp(name, FIT_SIG_NODENAME,
295 			     strlen(FIT_SIG_NODENAME))) {
296 			ret = fit_image_check_sig(fit, noffset, data,
297 							size, -1, &err_msg);
298 			if (ret) {
299 				puts("- ");
300 			} else {
301 				puts("+ ");
302 				verified = 1;
303 				break;
304 			}
305 		}
306 	}
307 
308 	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
309 		err_msg = "Corrupted or truncated tree";
310 		goto error;
311 	}
312 
313 	return verified ? 0 : -EPERM;
314 
315 error:
316 	printf(" error!\n%s for '%s' hash node in '%s' image node\n",
317 	       err_msg, fit_get_name(fit, noffset, NULL),
318 	       fit_get_name(fit, image_noffset, NULL));
319 	return -1;
320 }
321 
fit_image_verify_required_sigs(const void * fit,int image_noffset,const char * data,size_t size,const void * sig_blob,int * no_sigsp)322 int fit_image_verify_required_sigs(const void *fit, int image_noffset,
323 		const char *data, size_t size, const void *sig_blob,
324 		int *no_sigsp)
325 {
326 	int verify_count = 0;
327 	int noffset;
328 	int sig_node;
329 
330 	/* Work out what we need to verify */
331 	*no_sigsp = 1;
332 	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
333 	if (sig_node < 0) {
334 		debug("%s: No signature node found: %s\n", __func__,
335 		      fdt_strerror(sig_node));
336 		return 0;
337 	}
338 
339 	fdt_for_each_subnode(noffset, sig_blob, sig_node) {
340 		const char *required;
341 		int ret;
342 
343 		required = fdt_getprop(sig_blob, noffset, "required", NULL);
344 		if (!required || strcmp(required, "image"))
345 			continue;
346 		ret = fit_image_verify_sig(fit, image_noffset, data, size,
347 					sig_blob, noffset);
348 		if (ret) {
349 			printf("Failed to verify required signature '%s'\n",
350 			       fit_get_name(sig_blob, noffset, NULL));
351 			return ret;
352 		}
353 		verify_count++;
354 	}
355 
356 	if (verify_count)
357 		*no_sigsp = 0;
358 
359 	return 0;
360 }
361 
fit_config_check_sig(const void * fit,int noffset,int required_keynode,char ** err_msgp)362 int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
363 			 char **err_msgp)
364 {
365 	char * const exc_prop[] = {"data"};
366 	const char *prop, *end, *name;
367 	struct image_sign_info info;
368 	const uint32_t *strings;
369 	uint8_t *fit_value;
370 	int fit_value_len;
371 	int max_regions;
372 	int i, prop_len;
373 	char path[200];
374 	int count;
375 
376 	debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
377 	      fit_get_name(fit, noffset, NULL),
378 	      fit_get_name(gd_fdt_blob(), required_keynode, NULL));
379 	*err_msgp = NULL;
380 	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
381 				   err_msgp))
382 		return -1;
383 
384 	if (fit_image_hash_get_value(fit, noffset, &fit_value,
385 				     &fit_value_len)) {
386 		*err_msgp = "Can't get hash value property";
387 		return -1;
388 	}
389 
390 	/* Count the number of strings in the property */
391 	prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
392 	end = prop ? prop + prop_len : prop;
393 	for (name = prop, count = 0; name < end; name++)
394 		if (!*name)
395 			count++;
396 	if (!count) {
397 		*err_msgp = "Can't get hashed-nodes property";
398 		return -1;
399 	}
400 
401 	if (prop && prop_len > 0 && prop[prop_len - 1] != '\0') {
402 		*err_msgp = "hashed-nodes property must be null-terminated";
403 		return -1;
404 	}
405 
406 	/* Add a sanity check here since we are using the stack */
407 	if (count > IMAGE_MAX_HASHED_NODES) {
408 		*err_msgp = "Number of hashed nodes exceeds maximum";
409 		return -1;
410 	}
411 
412 	/* Create a list of node names from those strings */
413 	char *node_inc[count];
414 
415 	debug("Hash nodes (%d):\n", count);
416 	for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
417 		debug("   '%s'\n", name);
418 		node_inc[i] = (char *)name;
419 	}
420 
421 	/*
422 	 * Each node can generate one region for each sub-node. Allow for
423 	 * 7 sub-nodes (hash-1, signature-1, etc.) and some extra.
424 	 */
425 	max_regions = 20 + count * 7;
426 	struct fdt_region fdt_regions[max_regions];
427 
428 	/* Get a list of regions to hash */
429 	count = fdt_find_regions(fit, node_inc, count,
430 			exc_prop, ARRAY_SIZE(exc_prop),
431 			fdt_regions, max_regions - 1,
432 			path, sizeof(path), 0);
433 	if (count < 0) {
434 		*err_msgp = "Failed to hash configuration";
435 		return -1;
436 	}
437 	if (count == 0) {
438 		*err_msgp = "No data to hash";
439 		return -1;
440 	}
441 	if (count >= max_regions - 1) {
442 		*err_msgp = "Too many hash regions";
443 		return -1;
444 	}
445 
446 	/* Add the strings */
447 	strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
448 	if (strings) {
449 		/*
450 		 * The strings region offset must be a static 0x0.
451 		 * This is set in tool/image-host.c
452 		 */
453 		fdt_regions[count].offset = fdt_off_dt_strings(fit);
454 		fdt_regions[count].size = fdt32_to_cpu(strings[1]);
455 		count++;
456 	}
457 
458 	/* Allocate the region list on the stack */
459 	struct image_region region[count];
460 
461 	fit_region_make_list(fit, fdt_regions, count, region);
462 	if (info.crypto->verify(&info, region, count, fit_value,
463 				fit_value_len)) {
464 		*err_msgp = "Verification failed";
465 		return -1;
466 	}
467 
468 	return 0;
469 }
470 
fit_config_verify_sig(const void * fit,int conf_noffset,const void * sig_blob,int sig_offset)471 static int fit_config_verify_sig(const void *fit, int conf_noffset,
472 		const void *sig_blob, int sig_offset)
473 {
474 	int noffset;
475 	char *err_msg = "";
476 	int verified = 0;
477 	int ret;
478 
479 	/* Process all hash subnodes of the component conf node */
480 	fdt_for_each_subnode(noffset, fit, conf_noffset) {
481 		const char *name = fit_get_name(fit, noffset, NULL);
482 
483 		if (!strncmp(name, FIT_SIG_NODENAME,
484 			     strlen(FIT_SIG_NODENAME))) {
485 			ret = fit_config_check_sig(fit, noffset, sig_offset,
486 						   &err_msg);
487 			if (ret) {
488 				puts("- ");
489 			} else {
490 				puts("+ ");
491 				verified = 1;
492 				break;
493 			}
494 		}
495 	}
496 
497 	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
498 		err_msg = "Corrupted or truncated tree";
499 		goto error;
500 	}
501 
502 	return verified ? 0 : -EPERM;
503 
504 error:
505 	printf(" error!\n%s for '%s' hash node in '%s' config node\n",
506 	       err_msg, fit_get_name(fit, noffset, NULL),
507 	       fit_get_name(fit, conf_noffset, NULL));
508 	return -1;
509 }
510 
fit_config_verify_required_sigs(const void * fit,int conf_noffset,const void * sig_blob)511 int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
512 		const void *sig_blob)
513 {
514 	int noffset;
515 	int sig_node;
516 
517 	/* Work out what we need to verify */
518 	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
519 	if (sig_node < 0) {
520 		debug("%s: No signature node found: %s\n", __func__,
521 		      fdt_strerror(sig_node));
522 		return 0;
523 	}
524 
525 	fdt_for_each_subnode(noffset, sig_blob, sig_node) {
526 		const char *required;
527 		int ret;
528 
529 		required = fdt_getprop(sig_blob, noffset, "required", NULL);
530 		if (!required || strcmp(required, "conf"))
531 			continue;
532 		ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
533 					    noffset);
534 		if (ret) {
535 			printf("Failed to verify required signature '%s'\n",
536 			       fit_get_name(sig_blob, noffset, NULL));
537 			return ret;
538 		}
539 	}
540 
541 	return 0;
542 }
543 
fit_config_verify(const void * fit,int conf_noffset)544 int fit_config_verify(const void *fit, int conf_noffset)
545 {
546 	return fit_config_verify_required_sigs(fit, conf_noffset,
547 					       gd_fdt_blob());
548 }
549