two questions on verified boot
Rasmus Villemoes
rasmus.villemoes at prevas.dk
Sun Nov 21 15:55:50 CET 2021
(1) When one wants to get rid of CONFIG_LEGACY_IMAGE_FORMAT, one also
has to wrap any boot script in a FIT rather than a uImage. While it's
not directly documented anywhere how to do that, it seems that a minimal
.its for achieving it is
/dts-v1/;
/ {
description = "U-Boot script(s)";
images {
default = "boot";
boot {
description = "Bootscript";
data = /incbin/("boot.txt");
type = "script";
compression = "none";
hash-1 {
algo = "sha256";
};
};
};
};
[The UX when one doesn't guess that the description string is mandatory
is rather sad, but that's a separate story.]
Now, I can get that signed if I include a signature-foo node inside the
"boot" node, and also add a dummy empty /configurations node (otherwise
mkimage refuses to process it). But that will only work if I have added
a "required = image" property with the public key; if I want to use the
safer/saner "required = conf", how do I make sure any boot script is
properly signed?
The code in source.c only cares about the images node and calls
fit_image_verify(), and there's no concept of "configuration" and
combining multiple images when talking about a simple boot script.
(2) Assuming for the moment that I would be happy with just using
required=image, am I right in that not only does that mean that the
combination of kernel/fdt/initramfs is not verified, merely the
individual parts, but more importantly (a mix'n'match attack isn't
really very likely), _only_ the data property in each node is part of
what gets signed, not the other important properties such as load= and
entry=? IOW, suppose I have a FIT image with
images {
kernel {
data = blabla;
load = 0x1000000;
entry = 0x10000000;
signature {
... // correct signature of blabla
};
};
};
and I know that the boot process uses $loadaddr = 0x40000000. What is to
stop me from modifying that FIT image to read
images {
kernel {
data = blabla;
load = 0x1000000;
entry = 0x400abcde;
signature {
... // correct signature of blabla
};
};
};
some-other-node {
pwned = /incbin/("pwned");
};
where 0xabcde is chosen to coincide with where the data part of the
pwned property lies in the modified FIT? (That pwned property can be put
anywhere; I could even just replace the signer-name property inside the
signature node with a value of "mkimage\0<padding><my payload>".)
In fit_config_process_sig(), there's this elaborate dance with
fit_config_get_data()/fdt_find_regions() which, AFAICT, ends up
including all the property values (and the FDT_PROP tags and string
offsets etc.), and then we call info.crypto->sign() with some
appropriate region_count. But in fit_image_process_sig(), we call
info.crypto->sign() with nregions==1, and AFAICT, the data being signed
is just the value of the "data" property, nothing else.
Rasmus
More information about the U-Boot
mailing list