Enabling a bootloader chain using child and parent images (deprecated)

Note

This feature is now deprecated. See Enabling a bootloader chain using sysbuild.

You can add a bootloader chain to an application in the following ways:

While you can use temporary configurations for quickly experimenting with different configurations from build to build, the recommended method is to implement your bootloader chain with permanent configurations.

Both Kconfig fragments and Kconfig project configuration files use the same Kconfig syntax for configurations. You can add bootloader chains to nearly any sample in nRF Connect SDK or Zephyr for rapid testing and experimentation.

Choose the bootloader type depending on your application needs. For detailed information about the bootloader support in the nRF Connect SDK and the general architecture, see Secure bootloader chain.

Adding an immutable bootloader

The following sections describe how to add either nRF Secure Immutable Bootloader or MCUboot as an immutable bootloader.

Adding nRF Secure Immutable Bootloader as an immutable bootloader

To build nRF Secure Immutable Bootloader with a Zephyr or nRF Connect SDK sample, enable the CONFIG_SECURE_BOOT in the application’s prj.conf file, in an associated Kconfig fragment, or using the command line:

west build -b nrf52840dk/nrf52840 zephyr/samples/hello_world -- -DCONFIG_SECURE_BOOT=y

See Configuring and building for information on how to set the required configuration options temporarily or permanently.

Like other child images, image-specific configurations can be assigned at build time to further customize the bootloader’s functionality.

To ensure that the immutable bootloader occupies as little flash memory as possible, you can also apply the prj_minimal.conf configuration:

west build -b nrf52840dk/nrf52840 zephyr/samples/hello_world -- \
-DCONFIG_SECURE_BOOT=y \
-Db0_CONF_FILE=prj_minimal.conf

See Customizing the bootloader for more information about using Kconfig fragments.

Configuring nRF Secure Immutable Bootloader as an immutable bootloader

The following sections describe different configuration options available for nRF Secure Immutable Bootloader as an immutable bootloader.

Adding a custom signature key file

To add a signature key file to this bootloader, set the CONFIG_SB_SIGNING_KEY_FILE option in the application’s prj.conf file, in an associated Kconfig fragment, or using the command line:

CONFIG_SB_SIGNING_KEY_FILE="priv.pem"

This option only accepts the private key of an ECDSA key pair, as build system scripts automatically extract the public key at build time.

The file argument must be a string and is specified in one of the following ways:

  • The relative path to the file from the application configuration directory (if this is not set, then it will be the same as the application source directory).

    • If the prj.conf file is external to the directory, the key’s location is determined relative to the application directory, not to the configuration file.

  • The absolute path to the file.

For example, if a directory named _keys located in /home/user/ncs contains signing keys, you can provide the path in the following ways:

CONFIG_SB_SIGNING_KEY_FILE="../../_keys/priv.pem"

Or

CONFIG_SB_SIGNING_KEY_FILE="/home/user/ncs/_keys/priv.pem"

Note

The public key string must be an absolute path to the location of the public key file. Environment variables (like $HOME, $PWD, or $USER) and the ~ character on Unix systems are not expanded when setting an absolute path from a prj.conf file or Kconfig fragment, but are expanded correctly in key file paths from the command line that are not given as strings.

You can find specific configuration options for keys with this bootloader in nrf/subsys/bootloader/Kconfig.

See Signature keys for information on how to generate custom keys for a project.

Additionally, the nRF Secure Immutable Bootloader supports the following methods for signing images with private keys:

The OpenSSL method is handled internally by the build system, whereas using custom commands requires more configuration steps.

Checking the public key

You can check that the bootloader image is correctly compiled with the custom signing key by comparing its auto-generated public key against a manual public key dump using OpenSSL. You can do this with diff, running the following command from a terminal:

diff build/zephyr/nrf/subsys/bootloader/generated/public.pem <(openssl ec -in priv.pem -pubout)

If there is no file diff output, then the private key has been successfully included in the bootloader image.

