Important: Before you run this example, make sure to program the SoftDevice.
The Serial Secure DFU Bootloader example uses the Bootloader modules to implement a bootloader with secure Device Firmware Update (DFU) functionality.
The example bootloader accepts images that contain a new bootloader, SoftDevice, application, or any combination of these. To protect the target device against malicious attackers trying to impersonate the rightful sender of the firmware update, the init packet of the firmware package must be signed.
You can find the source code and the project file of the example in the following folder: <InstallFolder>\examples\dfu\bootloader_secure_serial
Button assignments:
When performing a DFU, you must provide a package (in zip format) that contains the firmware image, an init packet, and a manifest file that indicates the package format. The init packet contains information about the firmware image that is used to validate the image, and it must be signed to ensure that the update stems from a trusted source.
The required contents of the init packet are defined in the protocol buffer file dfu-cc.proto
. The following fields of the init packet are checked during the validation of the init packet:
Type | Field name | Description |
---|---|---|
Type of the image | type | The image can be an application image, SoftDevice image, bootloader image, or a combined image of bootloader and SoftDevice. |
Hash of the image | hash | The hash consists of two fields: an integer that specifies the used hash function and a byte array that contains the hash of the complete package. |
Firmware version | fw_version | This integer represents the firmware version of either the bootloader or the application image in the package. (The SoftDevice version is specified in a separate field.) |
Hardware version | hw_version | This integer represents the required hardware version of the device. |
Allowed versions of the SoftDevice | sd_req [] | This array of integers represents what SoftDevice firmware IDs are accepted for the image. Up to four allowed SoftDevice versions may be specified. For SD + BL + App updates, both the FW ID of the old and new SD should be present in the list. |
Size of the new SoftDevice, bootloader, or application | sd_size , bl_size , app_size | These integer values specify the size of the SoftDevice, bootloader, or application. |
Signature type | signature_type | The type of signature that the init packet is signed with. Supported signature types are ECDSA_P256_SHA256 and ED25519. This example uses ECDSA_P256_SHA256. |
Signature | signature | See Cryptography library for more information. |
Debugging | is_debug | When this flag is set, version validation (see Validation) is skipped. This flag is only honored in the debug projects. The non-debug projects always validate versions. |
To create a zip file that contains the firmware image (or images) and the corresponding init packet, use the nrfutil
tool (version 2.2.0 or later). This tool is available as a standalone Python package from the Nordic Semiconductor nrfutil GitHub repository or can be installed from pypi with pip install nrfutil
. See the nrfutil documentation for more information. Run nrfutil pkg generate --help
to display help about creating a zip file.
You can add the following firmware images in binary or hexadecimal format to the zip file:
--application
image: an image of an application--bootloader
image: an image of a bootloader--softdevice
image: an image of a SoftDeviceYou can also combine several images in one zip file. Note that, depending on the combination of images, the created zip file might contain two firmware packages (one for the bootloader and/or SoftDevice and one for the application) and the DFU process will be carried out in two steps. If you include both a bootloader and a SoftDevice in your firmware package, those two images will be merged together. An application, however, will always be updated separately after the other updates are completed.
In addition to the images, specify the information that you want to add to the init packet. The following options are available:
Option | Example value | Description |
---|---|---|
--debug-mode | n/a | Add this flag to skip version validation. |
--key-file file | c:\vault\priv.pem | A private (signing) key in PEM format that is used to cryptographically sign the firmware image (see Working with keys). |
--application-version version | 0xff | The version of the application image. |
--bootloader-version version | 0xff | The version of the bootloader image. |
--hw-version version | 52 | The version of the hardware that should accept the image. |
--sd-req sd_list | 0x87,0x8C | A comma-separated list of FWID values of installed, on-target SoftDevices that are valid to be used with the new image. Run nrfutil pkg generate --help to display a list of possible values. |
See the nrfutil documentation for additional information about nrfutil and about the required steps if you want to customize the init packet.
Validation of the image includes checks to verify that the image originates from a trusted source and that it is compatible with the device and the current firmware and hardware. If the flag is_debug
is set in the init packet, the debug version of the example skips version validation.
These checks are implemented in the dfu_handle_prevalidate()
function. Verification is done in the following order:
hw_version
.sd_req
.fw_version
.hash_data
.signature:
To be able to verify the signature, the validation code needs the public key that corresponds to the private key that was used to sign the init packet. This key is named pk
[] and is located in the file dfu_req_handling.c
.If one of these verification steps fails, an error code is returned.
There are three types of version numbers:
Unless version validation is skipped, the dfu_handle_prevalidate()
function applies the following acceptance rules to determine whether the image is accepted:
You can either create your own firmware package for testing or use one of the provided packages that are located in subfolders of <InstallFolder>\examples\dfu\ble_dfu_send_hex
. The provided packages have been generated using a private key that corresponds to the default public key in the project. This public key must not be used in production.
Test the Serial Secure DFU Bootloader application by performing the following steps:
dfu_public_key.c
. See Working with keys for instructions.dfu_public_key.c
file to the project folder, replacing the existing file.nrfutil dfu serial -pkg package.zip -p COM_PORT