1
2
3
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>
14DECLARE_GLOBAL_DATA_PTR;
15#endif
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
25
26
27
28
29
30
31
32
33
34
35
36
37
38struct 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
50
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
66static 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
107int 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, ®ion, 1, fit_value, fit_value_len)) {
131 *err_msgp = "Verification failed";
132 return -1;
133 }
134
135 return 0;
136}
137
138static 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
148 fdt_for_each_subnode(noffset, fit, image_noffset) {
149 const char *name = fit_get_name(fit, noffset, NULL);
150
151
152
153
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
180error:
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
187int 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
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258static 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 "data",
264 "data-size",
265 "data-position",
266 "data-offset"
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
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
313 if (count > IMAGE_MAX_HASHED_NODES) {
314 *err_msgp = "Number of hashed nodes exceeds maximum";
315 return -1;
316 }
317
318
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
340
341
342 max_regions = 20 + count * 7;
343 struct fdt_region fdt_regions[max_regions];
344
345
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
364 strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
365 if (strings) {
366
367
368
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
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
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415static 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
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
450error:
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
459
460
461
462
463
464
465
466
467
468
469
470static 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
483
484
485 if (strchr(name, '@')) {
486 printf("Configuration node '%s' contains '@'\n", name);
487 return -EPERM;
488 }
489
490
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
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
508
509
510
511
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
547int 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