FIT Signing
In order to do FIT signing for kernel or U-Boot signing following actions/configurations are required
- Product is created with a configuration which supports FIT image signing.
- Product operation SignUBoot has been configured
- Product operation SignKernel has been configured
Product configuration¶
- Create product with needed signing operations.
- Check product.
Input data for FIT signing¶
The input is a U-Boot FIT image (Flattened Image Tree), a binary file in FDT format (magic bytes: 0xd00dfeed). The file must be base64-encoded before uploading to the platform.
Requirements¶
The FIT image must contain:
- One or more sub-images (e.g. kernel, device tree blob, ramdisk, boot script)
- SHA hashes of each sub-image
- A signature node where the platform will write the cryptographic signature
The signature node in the FIT image specifies the signing algorithm and key reference. For example:
algo = "sha256,rsa4096"
key-name-hint = "uboot"
sign-images = "kernel", "fdt", "ramdisk", "script"
Note
The platform supports different hash algorithms (e.g. SHA-256, SHA-512) and key sizes (e.g. RSA-2048, RSA-4096). The values shown above are examples. Configure them according to your product's security requirements.
Example FIT image contents¶
A FIT image may contain for example:
- Linux kernel (compressed)
- Device tree blob
- Initramfs / ramdisk
- U-Boot boot script
- SHA hashes of each sub-image
- A signature node
Output¶
The platform returns the complete FIT image as raw binary (not base64) with the RSA signature node updated. The output is a valid FIT image that U-Boot can verify.
Specifically, within the FIT DTB structure at the signature node path (e.g. /configurations/main/signature-1/):
value: the RSA signature byteshashed-nodes: list of signed node pathshashed-strings: DTB strings regiontimestamp: signing timestamp
This is equivalent to what mkimage -F -k <key_dir> <fit.itb> produces. It re-signs an existing FIT image in place.
Developer example: preparing a FIT image for signing¶
1. Create the FIT image source (.its)¶
Define a FIT image tree source file that includes a signature node. Example fitImage.its:
/dts-v1/;
/ {
description = "Kernel and ramdisk FIT image";
#address-cells = <1>;
images {
kernel {
description = "Linux kernel";
data = /incbin/("Image.lz4");
type = "kernel";
arch = "arm64";
os = "linux";
compression = "lz4";
load = <0x00080000>;
entry = <0x00080000>;
hash-1 {
algo = "sha256";
};
};
fdt {
description = "Device tree";
data = /incbin/("system.dtb");
type = "flat_dt";
arch = "arm64";
compression = "none";
hash-1 {
algo = "sha256";
};
};
ramdisk {
description = "Initramfs";
data = /incbin/("initramfs.cpio.gz");
type = "ramdisk";
arch = "arm64";
os = "linux";
compression = "none";
hash-1 {
algo = "sha256";
};
};
};
configurations {
default = "main";
main {
description = "Boot configuration";
kernel = "kernel";
fdt = "fdt";
ramdisk = "ramdisk";
signature-1 {
algo = "sha256,rsa4096";
key-name-hint = "uboot";
sign-images = "kernel", "fdt", "ramdisk";
};
};
};
};
Note
The algo, key-name-hint, and sign-images fields must match your product operation configuration. The platform supports different SHA modes and RSA key sizes. The values above are examples.
2. Build the FIT image¶
mkimage -f fitImage.its fitImage.itb
This produces a binary .itb file containing the sub-images and an empty signature node ready for signing.
3. Submit to the LAAVAT Platform¶
The FIT image is base64-encoded and uploaded via the standard image signing flow. See the usage example below.
4. Embed the public key into U-Boot¶
The FIT signing public key must be embedded into U-Boot's control DTB at build time so U-Boot can verify FIT signatures at boot. There are different ways to achieve this (e.g. using fdt_add_pubkey, adding the key directly in the .its source, or other methods). The following example uses the fdt_add_pubkey approach:
- Retrieve the public key from the signing service via
GET /products/{id}. TheproductOperations[].token.publicKeyfield contains the RSA public key in base64-encoded PEM format. -
Create an X.509 certificate wrapping the public key. U-Boot's
fdt_add_pubkeytool requires an X.509.crtfile:# Generate a throwaway key (only used to self-sign the wrapper cert) openssl genrsa -out throwaway.key 2048 openssl req -new -key throwaway.key -out throwaway.csr -subj "/CN=HSM Key" # Create cert with the actual HSM public key openssl x509 -req \ -in throwaway.csr \ -signkey throwaway.key \ -force_pubkey hsm-public-key.pem \ -out fit-sign.crt \ -days 36500 -
Inject the public key into U-Boot's DTB:
fdt_add_pubkey \ -a sha256,rsa4096 \ -k <directory-containing-fit-sign.crt> \ -n "uboot" \ -r conf \ u-boot-control.dtb -
The resulting U-Boot control DTB (with the embedded public key) is then included in the boot image (e.g.
boot.binfor Zynq platforms). This establishes the chain of trust:eFuse PPK hash -> verifies boot.bin (contains U-Boot with embedded FIT public key) -> U-Boot verifies FIT image signature -> FIT contains kernel, DTB, initramfs (all covered by signature)
Note
This is just one possible approach. Consult U-Boot documentation for other methods of embedding the verification public key.
Note
The key-name-hint property in the FIT image is only a hint. U-Boot verification can proceed by checking all available signing keys until one matches. When using mkimage with a key directory (-k), the key-name-hint is used to locate the key file at <keydir>/<key-name-hint>.<ext>. Consult U-Boot documentation for details.
Example usage with reference client package: FIT signing¶
FIT signing examples ($TOKEN contains the "regular" user token and $APPROVERTOKEN contains a token for a user that's in the approvers group):
(venv) $ signing-tool -c -t $TOKEN -a https://app.laavat.io/<CustomerName>/api/v1 imagesigning add SignUBoot \
-N test -D test2 -P adcb30d8-f009-438e-b1b2-96f507b306cb --operid 4add90e9-ffb3-4708-9554-ed2e82e8fd71 -F linux-uImage.bin
# Approve the cst signing request
(venv) $ signing-tool -c -t $APPROVERTOKEN -a https://app.laavat.io/<CustomerName>/api/v1 imagesigning approve \
-I a83081a6-1d3b-4117-a81b-0ebcfcf0669c
# Get the signed payload
(venv) $signing-tool -c -t $TOKEN -a https://app.laavat.io/<CustomerName>/api/v1 imagesigning get \
-I a83081a6-1d3b-4117-a81b-0ebcfcf0669c -O /tmp/signed.bin