Custom signing commands

If you want complete control over the key handling of a project, you can use a custom signing command with nRF Secure Immutable Bootloader. Using a custom signing command removes the need to use of a private key from the build system. This is useful when the private keys are stored, managed, or otherwise processed through a hardware security module (HSM) or an in-house tool.

To use a custom signing command with this bootloader, set the following options in the application’s prj.conf file, in an associated Kconfig fragment, or using the command line:

CONFIG_SECURE_BOOT=y
CONFIG_SB_SIGNING_CUSTOM=y
CONFIG_SB_SIGNING_PUBLIC_KEY="/path/to/pub.pem"
CONFIG_SB_SIGNING_COMMAND="my_command"

Note

The public key string must be an absolute path to the location of the public key file, as mentioned previously in Adding a custom signature key file.

See CONFIG_SB_SIGNING_COMMAND for specifics about what a usable signing command must do. The command string can include its own arguments like a typical terminal command, including arguments specific to the build system:

my_command [options] <args ...> <build_system_args ..>

See the description of CONFIG_SB_SIGNING_COMMAND for which arguments can be sent to the build system in this way.

Note

Whitespace, hyphens, and other non-alphanumeric characters must be escaped appropriately when setting the string from the command line. If the custom signing command uses its own options or arguments, it is recommended to define the string in a prj.conf file or Kconfig fragment to avoid tracking backslashes. Like public key paths, environment variables are not expanded when using them in a command string set from one of these files.

Adding MCUboot as an immutable bootloader

To build MCUboot with a Zephyr or nRF Connect SDK sample, enable the CONFIG_BOOTLOADER_MCUBOOT in the application’s prj.conf file, an associated Kconfig fragment, or using the command line:

west build -b nrf52840dk/nrf52840 zephyr/samples/hello_world -- -DCONFIG_BOOTLOADER_MCUBOOT=y

See Configuring and building for information on how to set the required configuration options temporarily or permanently. Like other child images, you can assign image-specific configurations at build time to further customize the bootloader’s functionality.

Configuring MCUboot as an immutable bootloader

The following sections describe different configuration options available for MCUboot as an immutable bootloader.

Adding a custom signature key file

To pass the signature key file into the MCUboot image, set its CONFIG_BOOT_SIGNATURE_KEY_FILE option to the selected private key file. You can set the option in bootloader/mcuboot/boot/zephyr/prj.conf, an associated Kconfig fragment, or using the command line:

CONFIG_BOOT_SIGNATURE_KEY_FILE="priv.pem"

The path of the key works as described above for nRF Secure Immutable Bootloader, except the application directory for relative pathing is considered to be bootloader/mcuboot.

See Signature keys for information on how to generate custom keys for a project.

We recommend you also set the associated configuration for a key type to ensure MCUboot compiles the public key into its image correctly.

west build -b nrf52840dk/nrf52840 zephyr/samples/hello_world -- \
-DCONFIG_BOOTLOADER_MCUBOOT=y \
-Dmcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE=\"../../priv-ecdsa256.pem\" \
-Dmcuboot_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y

You can find specific configuration options for keys with this bootloader in bootloader/mcuboot/boot/zephyr/Kconfig.

Checking the public key

You can extract the public key locally and compare it against MCUboot’s auto-generated file to verify that it is using the custom key:

diff build/mcuboot/zephyr/autogen-pubkey.c <(python3 bootloader/mcuboot/scripts/imgtool.py getpub -k priv.pem)

If there is no file diff output, then the private key was successfully included with the bootloader image.

Adding an upgradable bootloader

MCUboot is the only upgradable bootloader currently available for the nRF Connect SDK. The following section describes how to add it to your secure bootloader chain.

Adding MCUboot as an upgradable bootloader

