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