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, const char *engine_id)
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 info->engine_id = engine_id;
174 if (!info->checksum || !info->crypto) {
175 printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
176 algo_name, node_name, image_name);
177 return -1;
178 }
179
180 return 0;
181}
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201static int fit_image_process_sig(const char *keydir, void *keydest,
202 void *fit, const char *image_name,
203 int noffset, const void *data, size_t size,
204 const char *comment, int require_keys, const char *engine_id)
205{
206 struct image_sign_info info;
207 struct image_region region;
208 const char *node_name;
209 uint8_t *value;
210 uint value_len;
211 int ret;
212
213 if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
214 require_keys ? "image" : NULL, engine_id))
215 return -1;
216
217 node_name = fit_get_name(fit, noffset, NULL);
218 region.data = data;
219 region.size = size;
220 ret = info.crypto->sign(&info, ®ion, 1, &value, &value_len);
221 if (ret) {
222 printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
223 node_name, image_name, ret);
224
225
226 if (ret == -ENOENT)
227 return 0;
228 return -1;
229 }
230
231 ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
232 NULL, 0);
233 if (ret) {
234 if (ret == -FDT_ERR_NOSPACE)
235 return -ENOSPC;
236 printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
237 node_name, image_name, fdt_strerror(ret));
238 return -1;
239 }
240 free(value);
241
242
243 info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
244
245 if (keydest)
246 ret = info.crypto->add_verify_data(&info, keydest);
247 else
248 return -1;
249
250
251
252
253
254
255 if (keydest && ret)
256 return ret;
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, conf_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 == -ENOSPC)
629 return -ENOSPC;
630 if (ret) {
631 printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
632 node_name, conf_name);
633 }
634 return ret;
635 }
636
637 return 0;
638}
639
640static int fit_config_add_verification_data(const char *keydir, void *keydest,
641 void *fit, int conf_noffset, const char *comment,
642 int require_keys, const char *engine_id)
643{
644 const char *conf_name;
645 int noffset;
646
647 conf_name = fit_get_name(fit, conf_noffset, NULL);
648
649
650 for (noffset = fdt_first_subnode(fit, conf_noffset);
651 noffset >= 0;
652 noffset = fdt_next_subnode(fit, noffset)) {
653 const char *node_name;
654 int ret = 0;
655
656 node_name = fit_get_name(fit, noffset, NULL);
657 if (!strncmp(node_name, FIT_SIG_NODENAME,
658 strlen(FIT_SIG_NODENAME))) {
659 ret = fit_config_process_sig(keydir, keydest,
660 fit, conf_name, conf_noffset, noffset, comment,
661 require_keys, engine_id);
662 }
663 if (ret)
664 return ret;
665 }
666
667 return 0;
668}
669
670int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
671 const char *comment, int require_keys,
672 const char *engine_id)
673{
674 int images_noffset, confs_noffset;
675 int noffset;
676 int ret;
677
678
679 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
680 if (images_noffset < 0) {
681 printf("Can't find images parent node '%s' (%s)\n",
682 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
683 return images_noffset;
684 }
685
686
687 for (noffset = fdt_first_subnode(fit, images_noffset);
688 noffset >= 0;
689 noffset = fdt_next_subnode(fit, noffset)) {
690
691
692
693
694 ret = fit_image_add_verification_data(keydir, keydest,
695 fit, noffset, comment, require_keys, engine_id);
696 if (ret)
697 return ret;
698 }
699
700
701 if (!IMAGE_ENABLE_SIGN || !keydir)
702 return 0;
703
704
705 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
706 if (confs_noffset < 0) {
707 printf("Can't find images parent node '%s' (%s)\n",
708 FIT_CONFS_PATH, fdt_strerror(confs_noffset));
709 return -ENOENT;
710 }
711
712
713 for (noffset = fdt_first_subnode(fit, confs_noffset);
714 noffset >= 0;
715 noffset = fdt_next_subnode(fit, noffset)) {
716 ret = fit_config_add_verification_data(keydir, keydest,
717 fit, noffset, comment,
718 require_keys,
719 engine_id);
720 if (ret)
721 return ret;
722 }
723
724 return 0;
725}
726
727#ifdef CONFIG_FIT_SIGNATURE
728int fit_check_sign(const void *fit, const void *key)
729{
730 int cfg_noffset;
731 int ret;
732
733 cfg_noffset = fit_conf_get_node(fit, NULL);
734 if (!cfg_noffset)
735 return -1;
736
737 printf("Verifying Hash Integrity ... ");
738 ret = fit_config_verify(fit, cfg_noffset);
739 if (ret)
740 return ret;
741 ret = bootm_host_load_images(fit, cfg_noffset);
742
743 return ret;
744}
745#endif
746