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