nRF Secure Immutable Bootloader
The nRF Secure Immutable Bootloader (NSIB), previously also known as B0 or b0
, is a secure bootloader built and maintained by Nordic Semiconductor.
It is specifically tailored for the immutable bootloader architecture of a secure boot chain.
It can verify and boot a second-stage bootloader or application while providing a persistent and reliable Root of Trust (RoT).
See Secure bootloader chain for more information about the full bootloader chain.
Note
Currently, the NSIB does not support performing firmware updates over the SMP transport. If the application using the NSIB requires SMP-based firmware updates, such as Bluetooth® LE DFU, include MCUboot as a second-stage bootloader.
Requirements
The NSIB supports the following development kits:
Hardware platforms |
PCA |
Board name |
Board target |
---|---|---|---|
PCA10153 |
|
||
PCA10090 |
|
||
PCA10171 |
|
||
PCA10095 |
|
||
PCA10040 |
|
||
PCA10056 |
|
||
PCA10100 |
|
||
PCA10112 |
|
The NSIB can only boot images that enable the firmware information module, see the Firmware information module.
Overview
The NSIB implements a simple and reliable Root of Trust (RoT) for a secure boot chain, as described in the Immutable bootloader conceptual documentation.
For locking the flash memory, the NSIB uses the Hardware flash write protection driver.
For the signature verification, to save space, NSIB only stores the hashes of the provisioned keys and compares only the hashes of these keys. The next image has metadata containing the full public key that corresponds to the private key used to sign the firmware. This public key is checked against the provisioned hashes of public keys to determine if the image is valid. All public key hashes at lower indices than the matching hash are permanently invalidated at this point. You can use this mechanism to decommission compromised keys.
Note
Make sure you provide NSIB with your own keys, as described in Provisioning, before you program it.
At the end of the RoT establishment, the NSIB also shares some of its functionality through an external API (EXT_API
).
For more information on the process, see Bootloader crypto.
For more information on EXT_API
, see External APIs.
Provisioning
The public key hashes are not compiled with the source code of the NSIB. Instead, they must be written to the device in a process called provisioning.
The hashes are automatically generated by the build system based on the specified private key and the additional public keys.
By default, the hashes are placed directly into the NSIB HEX file and then automatically provisioned when the HEX file is programmed to the device.
However, in a more realistic manufacturing process, you can program the NSIB HEX file and the HEX file containing the hashes separately, using the Python scripts located in the scripts/bootloader
folder.
In either case, the NSIB accesses the provisioned data at run time using the Bootloader storage library.
OTP regions
The one-time programmable (OTP) region is a special region of the User Information Configuration Registers (UICR) that only allows flash memory writes in half-word lengths, and only when the target half-word has the value of 0xFFFF
.
On products that support an OTP region, such as the nRF91 Series and nRF5340, the provisioned data is held in the OTP region instead of the internal flash memory.
Because of these design constraints, the following limitations apply:
The public key hash must not contain half-words with the value
0xFFFF
, as such hashes cannot be guaranteed to be immutable when placed in the OTP region. If any such hashes are provisioned, the NSIB will refuse to boot. If your public key hash is found to contain this value, it must be regenerated.Provisioned data cannot be written more than once to the target device. When programming images that contain flash memory content in the UICR region, such as the NSIB image, the UICR must first be erased.
Note
On the nRF91 Series and nRF5340 devices, the UICR can only be erased by erasing the entire flash memory.
For information how to erase the entire flash memory when flashing, see Programming an application.
Flash memory layout
The flash memory layout is defined by the samples/bootloader/pm.yml
file, which establishes four main partitions:
B0 - The NSIB image.
Provision - The provisioned data.
S0 - Slot 0.
S1 - Slot 1.
The default location for placing the next image in the boot chain is S0.
This would result, for example, in a flash memory layout like the following, when using the nrf52840dk_nrf52840
board:
Note
When the Provision area is in the OTP region, it will not appear in the flash memory layout. See OTP regions for more information.
Pre-signed variants
When two slots are present, two images must be built.
One that is executable from slot 0, and the other one from slot 1.
Building the image for slot 1 is done by enabling the CONFIG_BUILD_S1_VARIANT
option.
When the image for the next stage in the boot chain is upgraded, the new image is written to the slot with the oldest image version. See Hardware-based downgrade protection for more information about versioning.
If this image is faulty and cannot be booted, the other partition will always hold a working image that is booted instead.
When using the nrf52840dk_nrf52840
board, this would produce a flash memory layout like the following:
Configuration
See Configuring and building an application for information about how to permanently or temporarily change the configuration.
Signature keys
The ECDSA-P256 key type is supported for validating the next image in the boot chain. See Signature keys for more information.
Monotonic counter
You can implement hardware-based downgrade protection using a non-volatile monotonic counter.
Counter updates are written to slots in the Provision area, with each new counter update occupying a new slot. For this reason, the number of counter updates, and therefore firmware version updates, is limited. The Provision is a partition in non-volatile memory, and its location can be found using Partition Manager report.
Using a counter is optional and can be configured for the application using configuration options. You can also configure the supported number of updates, but the number is limited by the size of the Provision area and how much of that area is taken up by other features, like public key hashes. In addition, you can configure what firmware version of the image you want to boot.
To enable anti-rollback protection with monotonic counter for nRF Secure Immutable Bootloader, set the following configurations in the b0
image: CONFIG_SB_MONOTONIC_COUNTER
and CONFIG_SB_NUM_VER_COUNTER_SLOTS
Special handling is needed when updating the S1 variant of an image when Adding an upgradable bootloader. See Generating pre-signed variants for details. See Kconfig namespacing in the Zephyr documentation for information on how to set options for built images in sysbuild.
To set options for child images, such as NSIB and MCUboot, see the Image-specific variables section.
Building and running
This sample can be found under samples/bootloader
in the nRF Connect SDK folder structure.
To build the sample, follow the instructions in Configuring and building an application for your preferred building environment. See also Programming an application for programming steps and Testing and optimization for general information about testing and debugging in the nRF Connect SDK.
Note
When building repository applications in the SDK repositories, building with sysbuild is enabled by default.
If you work with out-of-tree freestanding applications, you need to manually pass the --sysbuild
parameter to every build command or configure west to always use it.
Caution
nRF Secure Immutable Bootloader should be included as a child image in a multi-image build, rather than being built stand-alone. While it is technically possible to build the NSIB by itself and merge it into other application images, this process is not supported. To reduce the development time and potential issues with this route, let the existing nRF Connect SDK infrastructure for multi-image builds handle the integration.
The NSIB is automatically added as a child image when the CONFIG_SECURE_BOOT
Kconfig option is set in the application.
For building and running the NSIB with an application, see Adding an immutable bootloader.
Building and running using Visual Studio Code
This sample can be found under samples/bootloader
in the nRF Connect SDK folder structure.
To add the NSIB as a child image to your application, complete the following steps:
Enable the nRF Secure Immutable Bootloader through Kconfig as follows:
Select Kconfig in the Actions View to open the nRF Kconfig tab.
Expand Modules > nrf > Nordic nRF Connect > Bootloader and set Use Secure Bootloader to enable
CONFIG_SECURE_BOOT
.Expand Use Secure Bootloader. Under Private key PEM file (
CONFIG_SB_SIGNING_KEY_FILE
), enter the path to the private key that you created.You can also modify other additional configuration options, but that is not recommended. The default settings are suitable for most use cases.
Note
If you need more flexibility with signing, or if you do not want the build system to handle your private key, choose
CONFIG_SB_SIGNING_CUSTOM
, and also specifyCONFIG_SB_SIGNING_COMMAND
andCONFIG_SB_SIGNING_PUBLIC_KEY
. You can use the Search modules bar in nRF Kconfig to find these options. These options allow you to define the signing command.Click Save.
Select Build in the Actions View to start the build process. The build process creates two images, one for the NSIB and one for the application, and merges them.
Select Flash in the Actions View to program the resulting image to your device.
Testing
See Testing the bootloader chain for testing of the expected runtime behavior of the NSIB when built with an application.
Dependencies
The following nRF Connect SDK libraries are used:
It uses the following sdk-nrfxlib libraries: