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