diff options
-rw-r--r-- | tools/binman/ftest.py | 8 | ||||
-rw-r--r-- | tools/fit_image.c | 80 |
2 files changed, 74 insertions, 14 deletions
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 1e570aba287..3d556535e07 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -4019,7 +4019,7 @@ class TestFunctional(unittest.TestCase): self.assertEqual({ 'image-pos': 0, 'offset': 0, - 'size': 1890, + 'size': 1378, 'u-boot:image-pos': 0, 'u-boot:offset': 0, @@ -4027,7 +4027,7 @@ class TestFunctional(unittest.TestCase): 'fit:image-pos': 4, 'fit:offset': 4, - 'fit:size': 1840, + 'fit:size': 1328, 'fit/images/kernel:image-pos': 304, 'fit/images/kernel:offset': 300, @@ -4045,8 +4045,8 @@ class TestFunctional(unittest.TestCase): 'fit/images/fdt-1/u-boot-spl-dtb:offset': 0, 'fit/images/fdt-1/u-boot-spl-dtb:size': 6, - 'u-boot-nodtb:image-pos': 1844, - 'u-boot-nodtb:offset': 1844, + 'u-boot-nodtb:image-pos': 1332, + 'u-boot-nodtb:offset': 1332, 'u-boot-nodtb:size': 46, }, props) diff --git a/tools/fit_image.c b/tools/fit_image.c index 8fdde012bda..8717dc9a3b1 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -24,6 +24,65 @@ static struct legacy_img_hdr header; +static int fit_estimate_hash_sig_size(struct image_tool_params *params, const char *fname) +{ + bool signing = IMAGE_ENABLE_SIGN && (params->keydir || params->keyfile); + struct stat sbuf; + void *fdt; + int fd; + int estimate = 0; + int depth, noffset; + const char *name; + + fd = mmap_fdt(params->cmdname, fname, 0, &fdt, &sbuf, false, true); + if (fd < 0) + return -EIO; + + /* + * Walk the FIT image, looking for nodes named hash* and + * signature*. Since the interesting nodes are subnodes of an + * image or configuration node, we are only interested in + * those at depth exactly 3. + * + * The estimate for a hash node is based on a sha512 digest + * being 64 bytes, with another 64 bytes added to account for + * fdt structure overhead (the tags and the name of the + * "value" property). + * + * The estimate for a signature node is based on an rsa4096 + * signature being 512 bytes, with another 512 bytes to + * account for fdt overhead and the various other properties + * (hashed-nodes etc.) that will also be filled in. + * + * One could try to be more precise in the estimates by + * looking at the "algo" property and, in the case of + * configuration signatures, the sign-images property. Also, + * when signing an already created FIT image, the hash nodes + * already have properly sized value properties, so one could + * also take pre-existence of "value" properties in hash nodes + * into account. But this rather simple approach should work + * well enough in practice. + */ + for (depth = 0, noffset = fdt_next_node(fdt, 0, &depth); + noffset >= 0 && depth > 0; + noffset = fdt_next_node(fdt, noffset, &depth)) { + if (depth != 3) + continue; + + name = fdt_get_name(fdt, noffset, NULL); + if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) + estimate += 128; + + if (signing && !strncmp(name, FIT_SIG_NODENAME, strlen(FIT_SIG_NODENAME))) + estimate += 1024; + } + + munmap(fdt, sbuf.st_size); + close(fd); + + return estimate; +} + static int fit_add_file_data(struct image_tool_params *params, size_t size_inc, const char *tmpfile) { @@ -844,16 +903,16 @@ static int fit_handle_file(struct image_tool_params *params) rename(tmpfile, bakfile); /* - * Set hashes for images in the blob. Unfortunately we may need more - * space in either FDT, so keep trying until we succeed. - * - * Note: this is pretty inefficient for signing, since we must - * calculate the signature every time. It would be better to calculate - * all the data and then store it in a separate step. However, this - * would be considerably more complex to implement. Generally a few - * steps of this loop is enough to sign with several keys. + * Set hashes for images in the blob and compute + * signatures. We do an attempt at estimating the expected + * extra size, but just in case that is not sufficient, keep + * trying adding 1K, with a reasonable upper bound of 64K + * total, until we succeed. */ - for (size_inc = 0; size_inc < 64 * 1024; size_inc += 1024) { + size_inc = fit_estimate_hash_sig_size(params, bakfile); + if (size_inc < 0) + goto err_system; + do { if (copyfile(bakfile, tmpfile) < 0) { printf("Can't copy %s to %s\n", bakfile, tmpfile); ret = -EIO; @@ -862,7 +921,8 @@ static int fit_handle_file(struct image_tool_params *params) ret = fit_add_file_data(params, size_inc, tmpfile); if (!ret || ret != -ENOSPC) break; - } + size_inc += 1024; + } while (size_inc < 64 * 1024); if (ret) { fprintf(stderr, "%s Can't add hashes to FIT blob: %d\n", |