xref: /openbmc/u-boot/common/image-sig.c (revision f9727161)
1 /*
2  * Copyright (c) 2013, Google Inc.
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #ifdef USE_HOSTCC
8 #include "mkimage.h"
9 #include <time.h>
10 #else
11 #include <common.h>
12 #include <malloc.h>
13 DECLARE_GLOBAL_DATA_PTR;
14 #endif /* !USE_HOSTCC*/
15 #include <image.h>
16 #include <rsa.h>
17 
18 #define IMAGE_MAX_HASHED_NODES		100
19 
20 struct image_sig_algo image_sig_algos[] = {
21 	{
22 		"sha1,rsa2048",
23 		rsa_sign,
24 		rsa_add_verify_data,
25 		rsa_verify,
26 	}
27 };
28 
29 struct image_sig_algo *image_get_sig_algo(const char *name)
30 {
31 	int i;
32 
33 	for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) {
34 		if (!strcmp(image_sig_algos[i].name, name))
35 			return &image_sig_algos[i];
36 	}
37 
38 	return NULL;
39 }
40 
41 /**
42  * fit_region_make_list() - Make a list of image regions
43  *
44  * Given a list of fdt_regions, create a list of image_regions. This is a
45  * simple conversion routine since the FDT and image code use different
46  * structures.
47  *
48  * @fit: FIT image
49  * @fdt_regions: Pointer to FDT regions
50  * @count: Number of FDT regions
51  * @region: Pointer to image regions, which must hold @count records. If
52  * region is NULL, then (except for an SPL build) the array will be
53  * allocated.
54  * @return: Pointer to image regions
55  */
56 struct image_region *fit_region_make_list(const void *fit,
57 		struct fdt_region *fdt_regions, int count,
58 		struct image_region *region)
59 {
60 	int i;
61 
62 	debug("Hash regions:\n");
63 	debug("%10s %10s\n", "Offset", "Size");
64 
65 	/*
66 	 * Use malloc() except in SPL (to save code size). In SPL the caller
67 	 * must allocate the array.
68 	 */
69 #ifndef CONFIG_SPL_BUILD
70 	if (!region)
71 		region = calloc(sizeof(*region), count);
72 #endif
73 	if (!region)
74 		return NULL;
75 	for (i = 0; i < count; i++) {
76 		debug("%10x %10x\n", fdt_regions[i].offset,
77 		      fdt_regions[i].size);
78 		region[i].data = fit + fdt_regions[i].offset;
79 		region[i].size = fdt_regions[i].size;
80 	}
81 
82 	return region;
83 }
84 
85 static int fit_image_setup_verify(struct image_sign_info *info,
86 		const void *fit, int noffset, int required_keynode,
87 		char **err_msgp)
88 {
89 	char *algo_name;
90 
91 	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
92 		*err_msgp = "Can't get hash algo property";
93 		return -1;
94 	}
95 	memset(info, '\0', sizeof(*info));
96 	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
97 	info->fit = (void *)fit;
98 	info->node_offset = noffset;
99 	info->algo = image_get_sig_algo(algo_name);
100 	info->fdt_blob = gd_fdt_blob();
101 	info->required_keynode = required_keynode;
102 	printf("%s:%s", algo_name, info->keyname);
103 
104 	if (!info->algo) {
105 		*err_msgp = "Unknown signature algorithm";
106 		return -1;
107 	}
108 
109 	return 0;
110 }
111 
112 int fit_image_check_sig(const void *fit, int noffset, const void *data,
113 		size_t size, int required_keynode, char **err_msgp)
114 {
115 	struct image_sign_info info;
116 	struct image_region region;
117 	uint8_t *fit_value;
118 	int fit_value_len;
119 
120 	*err_msgp = NULL;
121 	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
122 				   err_msgp))
123 		return -1;
124 
125 	if (fit_image_hash_get_value(fit, noffset, &fit_value,
126 				     &fit_value_len)) {
127 		*err_msgp = "Can't get hash value property";
128 		return -1;
129 	}
130 
131 	region.data = data;
132 	region.size = size;
133 
134 	if (info.algo->verify(&info, &region, 1, fit_value, fit_value_len)) {
135 		*err_msgp = "Verification failed";
136 		return -1;
137 	}
138 
139 	return 0;
140 }
141 
142 static int fit_image_verify_sig(const void *fit, int image_noffset,
143 		const char *data, size_t size, const void *sig_blob,
144 		int sig_offset)
145 {
146 	int noffset;
147 	char *err_msg = "";
148 	int verified = 0;
149 	int ret;
150 
151 	/* Process all hash subnodes of the component image node */
152 	for (noffset = fdt_first_subnode(fit, image_noffset);
153 	     noffset >= 0;
154 	     noffset = fdt_next_subnode(fit, noffset)) {
155 		const char *name = fit_get_name(fit, noffset, NULL);
156 
157 		if (!strncmp(name, FIT_SIG_NODENAME,
158 			     strlen(FIT_SIG_NODENAME))) {
159 			ret = fit_image_check_sig(fit, noffset, data,
160 							size, -1, &err_msg);
161 			if (ret) {
162 				puts("- ");
163 			} else {
164 				puts("+ ");
165 				verified = 1;
166 				break;
167 			}
168 		}
169 	}
170 
171 	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
172 		err_msg = "Corrupted or truncated tree";
173 		goto error;
174 	}
175 
176 	return verified ? 0 : -EPERM;
177 
178 error:
179 	printf(" error!\n%s for '%s' hash node in '%s' image node\n",
180 	       err_msg, fit_get_name(fit, noffset, NULL),
181 	       fit_get_name(fit, image_noffset, NULL));
182 	return -1;
183 }
184 
185 int fit_image_verify_required_sigs(const void *fit, int image_noffset,
186 		const char *data, size_t size, const void *sig_blob,
187 		int *no_sigsp)
188 {
189 	int verify_count = 0;
190 	int noffset;
191 	int sig_node;
192 
193 	/* Work out what we need to verify */
194 	*no_sigsp = 1;
195 	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
196 	if (sig_node < 0) {
197 		debug("%s: No signature node found: %s\n", __func__,
198 		      fdt_strerror(sig_node));
199 		return 0;
200 	}
201 
202 	for (noffset = fdt_first_subnode(sig_blob, sig_node);
203 	     noffset >= 0;
204 	     noffset = fdt_next_subnode(sig_blob, noffset)) {
205 		const char *required;
206 		int ret;
207 
208 		required = fdt_getprop(sig_blob, noffset, "required", NULL);
209 		if (!required || strcmp(required, "image"))
210 			continue;
211 		ret = fit_image_verify_sig(fit, image_noffset, data, size,
212 					sig_blob, noffset);
213 		if (ret) {
214 			printf("Failed to verify required signature '%s'\n",
215 			       fit_get_name(sig_blob, noffset, NULL));
216 			return ret;
217 		}
218 		verify_count++;
219 	}
220 
221 	if (verify_count)
222 		*no_sigsp = 0;
223 
224 	return 0;
225 }
226 
227 int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
228 			 char **err_msgp)
229 {
230 	char * const exc_prop[] = {"data"};
231 	const char *prop, *end, *name;
232 	struct image_sign_info info;
233 	const uint32_t *strings;
234 	uint8_t *fit_value;
235 	int fit_value_len;
236 	int max_regions;
237 	int i, prop_len;
238 	char path[200];
239 	int count;
240 
241 	debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
242 	      fit_get_name(fit, noffset, NULL),
243 	      fit_get_name(gd_fdt_blob(), required_keynode, NULL));
244 	*err_msgp = NULL;
245 	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
246 				   err_msgp))
247 		return -1;
248 
249 	if (fit_image_hash_get_value(fit, noffset, &fit_value,
250 				     &fit_value_len)) {
251 		*err_msgp = "Can't get hash value property";
252 		return -1;
253 	}
254 
255 	/* Count the number of strings in the property */
256 	prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
257 	end = prop ? prop + prop_len : prop;
258 	for (name = prop, count = 0; name < end; name++)
259 		if (!*name)
260 			count++;
261 	if (!count) {
262 		*err_msgp = "Can't get hashed-nodes property";
263 		return -1;
264 	}
265 
266 	/* Add a sanity check here since we are using the stack */
267 	if (count > IMAGE_MAX_HASHED_NODES) {
268 		*err_msgp = "Number of hashed nodes exceeds maximum";
269 		return -1;
270 	}
271 
272 	/* Create a list of node names from those strings */
273 	char *node_inc[count];
274 
275 	debug("Hash nodes (%d):\n", count);
276 	for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
277 		debug("   '%s'\n", name);
278 		node_inc[i] = (char *)name;
279 	}
280 
281 	/*
282 	 * Each node can generate one region for each sub-node. Allow for
283 	 * 7 sub-nodes (hash@1, signature@1, etc.) and some extra.
284 	 */
285 	max_regions = 20 + count * 7;
286 	struct fdt_region fdt_regions[max_regions];
287 
288 	/* Get a list of regions to hash */
289 	count = fdt_find_regions(fit, node_inc, count,
290 			exc_prop, ARRAY_SIZE(exc_prop),
291 			fdt_regions, max_regions - 1,
292 			path, sizeof(path), 0);
293 	if (count < 0) {
294 		*err_msgp = "Failed to hash configuration";
295 		return -1;
296 	}
297 	if (count == 0) {
298 		*err_msgp = "No data to hash";
299 		return -1;
300 	}
301 	if (count >= max_regions - 1) {
302 		*err_msgp = "Too many hash regions";
303 		return -1;
304 	}
305 
306 	/* Add the strings */
307 	strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
308 	if (strings) {
309 		fdt_regions[count].offset = fdt_off_dt_strings(fit) +
310 				fdt32_to_cpu(strings[0]);
311 		fdt_regions[count].size = fdt32_to_cpu(strings[1]);
312 		count++;
313 	}
314 
315 	/* Allocate the region list on the stack */
316 	struct image_region region[count];
317 
318 	fit_region_make_list(fit, fdt_regions, count, region);
319 	if (info.algo->verify(&info, region, count, fit_value,
320 			      fit_value_len)) {
321 		*err_msgp = "Verification failed";
322 		return -1;
323 	}
324 
325 	return 0;
326 }
327 
328 static int fit_config_verify_sig(const void *fit, int conf_noffset,
329 		const void *sig_blob, int sig_offset)
330 {
331 	int noffset;
332 	char *err_msg = "";
333 	int verified = 0;
334 	int ret;
335 
336 	/* Process all hash subnodes of the component conf node */
337 	for (noffset = fdt_first_subnode(fit, conf_noffset);
338 	     noffset >= 0;
339 	     noffset = fdt_next_subnode(fit, noffset)) {
340 		const char *name = fit_get_name(fit, noffset, NULL);
341 
342 		if (!strncmp(name, FIT_SIG_NODENAME,
343 			     strlen(FIT_SIG_NODENAME))) {
344 			ret = fit_config_check_sig(fit, noffset, sig_offset,
345 						   &err_msg);
346 			if (ret) {
347 				puts("- ");
348 			} else {
349 				puts("+ ");
350 				verified = 1;
351 				break;
352 			}
353 		}
354 	}
355 
356 	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
357 		err_msg = "Corrupted or truncated tree";
358 		goto error;
359 	}
360 
361 	return verified ? 0 : -EPERM;
362 
363 error:
364 	printf(" error!\n%s for '%s' hash node in '%s' config node\n",
365 	       err_msg, fit_get_name(fit, noffset, NULL),
366 	       fit_get_name(fit, conf_noffset, NULL));
367 	return -1;
368 }
369 
370 int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
371 		const void *sig_blob)
372 {
373 	int noffset;
374 	int sig_node;
375 
376 	/* Work out what we need to verify */
377 	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
378 	if (sig_node < 0) {
379 		debug("%s: No signature node found: %s\n", __func__,
380 		      fdt_strerror(sig_node));
381 		return 0;
382 	}
383 
384 	for (noffset = fdt_first_subnode(sig_blob, sig_node);
385 	     noffset >= 0;
386 	     noffset = fdt_next_subnode(sig_blob, noffset)) {
387 		const char *required;
388 		int ret;
389 
390 		required = fdt_getprop(sig_blob, noffset, "required", NULL);
391 		if (!required || strcmp(required, "conf"))
392 			continue;
393 		ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
394 					    noffset);
395 		if (ret) {
396 			printf("Failed to verify required signature '%s'\n",
397 			       fit_get_name(sig_blob, noffset, NULL));
398 			return ret;
399 		}
400 	}
401 
402 	return 0;
403 }
404 
405 int fit_config_verify(const void *fit, int conf_noffset)
406 {
407 	return !fit_config_verify_required_sigs(fit, conf_noffset,
408 						gd_fdt_blob());
409 }
410