[PATCH 00/16] tools: Add support for signing devicetree blobs

Rasmus Villemoes rasmus.villemoes at prevas.dk
Fri Nov 26 09:36:42 CET 2021


On 12/11/2021 20.28, Simon Glass wrote:
> At present mkimage supports signing FITs, the standard U-Boot image type.
> 
> Various people are opposed to using FIT since:
> 
> a) it requires adding support for FIT into other bootloaders, notably
>    UEFI
> b) it requires packaging a kernel in this standard U-Boot format, meaning
>    that distros must run 'mkimage' and deal with the kernel and initrd
>    being inside a FIT
> 
> The kernel and initrd can be dealt with in other ways. But without FIT,
> we have no standard way of signing and grouping FDT files. Instead we must
> include them in the distro as separate files.
> 
> In particular, some sort of mechanism for verifying FDT files is needed.
> One option would be to tack a signature on before or after the file,
> processing it accordingly. But due to the nature of the FDT binary format,
> it is possible to embed a signature inside the FDT itself, which is very
> convenient.
> 
> This series provides a tool, fdt_sign, which can add a signature to an
> FDT. The signature can be checked later, preventing any change to the FDT,
> other than in permitted nodes (e.g. /chosen).
> 
> This series also provides a fdt_check_sign tool, used to check signatures.

This could be useful. Not because I'm interested in signing device-tree
blobs as such, but as a replacement for the current incomprehensible way
FIT images are signed and verified. This seems to be a much better and
simpler scheme, that avoids (can avoid) the overly simplistic approach
of signing just image nodes, and the way too complex
signing-configurations-and-then-add-a-property-saying-which-nodes-I-signed-and-sign-that-as-well.

In order not to hard-code anything in the tool about /chosen or whatnot,
make the rule be that the blob (I'll use that word, because it can as
well be a FIT image containing kernel image+initramfs etc., or a FIT
containing a U-Boot script) has a property in the top node

  unsigned-nodes = "/chosen", "/signatures";

(maybe it could be

  unsigned-nodes = <&chosen &sigs>

but that may make the implementation a little more complex). That
property itself is by definition part of what gets signed. The verifier
can and should choose to reject the whole thing if "/" is mentioned.

Then, please, for debugging, inside the /signatures node, beside the
signature data, also add a copy of the offset/len pairs that were
actually hashed, and that hash value.

  /signatures {
    hashed-regions = <offset0 len0 offset1 len1 ...>;
    hash-1 {
      value = 0xabcd;
      algo = "sha256";
    };
    signature-1 {
       ...
    };
    ...

And make the tool start by adding dummy properties, so those strings
"hashed-regions", "value", "algo", "signer" and whatever other property
names are used already exist in the string table. After that, fill in
the actual values - and have the rule that the entire string table is
hashed, not just some initial part of it.

The verifier will of course not rely on /signatures/hashed-regions, but
will compute the regions itself based on /unsigned-nodes (and implicitly
add a region consisting of the string table and the memreserve table).

Then we'd have a generic scheme for signing blobs, disentangled from
whether they are actually describing hardware or used as a generic
container format. And instead of "image" or "conf", we could mark a
public key as being required for "whole-blob" (bikeshedding welcome),
using that same scheme for verifying a container with a boot script and
a container with kernel+initramfs+dtbs.
> For now there is absolutely no configurability in the signature mechanism.
> It would of course be possible to adjust which nodes are signed, as is

Yes, let the blob itself define that. And don't add any ad hoc "oh, skip
a property if it is called data-offset or data or...".

Rasmus


More information about the U-Boot mailing list