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->algo = image_get_sig_algo(algo_name);
170 info->require_keys = require_keys;
171 if (!info->algo) {
172 printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
173 algo_name, node_name, image_name);
174 return -1;
175 }
176
177 return 0;
178}
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197static int fit_image_process_sig(const char *keydir, void *keydest,
198 void *fit, const char *image_name,
199 int noffset, const void *data, size_t size,
200 const char *comment, int require_keys)
201{
202 struct image_sign_info info;
203 struct image_region region;
204 const char *node_name;
205 uint8_t *value;
206 uint value_len;
207 int ret;
208
209 if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
210 require_keys ? "image" : NULL))
211 return -1;
212
213 node_name = fit_get_name(fit, noffset, NULL);
214 region.data = data;
215 region.size = size;
216 ret = info.algo->sign(&info, ®ion, 1, &value, &value_len);
217 if (ret) {
218 printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
219 node_name, image_name, ret);
220
221
222 if (ret == -ENOENT)
223 return 0;
224 return -1;
225 }
226
227 ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
228 NULL, 0);
229 if (ret) {
230 if (ret == -FDT_ERR_NOSPACE)
231 return -ENOSPC;
232 printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
233 node_name, image_name, fdt_strerror(ret));
234 return -1;
235 }
236 free(value);
237
238
239 info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
240
241 if (keydest)
242 ret = info.algo->add_verify_data(&info, keydest);
243 else
244 return -1;
245
246
247
248
249
250
251 if (keydest && ret)
252 return ret;
253
254 return 0;
255}
256
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
291int fit_image_add_verification_data(const char *keydir, void *keydest,
292 void *fit, int image_noffset, const char *comment,
293 int require_keys)
294{
295 const char *image_name;
296 const void *data;
297 size_t size;
298 int noffset;
299
300
301 if (fit_image_get_data(fit, image_noffset, &data, &size)) {
302 printf("Can't get image data/size\n");
303 return -1;
304 }
305
306 image_name = fit_get_name(fit, image_noffset, NULL);
307
308
309 for (noffset = fdt_first_subnode(fit, image_noffset);
310 noffset >= 0;
311 noffset = fdt_next_subnode(fit, noffset)) {
312 const char *node_name;
313 int ret = 0;
314
315
316
317
318
319
320 node_name = fit_get_name(fit, noffset, NULL);
321 if (!strncmp(node_name, FIT_HASH_NODENAME,
322 strlen(FIT_HASH_NODENAME))) {
323 ret = fit_image_process_hash(fit, image_name, noffset,
324 data, size);
325 } else if (IMAGE_ENABLE_SIGN && keydir &&
326 !strncmp(node_name, FIT_SIG_NODENAME,
327 strlen(FIT_SIG_NODENAME))) {
328 ret = fit_image_process_sig(keydir, keydest,
329 fit, image_name, noffset, data, size,
330 comment, require_keys);
331 }
332 if (ret)
333 return ret;
334 }
335
336 return 0;
337}
338
339struct strlist {
340 int count;
341 char **strings;
342};
343
344static void strlist_init(struct strlist *list)
345{
346 memset(list, '\0', sizeof(*list));
347}
348
349static void strlist_free(struct strlist *list)
350{
351 int i;
352
353 for (i = 0; i < list->count; i++)
354 free(list->strings[i]);
355 free(list->strings);
356}
357
358static int strlist_add(struct strlist *list, const char *str)
359{
360 char *dup;
361
362 dup = strdup(str);
363 list->strings = realloc(list->strings,
364 (list->count + 1) * sizeof(char *));
365 if (!list || !str)
366 return -1;
367 list->strings[list->count++] = dup;
368
369 return 0;
370}
371
372static const char *fit_config_get_image_list(void *fit, int noffset,
373 int *lenp, int *allow_missingp)
374{
375 static const char default_list[] = FIT_KERNEL_PROP "\0"
376 FIT_FDT_PROP;
377 const char *prop;
378
379
380 prop = fdt_getprop(fit, noffset, "sign-images", lenp);
381 if (prop) {
382 *allow_missingp = 0;
383 return *lenp ? prop : NULL;
384 }
385
386
387 *allow_missingp = 1;
388 *lenp = sizeof(default_list);
389
390 return default_list;
391}
392
393static int fit_config_get_hash_list(void *fit, int conf_noffset,
394 int sig_offset, struct strlist *node_inc)
395{
396 int allow_missing;
397 const char *prop, *iname, *end;
398 const char *conf_name, *sig_name;
399 char name[200], path[200];
400 int image_count;
401 int ret, len;
402
403 conf_name = fit_get_name(fit, conf_noffset, NULL);
404 sig_name = fit_get_name(fit, sig_offset, NULL);
405
406
407
408
409
410 strlist_init(node_inc);
411 snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name);
412 if (strlist_add(node_inc, "/") ||
413 strlist_add(node_inc, name))
414 goto err_mem;
415
416
417 prop = fit_config_get_image_list(fit, sig_offset, &len,
418 &allow_missing);
419 if (!prop)
420 return 0;
421
422
423 end = prop + len;
424 image_count = 0;
425 for (iname = prop; iname < end; iname += strlen(iname) + 1) {
426 int noffset;
427 int image_noffset;
428 int hash_count;
429
430 image_noffset = fit_conf_get_prop_node(fit, conf_noffset,
431 iname);
432 if (image_noffset < 0) {
433 printf("Failed to find image '%s' in configuration '%s/%s'\n",
434 iname, conf_name, sig_name);
435 if (allow_missing)
436 continue;
437
438 return -ENOENT;
439 }
440
441 ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
442 if (ret < 0)
443 goto err_path;
444 if (strlist_add(node_inc, path))
445 goto err_mem;
446
447 snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH,
448 conf_name);
449
450
451 hash_count = 0;
452 for (noffset = fdt_first_subnode(fit, image_noffset);
453 noffset >= 0;
454 noffset = fdt_next_subnode(fit, noffset)) {
455 const char *name = fit_get_name(fit, noffset, NULL);
456
457 if (strncmp(name, FIT_HASH_NODENAME,
458 strlen(FIT_HASH_NODENAME)))
459 continue;
460 ret = fdt_get_path(fit, noffset, path, sizeof(path));
461 if (ret < 0)
462 goto err_path;
463 if (strlist_add(node_inc, path))
464 goto err_mem;
465 hash_count++;
466 }
467
468 if (!hash_count) {
469 printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
470 conf_name, sig_name, iname);
471 return -ENOMSG;
472 }
473
474 image_count++;
475 }
476
477 if (!image_count) {
478 printf("Failed to find any images for configuration '%s/%s'\n",
479 conf_name, sig_name);
480 return -ENOMSG;
481 }
482
483 return 0;
484
485err_mem:
486 printf("Out of memory processing configuration '%s/%s'\n", conf_name,
487 sig_name);
488 return -ENOMEM;
489
490err_path:
491 printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n",
492 iname, conf_name, sig_name, fdt_strerror(ret));
493 return -ENOENT;
494}
495
496static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
497 struct image_region **regionp, int *region_countp,
498 char **region_propp, int *region_proplen)
499{
500 char * const exc_prop[] = {"data"};
501 struct strlist node_inc;
502 struct image_region *region;
503 struct fdt_region fdt_regions[100];
504 const char *conf_name, *sig_name;
505 char path[200];
506 int count, i;
507 char *region_prop;
508 int ret, len;
509
510 conf_name = fit_get_name(fit, conf_noffset, NULL);
511 sig_name = fit_get_name(fit, conf_noffset, NULL);
512 debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
513
514
515 ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc);
516 if (ret)
517 return ret;
518
519
520 count = fdt_find_regions(fit, node_inc.strings, node_inc.count,
521 exc_prop, ARRAY_SIZE(exc_prop),
522 fdt_regions, ARRAY_SIZE(fdt_regions),
523 path, sizeof(path), 1);
524 if (count < 0) {
525 printf("Failed to hash configuration '%s/%s': %s\n", conf_name,
526 sig_name, fdt_strerror(ret));
527 return -EIO;
528 }
529 if (count == 0) {
530 printf("No data to hash for configuration '%s/%s': %s\n",
531 conf_name, sig_name, fdt_strerror(ret));
532 return -EINVAL;
533 }
534
535
536 region = fit_region_make_list(fit, fdt_regions, count, NULL);
537 if (!region) {
538 printf("Out of memory hashing configuration '%s/%s'\n",
539 conf_name, sig_name);
540 return -ENOMEM;
541 }
542
543
544 debug("Hash nodes:\n");
545 for (i = len = 0; i < node_inc.count; i++) {
546 debug(" %s\n", node_inc.strings[i]);
547 len += strlen(node_inc.strings[i]) + 1;
548 }
549 region_prop = malloc(len);
550 if (!region_prop) {
551 printf("Out of memory setting up regions for configuration '%s/%s'\n",
552 conf_name, sig_name);
553 return -ENOMEM;
554 }
555 for (i = len = 0; i < node_inc.count;
556 len += strlen(node_inc.strings[i]) + 1, i++)
557 strcpy(region_prop + len, node_inc.strings[i]);
558 strlist_free(&node_inc);
559
560 *region_countp = count;
561 *regionp = region;
562 *region_propp = region_prop;
563 *region_proplen = len;
564
565 return 0;
566}
567
568static int fit_config_process_sig(const char *keydir, void *keydest,
569 void *fit, const char *conf_name, int conf_noffset,
570 int noffset, const char *comment, int require_keys)
571{
572 struct image_sign_info info;
573 const char *node_name;
574 struct image_region *region;
575 char *region_prop;
576 int region_proplen;
577 int region_count;
578 uint8_t *value;
579 uint value_len;
580 int ret;
581
582 node_name = fit_get_name(fit, noffset, NULL);
583 if (fit_config_get_data(fit, conf_noffset, noffset, ®ion,
584 ®ion_count, ®ion_prop, ®ion_proplen))
585 return -1;
586
587 if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset,
588 require_keys ? "conf" : NULL))
589 return -1;
590
591 ret = info.algo->sign(&info, region, region_count, &value, &value_len);
592 free(region);
593 if (ret) {
594 printf("Failed to sign '%s' signature node in '%s' conf node\n",
595 node_name, conf_name);
596
597
598 if (ret == -ENOENT)
599 return 0;
600 return -1;
601 }
602
603 ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
604 region_prop, region_proplen);
605 if (ret) {
606 if (ret == -FDT_ERR_NOSPACE)
607 return -ENOSPC;
608 printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
609 node_name, conf_name, fdt_strerror(ret));
610 return -1;
611 }
612 free(value);
613 free(region_prop);
614
615
616 info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
617
618
619 if (keydest) {
620 ret = info.algo->add_verify_data(&info, keydest);
621 if (ret == -ENOSPC)
622 return -ENOSPC;
623 if (ret) {
624 printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
625 node_name, conf_name);
626 }
627 return ret;
628 }
629
630 return 0;
631}
632
633static int fit_config_add_verification_data(const char *keydir, void *keydest,
634 void *fit, int conf_noffset, const char *comment,
635 int require_keys)
636{
637 const char *conf_name;
638 int noffset;
639
640 conf_name = fit_get_name(fit, conf_noffset, NULL);
641
642
643 for (noffset = fdt_first_subnode(fit, conf_noffset);
644 noffset >= 0;
645 noffset = fdt_next_subnode(fit, noffset)) {
646 const char *node_name;
647 int ret = 0;
648
649 node_name = fit_get_name(fit, noffset, NULL);
650 if (!strncmp(node_name, FIT_SIG_NODENAME,
651 strlen(FIT_SIG_NODENAME))) {
652 ret = fit_config_process_sig(keydir, keydest,
653 fit, conf_name, conf_noffset, noffset, comment,
654 require_keys);
655 }
656 if (ret)
657 return ret;
658 }
659
660 return 0;
661}
662
663int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
664 const char *comment, int require_keys)
665{
666 int images_noffset, confs_noffset;
667 int noffset;
668 int ret;
669
670
671 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
672 if (images_noffset < 0) {
673 printf("Can't find images parent node '%s' (%s)\n",
674 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
675 return images_noffset;
676 }
677
678
679 for (noffset = fdt_first_subnode(fit, images_noffset);
680 noffset >= 0;
681 noffset = fdt_next_subnode(fit, noffset)) {
682
683
684
685
686 ret = fit_image_add_verification_data(keydir, keydest,
687 fit, noffset, comment, require_keys);
688 if (ret)
689 return ret;
690 }
691
692
693 if (!IMAGE_ENABLE_SIGN || !keydir)
694 return 0;
695
696
697 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
698 if (confs_noffset < 0) {
699 printf("Can't find images parent node '%s' (%s)\n",
700 FIT_CONFS_PATH, fdt_strerror(confs_noffset));
701 return -ENOENT;
702 }
703
704
705 for (noffset = fdt_first_subnode(fit, confs_noffset);
706 noffset >= 0;
707 noffset = fdt_next_subnode(fit, noffset)) {
708 ret = fit_config_add_verification_data(keydir, keydest,
709 fit, noffset, comment,
710 require_keys);
711 if (ret)
712 return ret;
713 }
714
715 return 0;
716}
717
718#ifdef CONFIG_FIT_SIGNATURE
719int fit_check_sign(const void *fit, const void *key)
720{
721 int cfg_noffset;
722 int ret;
723
724 cfg_noffset = fit_conf_get_node(fit, NULL);
725 if (!cfg_noffset)
726 return -1;
727
728 printf("Verifying Hash Integrity ... ");
729 ret = fit_config_verify(fit, cfg_noffset);
730 if (ret)
731 return ret;
732 ret = bootm_host_load_images(fit, cfg_noffset);
733
734 return ret;
735}
736#endif
737