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