Skip to content

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

  1. Create product with needed signing operations.
    1. 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 bytes
  • hashed-nodes: list of signed node paths
  • hashed-strings: DTB strings region
  • timestamp: 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:

  1. Retrieve the public key from the signing service via GET /products/{id}. The productOperations[].token.publicKey field contains the RSA public key in base64-encoded PEM format.
  2. Create an X.509 certificate wrapping the public key. U-Boot's fdt_add_pubkey tool requires an X.509 .crt file:

    # 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
    
  3. 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
    
  4. The resulting U-Boot control DTB (with the embedded public key) is then included in the boot image (e.g. boot.bin for 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