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 <log.h>
12 #include <malloc.h>
13 #include <asm/global_data.h>
14 DECLARE_GLOBAL_DATA_PTR;
15 #endif /* !USE_HOSTCC*/
16 #include <fdt_region.h>
17 #include <image.h>
18 #include <u-boot/rsa.h>
19 #include <u-boot/hash-checksum.h>
20 
21 #define IMAGE_MAX_HASHED_NODES		100
22 
23 /**
24  * fit_region_make_list() - Make a list of image regions
25  *
26  * Given a list of fdt_regions, create a list of image_regions. This is a
27  * simple conversion routine since the FDT and image code use different
28  * structures.
29  *
30  * @fit: FIT image
31  * @fdt_regions: Pointer to FDT regions
32  * @count: Number of FDT regions
33  * @region: Pointer to image regions, which must hold @count records. If
34  * region is NULL, then (except for an SPL build) the array will be
35  * allocated.
36  * @return: Pointer to image regions
37  */
fit_region_make_list(const void * fit,struct fdt_region * fdt_regions,int count,struct image_region * region)38 struct image_region *fit_region_make_list(const void *fit,
39 					  struct fdt_region *fdt_regions,
40 					  int count,
41 					  struct image_region *region)
42 {
43 	int i;
44 
45 	debug("Hash regions:\n");
46 	debug("%10s %10s\n", "Offset", "Size");
47 
48 	/*
49 	 * Use malloc() except in SPL (to save code size). In SPL the caller
50 	 * must allocate the array.
51 	 */
52 	if (!IS_ENABLED(CONFIG_SPL_BUILD) && !region)
53 		region = calloc(sizeof(*region), count);
54 	if (!region)
55 		return NULL;
56 	for (i = 0; i < count; i++) {
57 		debug("%10x %10x\n", fdt_regions[i].offset,
58 		      fdt_regions[i].size);
59 		region[i].data = fit + fdt_regions[i].offset;
60 		region[i].size = fdt_regions[i].size;
61 	}
62 
63 	return region;
64 }
65 
fit_image_setup_verify(struct image_sign_info * info,const void * fit,int noffset,const void * key_blob,int required_keynode,char ** err_msgp)66 static int fit_image_setup_verify(struct image_sign_info *info,
67 				  const void *fit, int noffset,
68 				  const void *key_blob, int required_keynode,
69 				  char **err_msgp)
70 {
71 	const char *algo_name;
72 	const char *padding_name;
73 
74 	if (fdt_totalsize(fit) > CONFIG_VAL(FIT_SIGNATURE_MAX_SIZE)) {
75 		*err_msgp = "Total size too large";
76 		return 1;
77 	}
78 	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
79 		*err_msgp = "Can't get hash algo property";
80 		return -1;
81 	}
82 
83 	padding_name = fdt_getprop(fit, noffset, "padding", NULL);
84 	if (!padding_name)
85 		padding_name = RSA_DEFAULT_PADDING_NAME;
86 
87 	memset(info, '\0', sizeof(*info));
88 	info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
89 	info->fit = fit;
90 	info->node_offset = noffset;
91 	info->name = algo_name;
92 	info->checksum = image_get_checksum_algo(algo_name);
93 	info->crypto = image_get_crypto_algo(algo_name);
94 	info->padding = image_get_padding_algo(padding_name);
95 	info->fdt_blob = key_blob;
96 	info->required_keynode = required_keynode;
97 	printf("%s:%s", algo_name, info->keyname);
98 
99 	if (!info->checksum || !info->crypto || !info->padding) {
100 		*err_msgp = "Unknown signature algorithm";
101 		return -1;
102 	}
103 
104 	return 0;
105 }
106 
fit_image_check_sig(const void * fit,int noffset,const void * data,size_t size,const void * key_blob,int required_keynode,char ** err_msgp)107 int fit_image_check_sig(const void *fit, int noffset, const void *data,
108 			size_t size, const void *key_blob, int required_keynode,
109 			char **err_msgp)
110 {
111 	struct image_sign_info info;
112 	struct image_region region;
113 	uint8_t *fit_value;
114 	int fit_value_len;
115 
116 	*err_msgp = NULL;
117 	if (fit_image_setup_verify(&info, fit, noffset, key_blob,
118 				   required_keynode, err_msgp))
119 		return -1;
120 
121 	if (fit_image_hash_get_value(fit, noffset, &fit_value,
122 				     &fit_value_len)) {
123 		*err_msgp = "Can't get hash value property";
124 		return -1;
125 	}
126 
127 	region.data = data;
128 	region.size = size;
129 
130 	if (info.crypto->verify(&info, &region, 1, fit_value, fit_value_len)) {
131 		*err_msgp = "Verification failed";
132 		return -1;
133 	}
134 
135 	return 0;
136 }
137 
fit_image_verify_sig(const void * fit,int image_noffset,const char * data,size_t size,const void * key_blob,int key_offset)138 static int fit_image_verify_sig(const void *fit, int image_noffset,
139 				const char *data, size_t size,
140 				const void *key_blob, int key_offset)
141 {
142 	int noffset;
143 	char *err_msg = "";
144 	int verified = 0;
145 	int ret;
146 
147 	/* Process all hash subnodes of the component image node */
148 	fdt_for_each_subnode(noffset, fit, image_noffset) {
149 		const char *name = fit_get_name(fit, noffset, NULL);
150 
151 		/*
152 		 * We don't support this since libfdt considers names with the
153 		 * name root but different @ suffix to be equal
154 		 */
155 		if (strchr(name, '@')) {
156 			err_msg = "Node name contains @";
157 			goto error;
158 		}
159 		if (!strncmp(name, FIT_SIG_NODENAME,
160 			     strlen(FIT_SIG_NODENAME))) {
161 			ret = fit_image_check_sig(fit, noffset, data, size,
162 						  key_blob, -1, &err_msg);
163 			if (ret) {
164 				puts("- ");
165 			} else {
166 				puts("+ ");
167 				verified = 1;
168 				break;
169 			}
170 		}
171 	}
172 
173 	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
174 		err_msg = "Corrupted or truncated tree";
175 		goto error;
176 	}
177 
178 	return verified ? 0 : -EPERM;
179 
180 error:
181 	printf(" error!\n%s for '%s' hash node in '%s' image node\n",
182 	       err_msg, fit_get_name(fit, noffset, NULL),
183 	       fit_get_name(fit, image_noffset, NULL));
184 	return -1;
185 }
186 
fit_image_verify_required_sigs(const void * fit,int image_noffset,const char * data,size_t size,const void * key_blob,int * no_sigsp)187 int fit_image_verify_required_sigs(const void *fit, int image_noffset,
188 				   const char *data, size_t size,
189 				   const void *key_blob, int *no_sigsp)
190 {
191 	int verify_count = 0;
192 	int noffset;
193 	int key_node;
194 
195 	/* Work out what we need to verify */
196 	*no_sigsp = 1;
197 	key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME);
198 	if (key_node < 0) {
199 		debug("%s: No signature node found: %s\n", __func__,
200 		      fdt_strerror(key_node));
201 		return 0;
202 	}
203 
204 	fdt_for_each_subnode(noffset, key_blob, key_node) {
205 		const char *required;
206 		int ret;
207 
208 		required = fdt_getprop(key_blob, noffset, FIT_KEY_REQUIRED,
209 				       NULL);
210 		if (!required || strcmp(required, "image"))
211 			continue;
212 		ret = fit_image_verify_sig(fit, image_noffset, data, size,
213 					   key_blob, noffset);
214 		if (ret) {
215 			printf("Failed to verify required signature '%s'\n",
216 			       fit_get_name(key_blob, noffset, NULL));
217 			return ret;
218 		}
219 		verify_count++;
220 	}
221 
222 	if (verify_count)
223 		*no_sigsp = 0;
224 
225 	return 0;
226 }
227 
228 /**
229  * fit_config_check_sig() - Check the signature of a config
230  *
231  * Here we are looking at a particular signature that needs verification (here
232  * signature-1):
233  *
234  *	configurations {
235  *		default = "conf-1";
236  *		conf-1 {
237  *			kernel = "kernel-1";
238  *			fdt = "fdt-1";
239  *			signature-1 {
240  *				algo = "sha1,rsa2048";
241  *				value = <...conf 1 signature...>;
242  *			};
243  *		};
244  *
245  * @fit: FIT to check
246  * @noffset: Offset of the signature node being checked (e.g.
247  *	 /configurations/conf-1/signature-1)
248  * @conf_noffset: Offset of configuration node (e.g. /configurations/conf-1)
249  * @key_blob: Blob containing the keys to check against
250  * @required_keynode:	Offset in @key_blob of the required key node,
251  *			if any. If this is given, then the configuration wil not
252  *			pass verification unless that key is used. If this is
253  *			-1 then any signature will do.
254  * @err_msgp:		In the event of an error, this will be pointed to a
255  *			help error string to display to the user.
256  * Return: 0 if all verified ok, <0 on error
257  */
fit_config_check_sig(const void * fit,int noffset,int conf_noffset,const void * key_blob,int required_keynode,char ** err_msgp)258 static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset,
259 				const void *key_blob, int required_keynode,
260 				char **err_msgp)
261 {
262 	static char * const exc_prop[] = {
263 		FIT_DATA_PROP,
264 		FIT_DATA_SIZE_PROP,
265 		FIT_DATA_POSITION_PROP,
266 		FIT_DATA_OFFSET_PROP,
267 	};
268 
269 	const char *prop, *end, *name;
270 	struct image_sign_info info;
271 	const uint32_t *strings;
272 	const char *config_name;
273 	uint8_t *fit_value;
274 	int fit_value_len;
275 	bool found_config;
276 	int max_regions;
277 	int i, prop_len;
278 	char path[200];
279 	int count;
280 
281 	config_name = fit_get_name(fit, conf_noffset, NULL);
282 	debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, key_blob,
283 	      fit_get_name(fit, noffset, NULL),
284 	      fit_get_name(key_blob, required_keynode, NULL));
285 	*err_msgp = NULL;
286 	if (fit_image_setup_verify(&info, fit, noffset, key_blob,
287 				   required_keynode, err_msgp))
288 		return -1;
289 
290 	if (fit_image_hash_get_value(fit, noffset, &fit_value,
291 				     &fit_value_len)) {
292 		*err_msgp = "Can't get hash value property";
293 		return -1;
294 	}
295 
296 	/* Count the number of strings in the property */
297 	prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
298 	end = prop ? prop + prop_len : prop;
299 	for (name = prop, count = 0; name < end; name++)
300 		if (!*name)
301 			count++;
302 	if (!count) {
303 		*err_msgp = "Can't get hashed-nodes property";
304 		return -1;
305 	}
306 
307 	if (prop && prop_len > 0 && prop[prop_len - 1] != '\0') {
308 		*err_msgp = "hashed-nodes property must be null-terminated";
309 		return -1;
310 	}
311 
312 	/* Add a sanity check here since we are using the stack */
313 	if (count > IMAGE_MAX_HASHED_NODES) {
314 		*err_msgp = "Number of hashed nodes exceeds maximum";
315 		return -1;
316 	}
317 
318 	/* Create a list of node names from those strings */
319 	char *node_inc[count];
320 
321 	debug("Hash nodes (%d):\n", count);
322 	found_config = false;
323 	for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
324 		debug("   '%s'\n", name);
325 		node_inc[i] = (char *)name;
326 		if (!strncmp(FIT_CONFS_PATH, name, strlen(FIT_CONFS_PATH)) &&
327 		    name[sizeof(FIT_CONFS_PATH) - 1] == '/' &&
328 		    !strcmp(name + sizeof(FIT_CONFS_PATH), config_name)) {
329 			debug("      (found config node %s)", config_name);
330 			found_config = true;
331 		}
332 	}
333 	if (!found_config) {
334 		*err_msgp = "Selected config not in hashed nodes";
335 		return -1;
336 	}
337 
338 	/*
339 	 * Each node can generate one region for each sub-node. Allow for
340 	 * 7 sub-nodes (hash-1, signature-1, etc.) and some extra.
341 	 */
342 	max_regions = 20 + count * 7;
343 	struct fdt_region fdt_regions[max_regions];
344 
345 	/* Get a list of regions to hash */
346 	count = fdt_find_regions(fit, node_inc, count,
347 				 exc_prop, ARRAY_SIZE(exc_prop),
348 				 fdt_regions, max_regions - 1,
349 				 path, sizeof(path), 0);
350 	if (count < 0) {
351 		*err_msgp = "Failed to hash configuration";
352 		return -1;
353 	}
354 	if (count == 0) {
355 		*err_msgp = "No data to hash";
356 		return -1;
357 	}
358 	if (count >= max_regions - 1) {
359 		*err_msgp = "Too many hash regions";
360 		return -1;
361 	}
362 
363 	/* Add the strings */
364 	strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
365 	if (strings) {
366 		/*
367 		 * The strings region offset must be a static 0x0.
368 		 * This is set in tool/image-host.c
369 		 */
370 		fdt_regions[count].offset = fdt_off_dt_strings(fit);
371 		fdt_regions[count].size = fdt32_to_cpu(strings[1]);
372 		count++;
373 	}
374 
375 	/* Allocate the region list on the stack */
376 	struct image_region region[count];
377 
378 	fit_region_make_list(fit, fdt_regions, count, region);
379 	if (info.crypto->verify(&info, region, count, fit_value,
380 				fit_value_len)) {
381 		*err_msgp = "Verification failed";
382 		return -1;
383 	}
384 
385 	return 0;
386 }
387 
388 /**
389  * fit_config_verify_key() - Verify that a configuration is signed with a key
390  *
391  * Here we are looking at a particular configuration that needs verification:
392  *
393  *	configurations {
394  *		default = "conf-1";
395  *		conf-1 {
396  *			kernel = "kernel-1";
397  *			fdt = "fdt-1";
398  *			signature-1 {
399  *				algo = "sha1,rsa2048";
400  *				value = <...conf 1 signature...>;
401  *			};
402  *		};
403  *
404  * We must check each of the signature subnodes of conf-1. Hopefully one of them
405  * will match the key at key_offset.
406  *
407  * @fit: FIT to check
408  * @conf_noffset: Offset of the configuration node to check (e.g.
409  *	/configurations/conf-1)
410  * @key_blob: Blob containing the keys to check against
411  * @key_offset: Offset of the key to check within @key_blob
412  * @return 0 if OK, -EPERM if any signatures did not verify, or the
413  *	configuration node has an invalid name
414  */
fit_config_verify_key(const void * fit,int conf_noffset,const void * key_blob,int key_offset)415 static int fit_config_verify_key(const void *fit, int conf_noffset,
416 				 const void *key_blob, int key_offset)
417 {
418 	int noffset;
419 	char *err_msg = "No 'signature' subnode found";
420 	int verified = 0;
421 	int ret;
422 
423 	/* Process all hash subnodes of the component conf node */
424 	fdt_for_each_subnode(noffset, fit, conf_noffset) {
425 		const char *name = fit_get_name(fit, noffset, NULL);
426 
427 		if (!strncmp(name, FIT_SIG_NODENAME,
428 			     strlen(FIT_SIG_NODENAME))) {
429 			ret = fit_config_check_sig(fit, noffset, conf_noffset,
430 						   key_blob, key_offset,
431 						   &err_msg);
432 			if (ret) {
433 				puts("- ");
434 			} else {
435 				puts("+ ");
436 				verified = 1;
437 				break;
438 			}
439 		}
440 	}
441 
442 	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
443 		err_msg = "Corrupted or truncated tree";
444 		goto error;
445 	}
446 
447 	if (verified)
448 		return 0;
449 
450 error:
451 	printf(" error!\n%s for '%s' hash node in '%s' config node\n",
452 	       err_msg, fit_get_name(fit, noffset, NULL),
453 	       fit_get_name(fit, conf_noffset, NULL));
454 	return -EPERM;
455 }
456 
457 /**
458  * fit_config_verify_required_keys() - verify any required signatures for config
459  *
460  * This looks through all the signatures we expect and verifies that at least
461  * all the required ones are valid signatures for the configuration
462  *
463  * @fit: FIT to check
464  * @conf_noffset: Offset of the configuration node to check (e.g.
465  *	/configurations/conf-1)
466  * @key_blob: Blob containing the keys to check against
467  * @return 0 if OK, -EPERM if any signatures did not verify, or the
468  *	configuration node has an invalid name
469  */
fit_config_verify_required_keys(const void * fit,int conf_noffset,const void * key_blob)470 static int fit_config_verify_required_keys(const void *fit, int conf_noffset,
471 					   const void *key_blob)
472 {
473 	const char *name = fit_get_name(fit, conf_noffset, NULL);
474 	int noffset;
475 	int key_node;
476 	int verified = 0;
477 	int reqd_sigs = 0;
478 	bool reqd_policy_all = true;
479 	const char *reqd_mode;
480 
481 	/*
482 	 * We don't support this since libfdt considers names with the
483 	 * name root but different @ suffix to be equal
484 	 */
485 	if (strchr(name, '@')) {
486 		printf("Configuration node '%s' contains '@'\n", name);
487 		return -EPERM;
488 	}
489 
490 	/* Work out what we need to verify */
491 	key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME);
492 	if (key_node < 0) {
493 		debug("%s: No signature node found: %s\n", __func__,
494 		      fdt_strerror(key_node));
495 		return 0;
496 	}
497 
498 	/* Get required-mode policy property from DTB */
499 	reqd_mode = fdt_getprop(key_blob, key_node, "required-mode", NULL);
500 	if (reqd_mode && !strcmp(reqd_mode, "any"))
501 		reqd_policy_all = false;
502 
503 	debug("%s: required-mode policy set to '%s'\n", __func__,
504 	      reqd_policy_all ? "all" : "any");
505 
506 	/*
507 	 * The algorithm here is a little convoluted due to how we want it to
508 	 * work. Here we work through each of the signature nodes in the
509 	 * public-key area. These are in the U-Boot control devicetree. Each
510 	 * node was created by signing a configuration, so we check if it is
511 	 * 'required' and if so, request that it be verified.
512 	 */
513 	fdt_for_each_subnode(noffset, key_blob, key_node) {
514 		const char *required;
515 		int ret;
516 
517 		required = fdt_getprop(key_blob, noffset, FIT_KEY_REQUIRED,
518 				       NULL);
519 		if (!required || strcmp(required, "conf"))
520 			continue;
521 
522 		reqd_sigs++;
523 
524 		ret = fit_config_verify_key(fit, conf_noffset, key_blob,
525 					    noffset);
526 		if (ret) {
527 			if (reqd_policy_all) {
528 				printf("Failed to verify required signature '%s'\n",
529 				       fit_get_name(key_blob, noffset, NULL));
530 				return ret;
531 			}
532 		} else {
533 			verified++;
534 			if (!reqd_policy_all)
535 				break;
536 		}
537 	}
538 
539 	if (reqd_sigs && !verified) {
540 		printf("Failed to verify 'any' of the required signature(s)\n");
541 		return -EPERM;
542 	}
543 
544 	return 0;
545 }
546 
fit_config_verify(const void * fit,int conf_noffset)547 int fit_config_verify(const void *fit, int conf_noffset)
548 {
549 	return fit_config_verify_required_keys(fit, conf_noffset,
550 					       gd_fdt_blob());
551 }
552