[U-Boot] Complete verified uboot example

Rick Altherr raltherr at google.com
Wed Feb 22 18:51:22 UTC 2017


On Tue, Feb 21, 2017 at 10:08 AM, Ron Brash <ron.brash at gmail.com> wrote:

> Hello all,
>
> I am adding verified kernel support on a board we are using and I am
> struggling to fully understand all of the concepts and steps required to
> pull everything together (on ARM, using ZImages and booting with a working
> DTB on 4.4.3x).  I also looked at the test script inside of examples, but
> it left me with more questions than understanding.
>
> Please correct me where appropriate in my understanding, but if I am
> confused, likely others are too and I hope this helps everyone involved
> overall.
>

You've asked some really good questions.  Hopefully this discussion will
end up with patches to clarify the docs.


>
> Steps:
> ---------------------------------------------------------------
>
> First, u-boot needs to have the appropriate features enabled and to be
> built using them.  At a minimum, I suspect:
>
> CONFIG_RSA=y
> CONFIG_FIT=y
> CONFIG_FIT_SIGNATURE=y
> CONFIG_OF_CONTROL=y
>
>
Yup.  That looks right.


> Next, we need to derive the appropriate cryptographic primitives/keys.
>
> #Generate a private signing key (RSA2048):
> openssl genrsa -F4 -out \
> "${key_dir}"/"${key_name}".key 2048
>
> # Generate a public key:
> openssl req -batch -new -x509 \
> -key "${key_dir}"/"${key_name}".key \
> -out "${key_dir}"/"${key_name}".crt
>
>
So far so good.  In general, I suggest having multiple signing keys.  You
can put all the public keys in your u-boot so an image signed with any of
those keys will be accepted.  If you happen to have a signing key
compromised, you can switch to one of the other ones.  With that other key,
you can sign an update the removes the compromised public key from future
images.


> Then we derive the ITS or image source file - a file that hints/describes
> the elements that will be verified and/or inside of the FIT image?  Lets
> call this $FIT_ITS
>
> FIT is a container format.  Generally, you'll create a FIT that contains
the zImage, dtb, initramfs, etc.  With FIT support enabled in u-boot, you
only need to provide the single FIT image address to 'bootm'.  u-boot will
use the config section to find the individual elements, load them into RAM
as needed, and boot.


> / dts - v1 /;
> / {
> description = "Configuration to load a Xen Kernel";
> #address-cells = <1>;
> images {
> linux_kernel @ 1 {
> description = "Linux zImage";
> data = /incbin / ("pathToImage/zImage");
> type = "kernel";
> arch = "arm";
> os = "linux";
> compression = "none";
> load = <0xaf600000 >;
> entry = <0xaf600000 >;
> hash @ 1 {
> algo = "sha1";
> };
> };
> fdt @ 1 {
> description = "FDT blob";
> data = /incbin / ("PathToDTBUsedByBootingKernel/ex.dtb");
> type = "flat_dt";
> arch = "arm";
> compression = "none";
> load = <0xaec00000 >;
>

You generally don't need a 'load' property for the FDT or an initramfs.
Without one, U-Boot will allocate RAM dynamically, if needed, and pass the
relocated address to the kernel.

hash @ 1 {
> algo = "sha1";
> };
> };
> };
> configurations {
> default = "config at 1";
> config @ 1 {
> description = "Plain Linux";
> kernel = "linux_kernel at 1";
> fdt = "fdt at 1";
> loadables = "linux_kernel at 1";
>

'loadables' is for other types of firmware.  You only need the 'kernel'
property for loading and booting the kernel.


> };
> };
> };
>
> Question: Does a signature section go into this as well? underneath the
> hash node for each value?


> signature at 1 {
>      algo = "sha1,rsa2048";
>      value = <...kernel signature 1...>
>  };
>

You add a signature section to each image you want signed within the FIT.
In your case, add one for both the kernel and FDT images.  Signatures go
_next_ to the hash section, not in it.  Omit the 'value' property as it
will be generated for you later.


>
> Then using the device-tree-compiler (dtc), I create a DTB for u-boot.  This
> is the control FDT and this defines what keys are used etc..
>

The control FDT is used for U-Boot's driver model _as well as_ providing
public keys for verifying images.  Your board may not currently use a
control FDT in which case you create one from scratch.


>
> #Assemble control FDT for U-Boot with space for public key:
> $DTC -p 0x1000 u-boot.dts -O dtb -o u-boot.dtb
>
> Question: What is required inside of the u-boot.dts for u-boot?  Is it
> simply the same .dts used by the booting kernel, but with a section
> proclaiming the keys?
>

This depends on the board you are using.  For example, an AST2500 requires
a DTB for U-Boot to load the right drivers.  The DTB used by U-Boot is
slightly different from that used by Linux as the Linux DTB often includes
addition configuration information.  When using verified boot, the U-Boot
DTB includes the public keys whereas the FDT/DTB stored in the FIT does not
as Linux doesn't need them.


>
> Question:  Where will the compiled u-boot.dtb eventually go?  Is this put
> into a FIT image, or flashed onto the board alongside the u-boot bootloader
> itself?
>

The U-Boot control FDT is compiled into the U-Boot binary.  The FDT in the
FIT is the FDT that is provided to Linux.


>
> Next, given that the above steps are completed, I need to create a FIT
> image with space for the signature.
>
> # Generate fitImage with space for signature:
> $MKIMG -D "-I dts -O dtb -p 2000" \
> -f f$FIT_ITS $FIT_IMG
>
> Question: Is the FIT_IMAGE the actual zimage or is it an output image that
> contains all of the values contained within the ITS?
>

The latter.  It will have a compiled version of the ITS as well as the
actual images specified in the ITS (kernel, fdt).


>
> Next this FIT_IMAGE (assuming that this is the final FIT image that
> contains the FDT and zImage) needs to be signed and the public key added to
> it; given that that the key information is in the uboot.
>

You sign the FIT_IMAGE and put the public keys in the control DTB.


>
> # Sign fitImage and add public key into u-boot.dtb:
> $MKIMG -D "-I dts -O dtb -p 2000" -F \
> -k "${key dir}" -K u-boot.dtb -r $FIT_IMG
>

This is putting the public keys used by the FIT image into the control DTB


>
> Then, we sign the subsequent fitImage again - correct?
>
> # Signing subsequent fitImage:
> $MKIMG -D "-I dts -O dtb -p 2000" \
> -k "${key dir}" -f $FIT_ITS -r $FIT_IMG
>

This is generating signatures for the images in the FIT and storing those
signatures in the FIT.


>
> Now that all of the above is done - we need to:
> 1. Write our uboot to the flash
> 2. Write our FIT_IMAGE to flash
>
> Question: Do we write anything else to persistent storage? The ITS? etc..
>

No.  Everything is contained in the U-Boot binary (control FDT including
public keys) and the FIT (images, signatures)

>
> Question: Do we just boot using anything else or just bootm
> 0xLocationOfTheFitImageInRAM
>

The latter.  bootm will check the config section in the FIT and use the
kernel, fdt, etc specified there.


>
> Greatly appreciate any assistance to all of these questions and I'm sure
> this threat will be of interest to anyone else too.
>
> Thanks!

_______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>


More information about the U-Boot mailing list