]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/image-host.c
mkimage: Automatically make space in FDT when full
[karo-tx-uboot.git] / tools / image-host.c
1 /*
2  * Copyright (c) 2013, Google Inc.
3  *
4  * (C) Copyright 2008 Semihalf
5  *
6  * (C) Copyright 2000-2006
7  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8  *
9  * SPDX-License-Identifier:     GPL-2.0+
10  */
11
12 #include "mkimage.h"
13 #include <image.h>
14 #include <version.h>
15
16 /**
17  * fit_set_hash_value - set hash value in requested has node
18  * @fit: pointer to the FIT format image header
19  * @noffset: hash node offset
20  * @value: hash value to be set
21  * @value_len: hash value length
22  *
23  * fit_set_hash_value() attempts to set hash value in a node at offset
24  * given and returns operation status to the caller.
25  *
26  * returns
27  *     0, on success
28  *     -1, on failure
29  */
30 static 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 -1;
41         }
42
43         return 0;
44 }
45
46 /**
47  * fit_image_process_hash - Process a single subnode of the images/ node
48  *
49  * Check each subnode and process accordingly. For hash nodes we generate
50  * a hash of the supplised data and store it in the node.
51  *
52  * @fit:        pointer to the FIT format image header
53  * @image_name: name of image being processes (used to display errors)
54  * @noffset:    subnode offset
55  * @data:       data to process
56  * @size:       size of data in bytes
57  * @return 0 if ok, -1 on error
58  */
59 static 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
67         node_name = fit_get_name(fit, noffset, NULL);
68
69         if (fit_image_hash_get_algo(fit, noffset, &algo)) {
70                 printf("Can't get hash algo property for '%s' hash node in '%s' image node\n",
71                        node_name, image_name);
72                 return -1;
73         }
74
75         if (calculate_hash(data, size, algo, value, &value_len)) {
76                 printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n",
77                        algo, node_name, image_name);
78                 return -1;
79         }
80
81         if (fit_set_hash_value(fit, noffset, value, value_len)) {
82                 printf("Can't set hash value for '%s' hash node in '%s' image node\n",
83                        node_name, image_name);
84                 return -1;
85         }
86
87         return 0;
88 }
89
90 /**
91  * fit_image_write_sig() - write the signature to a FIT
92  *
93  * This writes the signature and signer data to the FIT.
94  *
95  * @fit: pointer to the FIT format image header
96  * @noffset: hash node offset
97  * @value: signature value to be set
98  * @value_len: signature value length
99  * @comment: Text comment to write (NULL for none)
100  *
101  * returns
102  *     0, on success
103  *     -FDT_ERR_..., on failure
104  */
105 static int fit_image_write_sig(void *fit, int noffset, uint8_t *value,
106                 int value_len, const char *comment, const char *region_prop,
107                 int region_proplen)
108 {
109         int string_size;
110         int ret;
111
112         /*
113          * Get the current string size, before we update the FIT and add
114          * more
115          */
116         string_size = fdt_size_dt_strings(fit);
117
118         ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
119         if (!ret) {
120                 ret = fdt_setprop_string(fit, noffset, "signer-name",
121                                          "mkimage");
122         }
123         if (!ret) {
124                 ret = fdt_setprop_string(fit, noffset, "signer-version",
125                                   PLAIN_VERSION);
126         }
127         if (comment && !ret)
128                 ret = fdt_setprop_string(fit, noffset, "comment", comment);
129         if (!ret)
130                 ret = fit_set_timestamp(fit, noffset, time(NULL));
131         if (region_prop && !ret) {
132                 uint32_t strdata[2];
133
134                 ret = fdt_setprop(fit, noffset, "hashed-nodes",
135                                    region_prop, region_proplen);
136                 strdata[0] = 0;
137                 strdata[1] = cpu_to_fdt32(string_size);
138                 if (!ret) {
139                         ret = fdt_setprop(fit, noffset, "hashed-strings",
140                                           strdata, sizeof(strdata));
141                 }
142         }
143
144         return ret;
145 }
146
147 static int fit_image_setup_sig(struct image_sign_info *info,
148                 const char *keydir, void *fit, const char *image_name,
149                 int noffset, const char *require_keys)
150 {
151         const char *node_name;
152         char *algo_name;
153
154         node_name = fit_get_name(fit, noffset, NULL);
155         if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
156                 printf("Can't get algo property for '%s' signature node in '%s' image node\n",
157                        node_name, image_name);
158                 return -1;
159         }
160
161         memset(info, '\0', sizeof(*info));
162         info->keydir = keydir;
163         info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
164         info->fit = fit;
165         info->node_offset = noffset;
166         info->algo = image_get_sig_algo(algo_name);
167         info->require_keys = require_keys;
168         if (!info->algo) {
169                 printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
170                        algo_name, node_name, image_name);
171                 return -1;
172         }
173
174         return 0;
175 }
176
177 /**
178  * fit_image_process_sig- Process a single subnode of the images/ node
179  *
180  * Check each subnode and process accordingly. For signature nodes we
181  * generate a signed hash of the supplised data and store it in the node.
182  *
183  * @keydir:     Directory containing keys to use for signing
184  * @keydest:    Destination FDT blob to write public keys into
185  * @fit:        pointer to the FIT format image header
186  * @image_name: name of image being processes (used to display errors)
187  * @noffset:    subnode offset
188  * @data:       data to process
189  * @size:       size of data in bytes
190  * @comment:    Comment to add to signature nodes
191  * @require_keys: Mark all keys as 'required'
192  * @return 0 if ok, -1 on error
193  */
194 static int fit_image_process_sig(const char *keydir, void *keydest,
195                 void *fit, const char *image_name,
196                 int noffset, const void *data, size_t size,
197                 const char *comment, int require_keys)
198 {
199         struct image_sign_info info;
200         struct image_region region;
201         const char *node_name;
202         uint8_t *value;
203         uint value_len;
204         int ret;
205
206         if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
207                                 require_keys ? "image" : NULL))
208                 return -1;
209
210         node_name = fit_get_name(fit, noffset, NULL);
211         region.data = data;
212         region.size = size;
213         ret = info.algo->sign(&info, &region, 1, &value, &value_len);
214         if (ret) {
215                 printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
216                        node_name, image_name, ret);
217
218                 /* We allow keys to be missing */
219                 if (ret == -ENOENT)
220                         return 0;
221                 return -1;
222         }
223
224         ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
225                         NULL, 0);
226         if (ret) {
227                 if (ret == -FDT_ERR_NOSPACE)
228                         return -ENOSPC;
229                 printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
230                        node_name, image_name, fdt_strerror(ret));
231                 return -1;
232         }
233         free(value);
234
235         /* Get keyname again, as FDT has changed and invalidated our pointer */
236         info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
237
238         /* Write the public key into the supplied FDT file */
239         if (keydest && info.algo->add_verify_data(&info, keydest)) {
240                 printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
241                        node_name, image_name);
242                 return -1;
243         }
244
245         return 0;
246 }
247
248 /**
249  * fit_image_add_verification_data() - calculate/set verig. data for image node
250  *
251  * This adds hash and signature values for an component image node.
252  *
253  * All existing hash subnodes are checked, if algorithm property is set to
254  * one of the supported hash algorithms, hash value is computed and
255  * corresponding hash node property is set, for example:
256  *
257  * Input component image node structure:
258  *
259  * o image@1 (at image_noffset)
260  *   | - data = [binary data]
261  *   o hash@1
262  *     |- algo = "sha1"
263  *
264  * Output component image node structure:
265  *
266  * o image@1 (at image_noffset)
267  *   | - data = [binary data]
268  *   o hash@1
269  *     |- algo = "sha1"
270  *     |- value = sha1(data)
271  *
272  * For signature details, please see doc/uImage.FIT/signature.txt
273  *
274  * @keydir      Directory containing *.key and *.crt files (or NULL)
275  * @keydest     FDT Blob to write public keys into (NULL if none)
276  * @fit:        Pointer to the FIT format image header
277  * @image_noffset: Requested component image node
278  * @comment:    Comment to add to signature nodes
279  * @require_keys: Mark all keys as 'required'
280  * @return: 0 on success, <0 on failure
281  */
282 int fit_image_add_verification_data(const char *keydir, void *keydest,
283                 void *fit, int image_noffset, const char *comment,
284                 int require_keys)
285 {
286         const char *image_name;
287         const void *data;
288         size_t size;
289         int noffset;
290
291         /* Get image data and data length */
292         if (fit_image_get_data(fit, image_noffset, &data, &size)) {
293                 printf("Can't get image data/size\n");
294                 return -1;
295         }
296
297         image_name = fit_get_name(fit, image_noffset, NULL);
298
299         /* Process all hash subnodes of the component image node */
300         for (noffset = fdt_first_subnode(fit, image_noffset);
301              noffset >= 0;
302              noffset = fdt_next_subnode(fit, noffset)) {
303                 const char *node_name;
304                 int ret = 0;
305
306                 /*
307                  * Check subnode name, must be equal to "hash" or "signature".
308                  * Multiple hash nodes require unique unit node
309                  * names, e.g. hash@1, hash@2, signature@1, etc.
310                  */
311                 node_name = fit_get_name(fit, noffset, NULL);
312                 if (!strncmp(node_name, FIT_HASH_NODENAME,
313                              strlen(FIT_HASH_NODENAME))) {
314                         ret = fit_image_process_hash(fit, image_name, noffset,
315                                                 data, size);
316                 } else if (IMAGE_ENABLE_SIGN && keydir &&
317                            !strncmp(node_name, FIT_SIG_NODENAME,
318                                 strlen(FIT_SIG_NODENAME))) {
319                         ret = fit_image_process_sig(keydir, keydest,
320                                 fit, image_name, noffset, data, size,
321                                 comment, require_keys);
322                 }
323                 if (ret)
324                         return -1;
325         }
326
327         return 0;
328 }
329
330 struct strlist {
331         int count;
332         char **strings;
333 };
334
335 static void strlist_init(struct strlist *list)
336 {
337         memset(list, '\0', sizeof(*list));
338 }
339
340 static void strlist_free(struct strlist *list)
341 {
342         int i;
343
344         for (i = 0; i < list->count; i++)
345                 free(list->strings[i]);
346         free(list->strings);
347 }
348
349 static int strlist_add(struct strlist *list, const char *str)
350 {
351         char *dup;
352
353         dup = strdup(str);
354         list->strings = realloc(list->strings,
355                                 (list->count + 1) * sizeof(char *));
356         if (!list || !str)
357                 return -1;
358         list->strings[list->count++] = dup;
359
360         return 0;
361 }
362
363 static const char *fit_config_get_image_list(void *fit, int noffset,
364                 int *lenp, int *allow_missingp)
365 {
366         static const char default_list[] = FIT_KERNEL_PROP "\0"
367                         FIT_FDT_PROP;
368         const char *prop;
369
370         /* If there is an "image" property, use that */
371         prop = fdt_getprop(fit, noffset, "sign-images", lenp);
372         if (prop) {
373                 *allow_missingp = 0;
374                 return *lenp ? prop : NULL;
375         }
376
377         /* Default image list */
378         *allow_missingp = 1;
379         *lenp = sizeof(default_list);
380
381         return default_list;
382 }
383
384 static int fit_config_get_hash_list(void *fit, int conf_noffset,
385                                     int sig_offset, struct strlist *node_inc)
386 {
387         int allow_missing;
388         const char *prop, *iname, *end;
389         const char *conf_name, *sig_name;
390         char name[200], path[200];
391         int image_count;
392         int ret, len;
393
394         conf_name = fit_get_name(fit, conf_noffset, NULL);
395         sig_name = fit_get_name(fit, sig_offset, NULL);
396
397         /*
398          * Build a list of nodes we need to hash. We always need the root
399          * node and the configuration.
400          */
401         strlist_init(node_inc);
402         snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name);
403         if (strlist_add(node_inc, "/") ||
404             strlist_add(node_inc, name))
405                 goto err_mem;
406
407         /* Get a list of images that we intend to sign */
408         prop = fit_config_get_image_list(fit, sig_offset, &len,
409                                         &allow_missing);
410         if (!prop)
411                 return 0;
412
413         /* Locate the images */
414         end = prop + len;
415         image_count = 0;
416         for (iname = prop; iname < end; iname += strlen(iname) + 1) {
417                 int noffset;
418                 int image_noffset;
419                 int hash_count;
420
421                 image_noffset = fit_conf_get_prop_node(fit, conf_noffset,
422                                                        iname);
423                 if (image_noffset < 0) {
424                         printf("Failed to find image '%s' in  configuration '%s/%s'\n",
425                                iname, conf_name, sig_name);
426                         if (allow_missing)
427                                 continue;
428
429                         return -ENOENT;
430                 }
431
432                 ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
433                 if (ret < 0)
434                         goto err_path;
435                 if (strlist_add(node_inc, path))
436                         goto err_mem;
437
438                 snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH,
439                          conf_name);
440
441                 /* Add all this image's hashes */
442                 hash_count = 0;
443                 for (noffset = fdt_first_subnode(fit, image_noffset);
444                      noffset >= 0;
445                      noffset = fdt_next_subnode(fit, noffset)) {
446                         const char *name = fit_get_name(fit, noffset, NULL);
447
448                         if (strncmp(name, FIT_HASH_NODENAME,
449                                     strlen(FIT_HASH_NODENAME)))
450                                 continue;
451                         ret = fdt_get_path(fit, noffset, path, sizeof(path));
452                         if (ret < 0)
453                                 goto err_path;
454                         if (strlist_add(node_inc, path))
455                                 goto err_mem;
456                         hash_count++;
457                 }
458
459                 if (!hash_count) {
460                         printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
461                                conf_name, sig_name, iname);
462                         return -ENOMSG;
463                 }
464
465                 image_count++;
466         }
467
468         if (!image_count) {
469                 printf("Failed to find any images for configuration '%s/%s'\n",
470                        conf_name, sig_name);
471                 return -ENOMSG;
472         }
473
474         return 0;
475
476 err_mem:
477         printf("Out of memory processing configuration '%s/%s'\n", conf_name,
478                sig_name);
479         return -ENOMEM;
480
481 err_path:
482         printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n",
483                iname, conf_name, sig_name, fdt_strerror(ret));
484         return -ENOENT;
485 }
486
487 static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
488                 struct image_region **regionp, int *region_countp,
489                 char **region_propp, int *region_proplen)
490 {
491         char * const exc_prop[] = {"data"};
492         struct strlist node_inc;
493         struct image_region *region;
494         struct fdt_region fdt_regions[100];
495         const char *conf_name, *sig_name;
496         char path[200];
497         int count, i;
498         char *region_prop;
499         int ret, len;
500
501         conf_name = fit_get_name(fit, conf_noffset, NULL);
502         sig_name = fit_get_name(fit, conf_noffset, NULL);
503         debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
504
505         /* Get a list of nodes we want to hash */
506         ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc);
507         if (ret)
508                 return ret;
509
510         /* Get a list of regions to hash */
511         count = fdt_find_regions(fit, node_inc.strings, node_inc.count,
512                         exc_prop, ARRAY_SIZE(exc_prop),
513                         fdt_regions, ARRAY_SIZE(fdt_regions),
514                         path, sizeof(path), 1);
515         if (count < 0) {
516                 printf("Failed to hash configuration '%s/%s': %s\n", conf_name,
517                        sig_name, fdt_strerror(ret));
518                 return -EIO;
519         }
520         if (count == 0) {
521                 printf("No data to hash for configuration '%s/%s': %s\n",
522                        conf_name, sig_name, fdt_strerror(ret));
523                 return -EINVAL;
524         }
525
526         /* Build our list of data blocks */
527         region = fit_region_make_list(fit, fdt_regions, count, NULL);
528         if (!region) {
529                 printf("Out of memory hashing configuration '%s/%s'\n",
530                        conf_name, sig_name);
531                 return -ENOMEM;
532         }
533
534         /* Create a list of all hashed properties */
535         debug("Hash nodes:\n");
536         for (i = len = 0; i < node_inc.count; i++) {
537                 debug("   %s\n", node_inc.strings[i]);
538                 len += strlen(node_inc.strings[i]) + 1;
539         }
540         region_prop = malloc(len);
541         if (!region_prop) {
542                 printf("Out of memory setting up regions for configuration '%s/%s'\n",
543                        conf_name, sig_name);
544                 return -ENOMEM;
545         }
546         for (i = len = 0; i < node_inc.count;
547              len += strlen(node_inc.strings[i]) + 1, i++)
548                 strcpy(region_prop + len, node_inc.strings[i]);
549         strlist_free(&node_inc);
550
551         *region_countp = count;
552         *regionp = region;
553         *region_propp = region_prop;
554         *region_proplen = len;
555
556         return 0;
557 }
558
559 static int fit_config_process_sig(const char *keydir, void *keydest,
560                 void *fit, const char *conf_name, int conf_noffset,
561                 int noffset, const char *comment, int require_keys)
562 {
563         struct image_sign_info info;
564         const char *node_name;
565         struct image_region *region;
566         char *region_prop;
567         int region_proplen;
568         int region_count;
569         uint8_t *value;
570         uint value_len;
571         int ret;
572
573         node_name = fit_get_name(fit, noffset, NULL);
574         if (fit_config_get_data(fit, conf_noffset, noffset, &region,
575                                 &region_count, &region_prop, &region_proplen))
576                 return -1;
577
578         if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset,
579                                 require_keys ? "conf" : NULL))
580                 return -1;
581
582         ret = info.algo->sign(&info, region, region_count, &value, &value_len);
583         free(region);
584         if (ret) {
585                 printf("Failed to sign '%s' signature node in '%s' conf node\n",
586                        node_name, conf_name);
587
588                 /* We allow keys to be missing */
589                 if (ret == -ENOENT)
590                         return 0;
591                 return -1;
592         }
593
594         ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
595                                 region_prop, region_proplen);
596         if (ret) {
597                 if (ret == -FDT_ERR_NOSPACE)
598                         return -ENOSPC;
599                 printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
600                        node_name, conf_name, fdt_strerror(ret));
601                 return -1;
602         }
603         free(value);
604         free(region_prop);
605
606         /* Get keyname again, as FDT has changed and invalidated our pointer */
607         info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
608
609         /* Write the public key into the supplied FDT file */
610         if (keydest) {
611                 ret = info.algo->add_verify_data(&info, keydest);
612                 if (ret) {
613                         printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
614                                node_name, conf_name);
615                         return ret == FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
616                 }
617         }
618
619         return 0;
620 }
621
622 static int fit_config_add_verification_data(const char *keydir, void *keydest,
623                 void *fit, int conf_noffset, const char *comment,
624                 int require_keys)
625 {
626         const char *conf_name;
627         int noffset;
628
629         conf_name = fit_get_name(fit, conf_noffset, NULL);
630
631         /* Process all hash subnodes of the configuration node */
632         for (noffset = fdt_first_subnode(fit, conf_noffset);
633              noffset >= 0;
634              noffset = fdt_next_subnode(fit, noffset)) {
635                 const char *node_name;
636                 int ret = 0;
637
638                 node_name = fit_get_name(fit, noffset, NULL);
639                 if (!strncmp(node_name, FIT_SIG_NODENAME,
640                              strlen(FIT_SIG_NODENAME))) {
641                         ret = fit_config_process_sig(keydir, keydest,
642                                 fit, conf_name, conf_noffset, noffset, comment,
643                                 require_keys);
644                 }
645                 if (ret)
646                         return ret;
647         }
648
649         return 0;
650 }
651
652 int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
653                               const char *comment, int require_keys)
654 {
655         int images_noffset, confs_noffset;
656         int noffset;
657         int ret;
658
659         /* Find images parent node offset */
660         images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
661         if (images_noffset < 0) {
662                 printf("Can't find images parent node '%s' (%s)\n",
663                        FIT_IMAGES_PATH, fdt_strerror(images_noffset));
664                 return images_noffset;
665         }
666
667         /* Process its subnodes, print out component images details */
668         for (noffset = fdt_first_subnode(fit, images_noffset);
669              noffset >= 0;
670              noffset = fdt_next_subnode(fit, noffset)) {
671                 /*
672                  * Direct child node of the images parent node,
673                  * i.e. component image node.
674                  */
675                 ret = fit_image_add_verification_data(keydir, keydest,
676                                 fit, noffset, comment, require_keys);
677                 if (ret)
678                         return ret;
679         }
680
681         /* If there are no keys, we can't sign configurations */
682         if (!IMAGE_ENABLE_SIGN || !keydir)
683                 return 0;
684
685         /* Find configurations parent node offset */
686         confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
687         if (confs_noffset < 0) {
688                 printf("Can't find images parent node '%s' (%s)\n",
689                        FIT_IMAGES_PATH, fdt_strerror(confs_noffset));
690                 return -ENOENT;
691         }
692
693         /* Process its subnodes, print out component images details */
694         for (noffset = fdt_first_subnode(fit, confs_noffset);
695              noffset >= 0;
696              noffset = fdt_next_subnode(fit, noffset)) {
697                 ret = fit_config_add_verification_data(keydir, keydest,
698                                                        fit, noffset, comment,
699                                                        require_keys);
700                 if (ret)
701                         return ret;
702         }
703
704         return 0;
705 }
706
707 #ifdef CONFIG_FIT_SIGNATURE
708 int fit_check_sign(const void *working_fdt, const void *key)
709 {
710         int cfg_noffset;
711         int ret;
712
713         cfg_noffset = fit_conf_get_node(working_fdt, NULL);
714         if (!cfg_noffset)
715                 return -1;
716
717         ret = fit_config_verify(working_fdt, cfg_noffset);
718         return ret;
719 }
720 #endif