1
2
3
4
5
6
7
8
9
10
11
12#include "mkimage.h"
13#include <bootm.h>
14#include <image.h>
15#include <version.h>
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31static int fit_set_hash_value(void *fit, int noffset, uint8_t *value,
32 int value_len)
33{
34 int ret;
35
36 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
37 if (ret) {
38 printf("Can't set hash '%s' property for '%s' node(%s)\n",
39 FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL),
40 fdt_strerror(ret));
41 return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
42 }
43
44 return 0;
45}
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60static int fit_image_process_hash(void *fit, const char *image_name,
61 int noffset, const void *data, size_t size)
62{
63 uint8_t value[FIT_MAX_HASH_LEN];
64 const char *node_name;
65 int value_len;
66 char *algo;
67 int ret;
68
69 node_name = fit_get_name(fit, noffset, NULL);
70
71 if (fit_image_hash_get_algo(fit, noffset, &algo)) {
72 printf("Can't get hash algo property for '%s' hash node in '%s' image node\n",
73 node_name, image_name);
74 return -ENOENT;
75 }
76
77 if (calculate_hash(data, size, algo, value, &value_len)) {
78 printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n",
79 algo, node_name, image_name);
80 return -EPROTONOSUPPORT;
81 }
82
83 ret = fit_set_hash_value(fit, noffset, value, value_len);
84 if (ret) {
85 printf("Can't set hash value for '%s' hash node in '%s' image node\n",
86 node_name, image_name);
87 return ret;
88 }
89
90 return 0;
91}
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108static int fit_image_write_sig(void *fit, int noffset, uint8_t *value,
109 int value_len, const char *comment, const char *region_prop,
110 int region_proplen)
111{
112 int string_size;
113 int ret;
114
115
116
117
118
119 string_size = fdt_size_dt_strings(fit);
120
121 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
122 if (!ret) {
123 ret = fdt_setprop_string(fit, noffset, "signer-name",
124 "mkimage");
125 }
126 if (!ret) {
127 ret = fdt_setprop_string(fit, noffset, "signer-version",
128 PLAIN_VERSION);
129 }
130 if (comment && !ret)
131 ret = fdt_setprop_string(fit, noffset, "comment", comment);
132 if (!ret)
133 ret = fit_set_timestamp(fit, noffset, time(NULL));
134 if (region_prop && !ret) {
135 uint32_t strdata[2];
136
137 ret = fdt_setprop(fit, noffset, "hashed-nodes",
138 region_prop, region_proplen);
139 strdata[0] = 0;
140 strdata[1] = cpu_to_fdt32(string_size);
141 if (!ret) {
142 ret = fdt_setprop(fit, noffset, "hashed-strings",
143 strdata, sizeof(strdata));
144 }
145 }
146
147 return ret;
148}
149
150static int fit_image_setup_sig(struct image_sign_info *info,
151 const char *keydir, void *fit, const char *image_name,
152 int noffset, const char *require_keys)
153{
154 const char *node_name;
155 char *algo_name;
156
157 node_name = fit_get_name(fit, noffset, NULL);
158 if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
159 printf("Can't get algo property for '%s' signature node in '%s' image node\n",
160 node_name, image_name);
161 return -1;
162 }
163
164 memset(info, '\0', sizeof(*info));
165 info->keydir = keydir;
166 info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
167 info->fit = fit;
168 info->node_offset = noffset;
169 info->name = algo_name;
170 info->checksum = image_get_checksum_algo(algo_name);
171 info->crypto = image_get_crypto_algo(algo_name);
172 info->require_keys = require_keys;
173 if (!info->checksum || !info->crypto) {
174 printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
175 algo_name, node_name, image_name);
176 return -1;
177 }
178
179 return 0;
180}
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199static int fit_image_process_sig(const char *keydir, void *keydest,
200 void *fit, const char *image_name,
201 int noffset, const void *data, size_t size,
202 const char *comment, int require_keys)
203{
204 struct image_sign_info info;
205 struct image_region region;
206 const char *node_name;
207 uint8_t *value;
208 uint value_len;
209 int ret;
210
211 if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
212 require_keys ? "image" : NULL))
213 return -1;
214
215 node_name = fit_get_name(fit, noffset, NULL);
216 region.data = data;
217 region.size = size;
218 ret = info.crypto->sign(&info, ®ion, 1, &value, &value_len);
219 if (ret) {
220 printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
221 node_name, image_name, ret);
222
223
224 if (ret == -ENOENT)
225 return 0;
226 return -1;
227 }
228
229 ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
230 NULL, 0);
231 if (ret) {
232 if (ret == -FDT_ERR_NOSPACE)
233 return -ENOSPC;
234 printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
235 node_name, image_name, fdt_strerror(ret));
236 return -1;
237 }
238 free(value);
239
240
241 info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
242
243 if (keydest)
244 ret = info.crypto->add_verify_data(&info, keydest);
245 else
246 return -1;
247
248
249
250
251
252
253 if (keydest && ret)
254 return ret;
255
256 return 0;
257}
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293int fit_image_add_verification_data(const char *keydir, void *keydest,
294 void *fit, int image_noffset, const char *comment,
295 int require_keys)
296{
297 const char *image_name;
298 const void *data;
299 size_t size;
300 int noffset;
301
302
303 if (fit_image_get_data(fit, image_noffset, &data, &size)) {
304 printf("Can't get image data/size\n");
305 return -1;
306 }
307
308 image_name = fit_get_name(fit, image_noffset, NULL);
309
310
311 for (noffset = fdt_first_subnode(fit, image_noffset);
312 noffset >= 0;
313 noffset = fdt_next_subnode(fit, noffset)) {
314 const char *node_name;
315 int ret = 0;
316
317
318
319
320
321
322 node_name = fit_get_name(fit, noffset, NULL);
323 if (!strncmp(node_name, FIT_HASH_NODENAME,
324 strlen(FIT_HASH_NODENAME))) {
325 ret = fit_image_process_hash(fit, image_name, noffset,
326 data, size);
327 } else if (IMAGE_ENABLE_SIGN && keydir &&
328 !strncmp(node_name, FIT_SIG_NODENAME,
329 strlen(FIT_SIG_NODENAME))) {
330 ret = fit_image_process_sig(keydir, keydest,
331 fit, image_name, noffset, data, size,
332 comment, require_keys);
333 }
334 if (ret)
335 return ret;
336 }
337
338 return 0;
339}
340
341struct strlist {
342 int count;
343 char **strings;
344};
345
346static void strlist_init(struct strlist *list)
347{
348 memset(list, '\0', sizeof(*list));
349}
350
351static void strlist_free(struct strlist *list)
352{
353 int i;
354
355 for (i = 0; i < list->count; i++)
356 free(list->strings[i]);
357 free(list->strings);
358}
359
360static int strlist_add(struct strlist *list, const char *str)
361{
362 char *dup;
363
364 dup = strdup(str);
365 list->strings = realloc(list->strings,
366 (list->count + 1) * sizeof(char *));
367 if (!list || !str)
368 return -1;
369 list->strings[list->count++] = dup;
370
371 return 0;
372}
373
374static const char *fit_config_get_image_list(void *fit, int noffset,
375 int *lenp, int *allow_missingp)
376{
377 static const char default_list[] = FIT_KERNEL_PROP "\0"
378 FIT_FDT_PROP;
379 const char *prop;
380
381
382 prop = fdt_getprop(fit, noffset, "sign-images", lenp);
383 if (prop) {
384 *allow_missingp = 0;
385 return *lenp ? prop : NULL;
386 }
387
388
389 *allow_missingp = 1;
390 *lenp = sizeof(default_list);
391
392 return default_list;
393}
394
395static int fit_config_get_hash_list(void *fit, int conf_noffset,
396 int sig_offset, struct strlist *node_inc)
397{
398 int allow_missing;
399 const char *prop, *iname, *end;
400 const char *conf_name, *sig_name;
401 char name[200], path[200];
402 int image_count;
403 int ret, len;
404
405 conf_name = fit_get_name(fit, conf_noffset, NULL);
406 sig_name = fit_get_name(fit, sig_offset, NULL);
407
408
409
410
411
412 strlist_init(node_inc);
413 snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name);
414 if (strlist_add(node_inc, "/") ||
415 strlist_add(node_inc, name))
416 goto err_mem;
417
418
419 prop = fit_config_get_image_list(fit, sig_offset, &len,
420 &allow_missing);
421 if (!prop)
422 return 0;
423
424
425 end = prop + len;
426 image_count = 0;
427 for (iname = prop; iname < end; iname += strlen(iname) + 1) {
428 int noffset;
429 int image_noffset;
430 int hash_count;
431
432 image_noffset = fit_conf_get_prop_node(fit, conf_noffset,
433 iname);
434 if (image_noffset < 0) {
435 printf("Failed to find image '%s' in configuration '%s/%s'\n",
436 iname, conf_name, sig_name);
437 if (allow_missing)
438 continue;
439
440 return -ENOENT;
441 }
442
443 ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
444 if (ret < 0)
445 goto err_path;
446 if (strlist_add(node_inc, path))
447 goto err_mem;
448
449 snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH,
450 conf_name);
451
452
453 hash_count = 0;
454 for (noffset = fdt_first_subnode(fit, image_noffset);
455 noffset >= 0;
456 noffset = fdt_next_subnode(fit, noffset)) {
457 const char *name = fit_get_name(fit, noffset, NULL);
458
459 if (strncmp(name, FIT_HASH_NODENAME,
460 strlen(FIT_HASH_NODENAME)))
461 continue;
462 ret = fdt_get_path(fit, noffset, path, sizeof(path));
463 if (ret < 0)
464 goto err_path;
465 if (strlist_add(node_inc, path))
466 goto err_mem;
467 hash_count++;
468 }
469
470 if (!hash_count) {
471 printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
472 conf_name, sig_name, iname);
473 return -ENOMSG;
474 }
475
476 image_count++;
477 }
478
479 if (!image_count) {
480 printf("Failed to find any images for configuration '%s/%s'\n",
481 conf_name, sig_name);
482 return -ENOMSG;
483 }
484
485 return 0;
486
487err_mem:
488 printf("Out of memory processing configuration '%s/%s'\n", conf_name,
489 sig_name);
490 return -ENOMEM;
491
492err_path:
493 printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n",
494 iname, conf_name, sig_name, fdt_strerror(ret));
495 return -ENOENT;
496}
497
498static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
499 struct image_region **regionp, int *region_countp,
500 char **region_propp, int *region_proplen)
501{
502 char * const exc_prop[] = {"data"};
503 struct strlist node_inc;
504 struct image_region *region;
505 struct fdt_region fdt_regions[100];
506 const char *conf_name, *sig_name;
507 char path[200];
508 int count, i;
509 char *region_prop;
510 int ret, len;
511
512 conf_name = fit_get_name(fit, conf_noffset, NULL);
513 sig_name = fit_get_name(fit, conf_noffset, NULL);
514 debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
515
516
517 ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc);
518 if (ret)
519 return ret;
520
521
522 count = fdt_find_regions(fit, node_inc.strings, node_inc.count,
523 exc_prop, ARRAY_SIZE(exc_prop),
524 fdt_regions, ARRAY_SIZE(fdt_regions),
525 path, sizeof(path), 1);
526 if (count < 0) {
527 printf("Failed to hash configuration '%s/%s': %s\n", conf_name,
528 sig_name, fdt_strerror(ret));
529 return -EIO;
530 }
531 if (count == 0) {
532 printf("No data to hash for configuration '%s/%s': %s\n",
533 conf_name, sig_name, fdt_strerror(ret));
534 return -EINVAL;
535 }
536
537
538 region = fit_region_make_list(fit, fdt_regions, count, NULL);
539 if (!region) {
540 printf("Out of memory hashing configuration '%s/%s'\n",
541 conf_name, sig_name);
542 return -ENOMEM;
543 }
544
545
546 debug("Hash nodes:\n");
547 for (i = len = 0; i < node_inc.count; i++) {
548 debug(" %s\n", node_inc.strings[i]);
549 len += strlen(node_inc.strings[i]) + 1;
550 }
551 region_prop = malloc(len);
552 if (!region_prop) {
553 printf("Out of memory setting up regions for configuration '%s/%s'\n",
554 conf_name, sig_name);
555 return -ENOMEM;
556 }
557 for (i = len = 0; i < node_inc.count;
558 len += strlen(node_inc.strings[i]) + 1, i++)
559 strcpy(region_prop + len, node_inc.strings[i]);
560 strlist_free(&node_inc);
561
562 *region_countp = count;
563 *regionp = region;
564 *region_propp = region_prop;
565 *region_proplen = len;
566
567 return 0;
568}
569
570static int fit_config_process_sig(const char *keydir, void *keydest,
571 void *fit, const char *conf_name, int conf_noffset,
572 int noffset, const char *comment, int require_keys)
573{
574 struct image_sign_info info;
575 const char *node_name;
576 struct image_region *region;
577 char *region_prop;
578 int region_proplen;
579 int region_count;
580 uint8_t *value;
581 uint value_len;
582 int ret;
583
584 node_name = fit_get_name(fit, noffset, NULL);
585 if (fit_config_get_data(fit, conf_noffset, noffset, ®ion,
586 ®ion_count, ®ion_prop, ®ion_proplen))
587 return -1;
588
589 if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset,
590 require_keys ? "conf" : NULL))
591 return -1;
592
593 ret = info.crypto->sign(&info, region, region_count, &value,
594 &value_len);
595 free(region);
596 if (ret) {
597 printf("Failed to sign '%s' signature node in '%s' conf node\n",
598 node_name, conf_name);
599
600
601 if (ret == -ENOENT)
602 return 0;
603 return -1;
604 }
605
606 ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
607 region_prop, region_proplen);
608 if (ret) {
609 if (ret == -FDT_ERR_NOSPACE)
610 return -ENOSPC;
611 printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
612 node_name, conf_name, fdt_strerror(ret));
613 return -1;
614 }
615 free(value);
616 free(region_prop);
617
618
619 info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
620
621
622 if (keydest) {
623 ret = info.crypto->add_verify_data(&info, keydest);
624 if (ret == -ENOSPC)
625 return -ENOSPC;
626 if (ret) {
627 printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
628 node_name, conf_name);
629 }
630 return ret;
631 }
632
633 return 0;
634}
635
636static int fit_config_add_verification_data(const char *keydir, void *keydest,
637 void *fit, int conf_noffset, const char *comment,
638 int require_keys)
639{
640 const char *conf_name;
641 int noffset;
642
643 conf_name = fit_get_name(fit, conf_noffset, NULL);
644
645
646 for (noffset = fdt_first_subnode(fit, conf_noffset);
647 noffset >= 0;
648 noffset = fdt_next_subnode(fit, noffset)) {
649 const char *node_name;
650 int ret = 0;
651
652 node_name = fit_get_name(fit, noffset, NULL);
653 if (!strncmp(node_name, FIT_SIG_NODENAME,
654 strlen(FIT_SIG_NODENAME))) {
655 ret = fit_config_process_sig(keydir, keydest,
656 fit, conf_name, conf_noffset, noffset, comment,
657 require_keys);
658 }
659 if (ret)
660 return ret;
661 }
662
663 return 0;
664}
665
666int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
667 const char *comment, int require_keys)
668{
669 int images_noffset, confs_noffset;
670 int noffset;
671 int ret;
672
673
674 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
675 if (images_noffset < 0) {
676 printf("Can't find images parent node '%s' (%s)\n",
677 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
678 return images_noffset;
679 }
680
681
682 for (noffset = fdt_first_subnode(fit, images_noffset);
683 noffset >= 0;
684 noffset = fdt_next_subnode(fit, noffset)) {
685
686
687
688
689 ret = fit_image_add_verification_data(keydir, keydest,
690 fit, noffset, comment, require_keys);
691 if (ret)
692 return ret;
693 }
694
695
696 if (!IMAGE_ENABLE_SIGN || !keydir)
697 return 0;
698
699
700 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
701 if (confs_noffset < 0) {
702 printf("Can't find images parent node '%s' (%s)\n",
703 FIT_CONFS_PATH, fdt_strerror(confs_noffset));
704 return -ENOENT;
705 }
706
707
708 for (noffset = fdt_first_subnode(fit, confs_noffset);
709 noffset >= 0;
710 noffset = fdt_next_subnode(fit, noffset)) {
711 ret = fit_config_add_verification_data(keydir, keydest,
712 fit, noffset, comment,
713 require_keys);
714 if (ret)
715 return ret;
716 }
717
718 return 0;
719}
720
721#ifdef CONFIG_FIT_SIGNATURE
722int fit_check_sign(const void *fit, const void *key)
723{
724 int cfg_noffset;
725 int ret;
726
727 cfg_noffset = fit_conf_get_node(fit, NULL);
728 if (!cfg_noffset)
729 return -1;
730
731 printf("Verifying Hash Integrity ... ");
732 ret = fit_config_verify(fit, cfg_noffset);
733 if (ret)
734 return ret;
735 ret = bootm_host_load_images(fit, cfg_noffset);
736
737 return ret;
738}
739#endif
740