To use MCUboot as an upgradable bootloader to your application, complete the following steps:

  1. Add nRF Secure Immutable Bootloader as the immutable bootloader.

  2. Add MCUboot to the boot chain by including the CONFIG_BOOTLOADER_MCUBOOT Kconfig option with either the build command or in the application’s prj.conf file:

    west build -b nrf52840dk/nrf52840 zephyr/samples/hello_world -- \
    -DCONFIG_SECURE_BOOT=y \
    -DCONFIG_BOOTLOADER_MCUBOOT=y
    

    See Configuring and building for information on how to set the required configuration options temporarily or permanently.

  3. Optionally, you can configure MCUboot to use the cryptographic functionality exposed by the immutable bootloader and reduce the flash memory usage for MCUboot to less than 16 kB. To enable this configuration, apply both the prj_minimal.conf Kconfig project file and the external_crypto.conf Kconfig fragment for the MCUboot image:

    west build -b nrf52840dk/nrf52840 zephyr/samples/hello_world -- \
    -DCONFIG_BOOTLOADER_MCUBOOT=y \
    -DCONFIG_SECURE_BOOT=y \
    -Dmcuboot_CONF_FILE=prj_minimal.conf \
    -Dmcuboot_EXTRA_CONF_FILE=external_crypto.conf
    

    See Customizing the bootloader for more information about using Kconfig fragments with bootloaders.

The build process generates several Output build files (image files), including MCUboot output build files.

Configuring MCUboot as an upgradable bootloader

The following sections describe different configuration options available for MCUboot as an upgradable bootloader.

Adding a custom signature key file

The process to use specific signature keys with MCUboot used as the upgradable bootloader is the same as when it is used as the immutable one.

Note

Since each bootloader is built with its own signature key, using a different private key with an upgradable bootloader will not cause problems with the secure boot chain. You can also use the same private key for both the immutable and upgradable bootloaders, as long as the key type is supported by both of them.

Generating pre-signed variants

Enable the CONFIG_BUILD_S1_VARIANT Kconfig option when building the upgradable bootloader to automatically generate pre-signed variants of the image for both slots:

west build -b nrf52840dk/nrf52840 zephyr/samples/hello_world -- \
-DCONFIG_SECURE_BOOT=y \
-DCONFIG_BOOTLOADER_MCUBOOT=y \
-DCONFIG_BUILD_S1_VARIANT=y

This is a necessary step for creating application update images for use with MCUboot and NSIB.

The S1 variant is built as a separate child image called s1_image. For this reason, any modifications to the configuration of the S1 variant must be done to the s1_image child image. By default, this child image is an exact duplicate of the original image, with the exception of its placement in memory. You only have to modify the version set in the CONFIG_FW_INFO_FIRMWARE_VERSION Kconfig option. To make s1_image bootable with nRF Secure Immutable Bootloader, the value of CONFIG_FW_INFO_FIRMWARE_VERSION for s1_image must be bigger than the one for original image.

Testing the bootloader chain

To test either of the bootloaders and the secure bootloader chain, build and program them with any sample as described in Adding a bootloader chain.

By default, both nRF Secure Immutable Bootloader and MCUboot print information to their serial output on boot. This output includes information about the validation of images in its slots, as well as firmware-specific information if using CONFIG_FW_INFO with the nRF Secure Immutable Bootloader. To see this output:

  1. Connect to the kit with a terminal emulator (for example, nRF Connect Serial Terminal). See Testing and optimization for the required settings and steps.

  2. Reset the development kit.

  3. Observe that each bootloader in the chain prints its information upon boot (some values may vary by build):

Attempting to boot slot 0.
Attempting to boot from address 0x9000.
Verifying signature against key 0.
Hash: 0xc0...71
Firmware signature verified.
Firmware version 1
Setting monotonic counter (version: 1, slot: 0)

When compiled with minimal configurations that disable logging output, such as prj_minimal.conf, you can disable the bootloader information output altogether or per-bootloader. Refer to the source code directories of each bootloader to see what minimal configuration options are already available, or add them through a custom Kconfig fragment if desired.