In today’s connected world, the ability to provide updates to embedded devices is more important than ever. Devices need to be updated to provide new functionality, connect with new services and receive security updates. Updates are no longer only a necessity to establish a strong reputation for customer trust, but are also required for legal reasons. New security regulations for embedded devices, such as the EU’s Cyber Resilience Act (CRA), require the ability to install trusted updates over long timescales.
Aside from updates, devices also need to be secured against manipulation. Embedded devices handle a large range of tasks which are often safety-critical, involve financial transactions, or provide sensitive data to end users or service providers which must not be forged. Manufacturers of embedded devices need to ensure that the software on their devices cannot be manipulated, even before they are allowed to enter certain markets at all. Due to these reasons, manufacturers of embedded devices need to integrate updateability into the core of their products right from the start of the design process.
SEGGER’s emBoot-Secure, which is described in detail in this manual, is a collection of multiple components that make designing and implementing a secure update mechanism for embedded devices easy.
In particular, emBoot-Secure consists of the following components:
Easy-to-use software tools for creating update packages, compressing them, protecting them from manipulation and inspection, and managing the required cryptographic keys
A bootloader library, which makes it easy to build a custom bootloader that is tailored to a specific embedded project and handles firmware updates efficiently and securely
Example bootloader implementations, which show how the bootloader library can be used and adapted to a specific embedded project
The Signature Server, a dedicated hardware device that can optionally be used to generate, store, and apply cryptographic keys
Comprehensive documentation (this document)
To ease the update process, the firmware of the embedded device is divided into two software components: the bootloader, which is built with the emBoot-Secure library, and the application firmware. While the application firmware provides the core functionality of the device, the bootloader is responsible for verifying the authenticity and integrity of update packages and for their installation. Each time the embedded device is turned on, the bootloader is also responsible for verifying that the application firmware has not been manipulated.
Principle of operation
This section introduces the emBoot-Secure packaging process and the bootloader’s logic at startup.
Packaging process
At a high level, the process of integrating emBoot-Secure into an embedded software project can be separated into the following five steps.
Figure: The 5-step process of setting up and using emBoot-Secure
This process involves some initial steps to generate the required cryptographic keys and build a tailored bootloader for the project that contains those keys.
In addition, each firmware update needs to be packaged, transferred to the target, and installed.
Key generation
The security services that emBoot-Secure provides rely on cryptographic procedures, which require some cryptographic keys to operate. In particular, two different kinds of keys are required:
Signing key pair: To implement protection against manipulation of the update package, the concept of digital signatures is used. This concept requires a pair of two keys, a public and a private key. The private key is kept in secret at the manufacturer of the embedded device and is used to produce valid firmware update packages. The public key is embedded into every device and can be used to verify whether an update package has been manipulated or not. emBoot-Secure uses the established RSA or ECDSA algorithm for this purpose.
Encryption key: To implement protection against inspection of the update package, for example by malicious actors or competitors, update packages can optionally be encrypted. This requires another (single) key, which is used for both encryption (at the manufacturer) and decryption (on the embedded device). emBoot-Secure uses the established AES-GCM algorithm for this purpose.
These cryptographic keys need to be generated once and are valid for the whole lifecycle of the product.
The private signing key is a valuable asset in the process of creating cryptographically signed firmware images and update packages. If an attacker can gain access to the key, manipulated firmware images can be signed and installed into the target device. To prevent malicious actors from gaining access to the private key, emBoot-Secure provides its Signature Server. This server, a dedicated hardware appliance, can securely store private keys.
Key embedding
The generated keys are converted into C files using the key generation tool and linked into the bootloader.
Firmware packaging
Whenever a new update is to be distributed, it is packaged into an update package using the firmware preparation tool.
This tool applies the signature and optionally compresses and encrypts the firmware image.
The signing process consists of two steps, hash computation and creation of the signature.
In the first step, a hash over the firmware image is computed. A hash is a cryptographic checksum, which is designed such that changing a single bit in the firmware image will change the hash result in an unpredictable fashion. This makes it practically impossible to modify the image in such a way that the modified version produces the same hash as the original version.
The emBoot-Secure library supports several cryptographic hash functions such as SHA256, SHA512 or SHA1.
In the second step, the digital signature is computed.
To prevent manipulation of the hash value, the manufacturer uses the private key to sign it. The bootloader can later verify the signature using the public key, which is embedded in the bootloader in the target device. The supported signature algorithms are RSA and ECDSA, with various key sizes.
The firmware preparation tool either computes the signature locally on a computer or requests it from the Signature Server. If the Signature Server is used, the firmware preparation tool sends the hash to the server and receives the signature in return, which is then embedded into the update package. The private key, however, does not leave the Signature Server and can therefore not be leaked.
In addition, the image can optionally be compressed and encrypted.
Compression enables the creation of small update packages, which is especially important when they need to be distributed to the target using low-bandwidth channels such as CAN or small RF data packages. The emBoot-Secure library features compression of the update package using SEGGER’s SMASH-2 algorithm, which is optimized for compression of firmware images. It has a very small footprint and is therefore ideal for use in bootloaders.
Encryption prevents update packages from inspection by third parties. emBoot-Secure optionally encrypts update packages with the AES-GCM algorithm.
The firmware preparation tool can also produce a signed firmware image for initial manufacturing, which can be written into flash memory using standard tools. This step is required because the bootloader needs to verify the authenticity of the installed firmware image on every start.
Firmware transfer
For update package distribution, the manufacturer of the embedded device is free to implement a method that fits the target ecosystem - such as Wi-Fi, Bluetooth, Ethernet, USB, SD card, or CAN.
The target’s application firmware is responsible for storing the update package on the device, such that the bootloader can find it during the next reboot.
Firmware update
When the bootloader discovers a new update package, it first compares the version number of the update with version number of the currently installed firmware. If the version number of the update package is newer, the bootloader unpacks it. If needed, the update package is decrypted and/or decompressed. Then, the signature is verified and, given a valid signature, the new firmware is written to flash memory. This process is explained in detail in the next section.
Bootloader logic
This section describes the principle of operation of the emBoot-Secure bootloader library and its interaction with the target system as part of a bootloader.
The figure below shows how the bootloader operates after a reset of the microcontroller.
Figure: Flowchart of the update process
Searching for update packages
The bootloader starts by searching for update packages. These packages are stored in so-called areas, which are addressed using an index. During the configuration of the bootloader, the manufacturer specifies the number of areas and implements a function which allows the bootloader to read data from them. The bootloader itself is agnostic to the implementation details of these areas - they can be regions of internal flash memory, external flash memory or files in a filesystem.
Version number check
When the bootloader determines that an area contains an update package, it compares the version number of the update package with the version number of the installed firmware image. The version numbers are stored in the headers of both the update package and the firmware image. By default, the bootloader will only install update packages with higher version numbers, in order to prevent a firmware rollback, but this setting can be changed if needed. Once an update package with a suitable version number has been found, the bootloader considers it for installation.
Update package decryption
If the update package is encrypted, the bootloader will attempt to decrypt it with its embedded encryption key. The AES-GCM encryption method includes an authentication layer, which allows to detect manipulated or corrupted packages early on. If this authentication fails, the update package is rejected immediately.
Update package decompression
If the update package is compressed, it is decompressed at this stage. The update package is rejected if any bitstream errors occur.
Firmware signature verification
The emBoot-Secure library’s core function is the verification of both firmware update packages and installed firmware images. The verification is needed to confirm that the application firmware was supplied by the manufacturer and has not been tampered with, neither before nor after installation. In order to verify the authenticity of an update package, the digital signature is checked in two steps: hash computation and signature verification.
In the first step, the hash of the firmware image in the update package is computed and compared with the expected hash value stored in the package’s metadata.
If the hash matches, it has to be checked for manipulation. Therefore, in the second step, the digital signature that has been computed by the manufacturer when the update was packaged is verified using the public key, which is embedded in the bootloader.
Update installation
If the bootloader determines that the update package is authentic, it proceeds with installation. This requires the bootloader to erase the region of flash memory which contains the previous version of the application firmware and to write the firmware image obtained from the update package into it. The process in which flash memory is erased and written to is highly dependent on the employed target hardware. Therefore, the bootloader employs a flash memory driver, which is usually part of the emBoot-Secure shipping package. The manufacturer configures the flash memory layout which the emBoot-Secure library should use via compile-time configuration flags. The bootloader uses these settings to determine the region of flash memory into which it must write the updated firmware image.
Since the bootloader was designed such that it can access the update package without help from the application firmware, it can resume the update process if it gets interrupted after the previously installed application firmware has been (partially) erased from flash memory. This ensures that the device does not get “bricked”.
Booting without an update package
When the bootloader has finished the installation of the update package, it resets the microcontroller. After the reset, the bootloader again searches the regions which may contain update packages, but it should not find a newer update package any more.
At this point, the bootloader does not know that the firmware image has just been installed and therefore proceeds to check the authenticity of the installed firmware image. This step is necessary to detect accidental or intentional manipulation of the firmware image. During the installation of the firmware image, the header and the metadata which contain the version number, the hash value, and the manufacturer’s cryptographic signature have been written into the flash memory along with the raw firmware image. Therefore, the bootloader can again compute the hash, compare it against the hash value stored in the metadata, and verify the signature. If the signature is valid, the bootloader reads the firmware entry point address from the header and proceeds to start the firmware image. Its work is done.
Handling invalid firmware images
If the bootloader determined that the installed firmware image is not authentic, it looks again for firmware update packages. But this time, since there is no usable firmware image installed, it will install any update package, regardless of the version number. The bootloader can also be supplied with a dedicated rescue firmware image, which is retained in a special area independent of regular update packages. This rescue image may have reduced functionality and its only purpose may be to provide a means of obtaining a more recent update package. The manufacturer can also implement a method to determine whether a rescue image should be installed based on certain conditions, for example, when the customer presses a button or sets a jumper during start-up. Alternatively, the application could indicate a non-recoverable state to the bootloader using non-volatile, battery-powered SRAM which is available in some targets.
In the worst case scenario, the bootloader will neither find an update package nor will it be able to confirm the authenticity of the installed firmware image. In that case, it will refuse to start the application firmware and indicate an error condition, depending on the means available in the device. While this condition usually renders the device unusable, it prevents the device from starting with a damaged or tampered firmware image, which could allow an attacker to wreak havoc unnoticedly or cause dangerous malfunction of the embedded device.
Components of emBoot-Secure
emBoot-Secure consists of the following parts:
Item
Description
emBoot-Secure library
Source code of emBoot-Secure library.
Signature Server
Signature Server hardware device for secure key storage (optional).
Command line tools
Command line tools for generating keys, managing the Signature Server and creating update packages.
Documentation
The documentation.
The command line tools are provided in ELF format (without a file extension) for Linux and as .exe files for the Windows operating system. In this manual, the command line tools’ filenames are referenced for both formats interchangeably. The command line arguments are the same for both operating systems.
Components of the emBoot-Secure library
emBoot-Secure is provided in source code and the exact content
depends upon the versions and add-ons that you purchase.
The following table shows the content of the package:
Files
Description
Config
Configuration header and C files.
BOOT
emBoot-Secure library source code.
SEGGER
SEGGER software component source code.
CRYPTO
Cryptographic library for signature validation and optional update package decryption
COMPRESS-ToGo
Code for optional decompression of update package
Application
emBoot-Secure sample implementations and configurations.
BSP/<mcu>
Sample configurations and flash routines for selected MCUs.
Tool
Command line tools
Doc
Documentation
Getting started
This chapter explains how to write a secure bootloader which can update the application firmware and itself.
Overview
Partitioning of the non-volatile memory
Several areas in the non-volatile memory of the target device must be defined, especially:
The area of the bootloader.
The area of the application firmware.
One or more areas where firmware update files can be stored.
The bootloader and the application firmware usually reside in memory that can be executed by the CPU.
The memory addresses of these areas must be defined in the configuration file BOOT_Conf.h.
For all other areas, it is sufficient that they can be read sequentially.
A firmware project for the bootloader can be created with any toolchain or IDE.
After an empty (“Hello-World”) application is created, all necessary emBoot-Secure source and
configuration files can then be added to the project in order to build a bootloader,
see Setting up the bootloader project.
Configuring the bootloader's behavior
The behavior of the parts of the bootloader supplied by the emBoot-Secure library are configured in the BOOT_Conf.h. This concerns both the search for update packages as well as supported cryptographic and compression algorithms.
Hardware (board) specific support
Each bootloader project requires hardware-specific support functions,
especially for flash memory write and erase. These board support files are usually placed in a file named
BOOT_Config_<boardname>.c. Depending on the purchase agreement,
this copy of the emBoot-Secure library ships with board support files for the employed target boards.
The emBoot-Secure library searches for update packages by using the SBTL_ReadArea() callback. This callback needs to be implemented to allow hardware specific access to update packages, for example in a part of the device’s internal flash memory or by accessing a filesystem on external flash memory.
There are also some options of the CRYPTO library which can be configured to enable hardware cryptographic support if available on the target board.
Implementation of the top-level bootloader code (main() function).
emBoot-Secure comes with samples that can be taken as the main bootloader function
or can be used as a starting point for creating a customized version.
Key creation
At least one firmware signing key pair must be generated. Key generation can either be done using the key generation tool or the Signature Server. Either RSA or ECDSA algorithms can be chosen, depending on the project’s individual requirements. The public key must be made available to the emBoot-Secure library using either the SBTL_GetRSAPublicKey or the SBTL_GetECPublicKey() function, respectively. A C file containing implementations of these functions, including the public key, can be created using the key generation tool.
Optionally, a firmware encryption key can be generated using the key generation tool. The firmware encryption key is requested by the emBoot-Secure library through the SBTL_GetAESKey() function, which can also be created from the AES key using the key generation tool.
The resulting C files containing the keys need to be added to the bootloader project.
Application firmware and integration
Application firmware needs to be adapted in order to be launchable by the bootloader.
The linker has to be instructed to place it in its designated region of flash memory, leaving space
for metadata such as a version number and the location of the digital signature.
Also, the vector table, which is used by the microcontroller to determine the entry point
of the application and the location of interrupt handlers, has to be placed at a suitable
position in the firmware’s flash region and activated during application start-up. This process
is described in the section Adapting application firmware.
Creating firmware for the target
Finally, the application firmware image has to be processed by emBoot-Secure’s FirmwareTool. For the device production process, a signed firmware image is created which can be flashed into the target alongside the bootloader. To update the application firmware and the bootloader in the field, update packages containing the signed (and optionally compressed and encrypted) firmware image are produced. These steps are covered in the section Creating firmware for the target.
Partitioning of the non-volatile memory
emBoot-Secure can handle the following types of areas in non-volatile memory:
Bootloader area
This area contains the bootloader, which is started by the device after power up.
If the bootloader shall be able to update itself, the
memory region must be erasable without affecting other parts of the memory.
Application firmware area
This area contains the application firmware of the target device and can be updated
by the bootloader. It should be large enough to store any future versions of the
firmware.
The memory region must be erasable without affecting other parts of the memory.
The firmware in this area contains a header and a signature that is verified
on every start-up by the bootloader.
Update area
There can be one or several of these areas. The application firmware can store update packages
into any of these areas which will be read by the bootloader on the next
start-up of the device. If the bootloader can successfully verify the update package, it
will transfer the new firmware into the application firmware area. emBoot-secure uses the SBTL_ReadArea callback to request data from this area.
Failsafe firmware area
This is an optional area that contains a failsafe firmware image. The bootloader will copy this
into the application firmware area in case it determines that the application firmware is corrupted
and no valid update package is available. In order to get the device operational again,
the failsafe firmware must contain at least
the functionality to receive an update package and store it into an update area. emBoot-secure uses the SBTL_ReadArea callback to request data from this area.
Sample memory configurations
This section lists common flash memory layouts and how to configure emBoot-Secure to use these layouts. The memory layouts are described using configuration flags in BOOT_Conf.h. For a general explanation of these flags, see Configuration switches for flash memory layout. Only regions of memory which contain the bootloader and the application firmware image need to be described, since emBoot-Secure needs to be able to write into them. Areas containing update packages or failsafe firmware update packages are not described by configuration flags. Instead, emBoot-Secure will request data from these regions using the SBTL_ReadArea() callback, which needs to be implemented accordingly.
Simple configuration
All areas reside in internal flash of the device.
This configuration can be achieved with settings like this (in BOOT_Conf.h):
In this example with a 2 MB flash memory, the bootloader is in the memory area from 0x000000 to 0x01FFFF and the firmware is in 0x020000 to 0x11FFFF.
In both areas, the smallest addressable flash blocks have a size of 4KB. Address 0x120000 denotes the starting point of the region containing firmware update packages.
It can be used for one or more update packages, for example a failsafe firmware area which is not touched and an area for firmware updates.
Configuration with external SPI flash
An external flash memory can easily used to store update packages and failsafe firmware in order to fully utilize the
internal flash memory for the active firmware:
This configuration can be achieved with settings like this (in BOOT_Conf.h):
In this example there is a 256 KB flash at address 0x0 and another 1 MB flash at 0x08000000.
Configuration with dual bank flash
If flash bank swapping is supported by the hardware, the following configuration can be used
for a reliable bootloader update mechanism (for details about this mode, see section Bootloader update in bank swap mode):
The bootloader in flash bank 1 is the active bootloader, while the bootloader region
in flash bank 2 is only active during the update process.
This configuration can be achieved with settings like this (in BOOT_Conf.h):
#defineSBTL_BOOTLOADER_UPDATE_MODE SBTL_BOOTLOADER_UPDATE_MODE_BANKSWAP// Definition of the flash area containing the active bootloader#defineSBTL_BOOTLOADER_SOURCE_START_ADDR 0x00000000#defineSBTL_BOOTLOADER_SOURCE_SECTOR_SIZE 0x1000#defineSBTL_BOOTLOADER_SOURCE_SECTOR_COUNT 0x20// Definition of the flash area used during bootloader updates#defineSBTL_BOOTLOADER_TARGET_START_ADDR 0x00100000#defineSBTL_BOOTLOADER_TARGET_SECTOR_SIZE 0x1000#defineSBTL_BOOTLOADER_TARGET_SECTOR_COUNT 0x20#defineSBTL_FIRMWARE_START_ADDR 0x00020000#defineSBTL_FIRMWARE_SECTOR_SIZE 0x1000#defineSBTL_FIRMWARE_SECTOR_COUNT 0x1e0
Setting up the bootloader project
Basic familiarity with the tools required for developing embedded software applications, such as compiler, linker and
project manager / build system is assumed. This includes adding source and header files to the project, setting
the include search path, and so on.
The starting point is a running, empty project (“Hello-World” application) for the target device.
It should contain code to initialize any hardware required for bootloader operation,
for example clocks, PLLs, RAM and flash memory access. The linker must be directed to
place the code into the configured address range for the bootloader, see SBTL_BOOTLOADER_START_ADDR and associated macros.
All necessary emBoot-Secure source and configuration files can then be added to the project,
as described in the next sections.
Add emBoot-Secure files
All source files from the following folders should be added to the project.
Folder
Description
BOOT
emBoot-Secure library core components
SEGGER
Supportive code shared by SEGGER’s products
CRYPTO
Cryptographic library for signature validation and optional update package decryption
COMPRESS-ToGo
Code for optional decompression of update package
The above folders must also added to the include search path of the project. Not all of these files (or functions therein) may be needed in an actual bootloader project, but the linker will usually drop everything which is not referenced. The options required for
this feature to work depend on the compiler and the linker, and can usually be found in using the keyword “function sections”.
The Config directory contains files which are designed to be customized and are provided as templates only.
It is recommended to create a copy of them in the directory of the user-specific bootloader code.
This prevents the changes from being overwritten when a newer version of the emBoot-Secure library is imported.
These files are:
File
Description
Config/BOOT_Conf.h
Configures flash memory layout and boot loader behavior.
Contains board-specific code for the bootloader, especially for reading memory areas and
flash programming. The central file is BOOT_Config_<board>.c
Application/*.c
Contains example bootloader main() implementations.
Customization of theses files is described in the following sections.
Configuring the bootloader
The file BOOT_Conf.h contains the configuration specific to the user’s project and needs to be modified as described in the following sections.
Partitioning the non-volatile memory for emBoot-Secure
The first step in the bootloader creation process is the partitioning of the non-volatile memory to allocate memory for
the bootloader and the application firmware. In this section, an example configuration for a device with 2 MB internal flash memory
is demonstrated. The flash memory is organized into sectors of 4096 bytes (4 KB). Erasing of flash memory can only be done at the sector scale.
To provide ample room for during development of the bootloader, especially for non-optimized debug builds, 128 KB of
flash memory are assigned to the bootloader while the remaining flash memory is available for the application firmware.
The bootloader must be placed at the beginning of the flash memory, since it contains the vector table which is read
by the microcontroller after a reset.
The linker needs to know about the flash memory layout in order to place the application firmware code at the appropriate
addresses, therefore separate linker scripts are needed for the bootloader and the application firmware.
A suitable script for the SEGGER Linker is shown below:
// Linker_Bootloader.icf
define region FLASH1 = [from 0x00000000 size 0x00200000];
#define BOOTLOADER_SIZE 128k
// HEADER_SIZE must match value SBTL_FIRMWARE_HEADER_SIZE in Boot_ConfDefaults.h.
#define HEADER_SIZE 64
define region BOOTLOADER = [from 0x00000000 size BOOTLOADER_SIZE];
define region HEADER = [from BOOTLOADER_SIZE size HEADER_SIZE];
define region APP = FLASH - BOOTLOADER - HEADER;
// snipped: definitions of blocks and sections
//
// FLASH Placement
//
place at start of BOOTLOADER
{ block vectors }; // Vector table section
place in BOOTLOADER with minimum size order
{
block tdata_load, // Thread-local-storage load image
block exidx, // ARM exception unwinding block
block ctors, // Constructors block
block dtors, // Destructors block
readonly, // Catch-all for readonly data
readexec // Catch-all for (readonly) executable code
};
The bootloader also needs to know about the flash layout; it is configured in BOOT_Conf.h as follows:
If a flash memory contains areas with different erasable block sizes, it can be configured in the same way.
Customizing the behavior of the bootloader
Several aspects of the behavior of the bootloader need configuration in BOOT_Conf.h. Explicit configuration is only
needed when the settings differ from the defaults defined in BOOT_ConfDefaults.h.
The configuration of the vendor and product names is needed by the bootloader for the derivation of a 32 bit product id number, which is used to ensure that only compatible firmware updates are installed. The product id can be obtained by calling SBTL_GetProductID().
For this example, the number of areas in which the bootloader can search for updates is set to two.
#defineSBTL_NUM_AREAS_UPDATE 2
Additionally, areas containing update packages with failsafe rescue firmware can be configured if available. If they are used, the bootloader has to determine whether the currently installed firmware needs to be replaced by a failsafe version, for example by reading out a push button which can be pressed by the end user during the boot process. The rescue update package can be queried for using the SBTL_FindRescueFirmware().
#defineSBTL_NUM_AREAS_FAILSAFE 0
By default, the emBoot-Secure library will only consider update packages for installation which have a version number higher than the firmware which is currently installed. The same is true for bootloader update packages. This provides rollback protection, i.e., it prevents the installation of older, known-vulnerable versions. If rollback protection is not desired, downgrades can be allowed using the respective flags for bootloader and application firmware update packages.
Two different bootloader update modes can be enabled, depending on the capabilities of the target hardware.
SBTL_BOOTLOADER_UPDATE_MODE_NONE
Update of the bootlader is prohibited.
SBTL_BOOTLOADER_UPDATE_MODE_NORMAL
The bootloader can be updated. During update, the bootloader overwrites itself. This carries the risk of device bricking if the
update process is interrupted. This should be used with care.
SBTL_BOOTLOADER_UPDATE_MODE_BANKSWAP
On target hardware with two swappable flash banks, the bootloader can update itself in a two-step process,
which can recover from interruptions or transient failures.
For this example, the normal update mode is configured:
For verification of the firmware integrity and authenticity, either RSA or ECDSA based signature algorithms can be used. Several hash algorithms like SHA1, SHA256, SHA384 and SHA512 are available. A list of relevant flags is provided in the section Configuration switches related to algorithms. Section Choosing a signature scheme and its parameters provides a more in-depth overview over the available choices and their trade-offs. In this example, RSA-based signatures with SHA256 hashes are chosen.
Update packages can optionally be compressed using SEGGER’s SMASH-2 compression algorithm. If the application firmware contains a lot of ARM Thumb-2 instructions, the optimized SMASH-2-T2 variant can be used. Enabling compression can lead to smaller update packages, but increases code size of the bootloader. See section Resource use and performance for more information. Enabling this flag will integrate the code required to process compressed update packages, but it does not make compression mandatory. The bootloader can still process and install uncompressed update packages.
Finally, update packages can be encrypted to prevent them from being inspected and reverse-engineered. The emBoot-Secure library provides the symmetric AES encryption algorithm in Galois/Counter mode. Encryption requires the generation of an AES key, which needs to be converted to a C file which can be added to the bootloader project, see section Adding keys to the bootloader. Enabling this flag will integrate the code required to process encrypted update packages, but it does not make encryption mandatory. The bootloader can still process and install unencrypted update packages.
#defineSBTL_ALGO_ENC_AES_GCM 1
Adding hardware-dependent configuration
A bootloader implementation always needs hardware- and/or board-specific support functions, which act as callbacks.
They are used both to obtain information as well as to modify flash memory.
These functions are stored in a file called BOOT_Config_<TargetName>.c
Sample configurations for popular evaluation boards are supplied
with the emBoot-Secure shipping package (in the folders BSP/<BoardName>)
or can be provided by SEGGER on request.
If there is no board configuration file for the selected target device,
a configuration file for a similar hardware should be taken and modified to
match the hardware.
Required support functions are described in the next sections.
Configuring debugging output
While developing and testing a bootloader, we recommend to use the DEBUG configuration of
emBoot-Secure. This is enabled by setting the preprocessor symbol DEBUG (or SBTL_DEBUG) to 1.
The DEBUG configuration contains additional run-time checks and generates debug output messages
which are very useful to identify problems that may occur during development.
In case of a fatal problem (e.g. an invalid configuration),
the program will end up in the function SBTL_Panic.
Once the application is running correctly, DEBUG can be set to 0.
To later compile a release configuration, which has a smaller code footprint,
the preprocessor symbol DEBUG (or SBTL_DEBUG) can simply be set to 0.
The file BOOT_ConfigIO.c found in the folder Config must be added to the project
and configured to match the message output method used by the debugging tools (semihosting, RTT, etc.).
If possible, SEGGER’s Real-Time-Transfer (RTT) should be used. The output is shown in the
output pane of the Embedded Studio IDE or can be viewed with the J-Link RTT Viewer. Note, however, that when the bootloader transfers control to the firmware application, which uses its own buffer for RTT, those messages will not be captured by the RTT interface. Therefore, for observing the application’s debug output during development, it has to be started directly by the debugger.
Debug output can be added to custom bootloader code using the SBTL_LOG macro, which invokes the SBTL_Logf() function when debug output is enabled. Otherwise, it does not produce any code. The macro forwards messages with printf-compatible format specifiers and a variable number of arguments to SBTL_Logf(). Due to limitations in the C preprocessors, two parentheses have to be used around its arguments. A newline character at the end of the string is not needed.
The emBoot-Secure library needs to access different types of firmware (and possibly, bootloader) images while determining
which actions to take, like installing an update or starting the application. The different accessible images are
called “areas” and are addressed via indices. In order to read data from an area, the function SBTL_ReadArea() is used.
When the emBoot-Secure library requests data from an area, it will always start reading the area from the beginning. It will
always read the data sequentially and when it has either read enough data from an area or read until the end of an area,
it will call SBTL_CloseArea(). These rules allow the mechanism to be applied to different kinds of storage mechanisms.
In this example, the two update areas which have been configured will be implemented as files on the
NAND flash chip on the SEGGER emPower evaluation board. This allows the application firmware to place up to two files with firmware
in the filesystem.
// Static variable to hold the handle for the currently open file.staticFS_FILE*AreaFile =0;intSBTL_ReadArea(unsignedArea,U32 Offset,unsignedBuffSize,U8 *pBuff){FS_FILE*FileHandle;unsignedlongnBytesRead;I16 ErrorCode;constchar*Filename =0;if(Area ==SBTL_MEM_AREA_FIRMWARE){memcpy(pBuff,(U8*)(SBTL_FIRMWARE_START_ADDR+Offset),BuffSize);returnBuffSize;}if(Offset ==0){switch(Area){caseSBTL_MEM_AREA_UPDATE(0):Filename ="update_1.upd";break;caseSBTL_MEM_AREA_UPDATE(1):Filename ="update_2.upd";break;default:return-1;}FileHandle =_OpenFirmwareFileForReading(Filename);if(FileHandle ==0){return-1;}AreaFile =FileHandle;}// At this point, areaFile is a handle to an open file.// Read data as requested.nBytesRead =FS_Read(AreaFile,pBuff,BuffSize);if(nBytesRead !=BuffSize){ErrorCode =FS_FError(AreaFile);if(ErrorCode ==FS_ERRCODE_EOF){// Reached EOF, that is not an error.returnnBytesRead;}// Other errorreturn-1;}returnnBytesRead;}
Reading from the currently installed firmware
Data was requested from the currently installed firmware image. It can simply be copied
into the caller’s buffer using memcpy.
Caller starts reading from a new area
The Offset parameter is zero, which means the caller starts reading from a new area.
The switch statement is used to determine the filename corresponding to the area.
Attempt to open the file corresponding to the area
An attempt to open the file for reading is made. Details of file opening, like checking for
available storage volumes, has been moved into the function _OpenFirmwareFileForReading
which is not shown here. If opening of the file fails, an error code is returned.
This indicates to the caller that the region cannot be read. If opening succeeds, the
file handle is stored in a global variable to be available for the next call.
Read data from the file
Data is read from the file. If less data than requested was read, the code checks for
filesystem errors. In case of end of file (EOF), the number of bytes
read is returned. The caller must not assume that the end of the file has been reached if
less data than requested has been returned. The caller may call the function again to read more data, in which case
the function will return zero, indicating to the caller that the end of the file
has been reached. In case of any other error, -1 is returned.
The function SBTL_CloseArea() is called by the emBoot-Secure library after it has finished reading
from an area. In this example, only the areas backed by files need to be closed. The Area
parameter is therefore not needed in this case. Only the AreaFile variable is checked for
a file handle, which is then closed.
voidSBTL_CloseArea(unsignedArea){// Mark the parameter Area as unused to avoid// compiler warnings.(void)Area;// If a file is open, close it.if(AreaFile !=0){FS_FClose(AreaFile);AreaFile =0;}}
Writing to flash memory
When the emBoot-Secure library is instructed to update application firmware images or bootloader images in flash memory, it needs hardware specific functions which perform the writing operations. Depending on the agreements made during purchase of the emBoot-Secure license, a flash memory driver for a specific controller is provided alongside the emBoot-Secure core library. Many microcontrollers do not support writing to flash memory while code is executed from flash memory at the same time. Therefore, the functions for writing to flash memory have to be placed in RAM.
This chapter provides hints for placing functions in RAM, and discusses the inner workings of a flash memory driver at a high level.
Placing functions in RAM
The details about how to place a function in RAM depend on the compiler. Usually, the compiler has to be instructed to mark the function for placement in a certain section, which has been configured for placement in RAM in the linker script. The linker will then place the function in a section which is copied from flash memory into RAM during startup. Not all compiler/linker combinations perform the initial copying process from flash into RAM on their own and a custom implementation may be needed. For details, the manuals of the compiler and linker need to be consulted. This section explains how placing a function in RAM works with the SEGGER compiler, the GNU compiler, the IAR compilers for ARM and Renesas platforms, as well as the Renesas compiler in C99 mode.
In the emBoot-Secure library, the instruction for placing a function into RAM is implemented by the SBTL_RAM_FUNCTION macro. This macro has to be placed in front of the definition of each function which needs to be placed in RAM. Unfortunately, some compilers do not allow changing the placement options for a single function with the required granularity, and therefore the macro may affect all function definitions which follow it. Therefore, source code files should be divided into a section of functions with regular placement in flash, while the functions with RAM placement, each prefixed by the macro, follow below them.
The SBTL_RAM_FUNCTION implementations discussed below are activated by default in the file BOOT_ConfDefaults.h. If another compiler is used, the macro has to be appropriately defined in the file BOOT_Conf.h.
SEGGER Compiler, GNU Compiler, IAR (ARM and Renesas) compiler
For these compilers, the RAM placement is achieved using a function attribute which contains the name of the section and an instruction forbidding inlining of the function. The name of the section depends on the linker script. .fast is the default name in used in the linker scripts provided for the SEGGER linker and a common name used in scripts for other linkers.
In C99 mode, the Renesas compiler enables RAM placement through a pragma, which applies to all functions which appear after the pragma. Assuming that the linker script is configured to place the section ram_text in RAM, the pragma can be implemented as follows:
#defineSBTL_MACRO_TO_STRING(x)#x#defineSBTL_RAM_FUNCTION _Pragma(SBTL_MACRO_TO_STRING(section P ram_text))
Flash memory driver functions
The SBTL_WriteFlash() function is called by the emBoot-Secure library during an update to write the new firmware or bootloader code into flash memory. The process of writing to flash memory is highly specific to the employed microcontroller model. Depending on the agreements made during purchase of the emBoot-Secure license, a driver package for a specific controller is provided alongside the emBoot-Secure core library. Since the driver package is usually acquired by customers, this guide does not discuss the details of flash memory programming for a specific controller, but explains the high level details.
The SBTL_RAM_FUNCTION macro is used to place the function in RAM.
Determining the sector number
The SBTL_WriteFlash() function has to take care of both flash erasure and programming. The emBoot-Secure library will examine the flash memory layout defined in BOOT_Conf.h, see Configuration switches for flash memory layout for details. It will make a separate call to
SBTL_WriteFlash() for each sector of flash memory which needs to be written. Therefore, the function can determine
the sector number from the FlashAddr parameter, erase it, and then write the buffer pointed to by
pData into that sector.
Prepare for flash programming
On the MK66F18 processor, which drives the previously mentioned SEGGER emPower evaluation board, clock speed and supply voltages have to be in certain ranges for flash memory programming.
Therefore, in this step, the clock speed and the supply voltages are set to the required values. Also, if interrupts are
enabled, they need to be disabled to avoid jumps into flash memory due to interrupts while flashing is in progress.
Erase flash memory
The flash sector is erased. If erasure fails, programming is skipped but the system still has to be returned
into the previous state, therefore a jump to the end label is performed.
Write to flash memory
The buffer is written to flash memory.
Restore system state
The system is restored to the clock speed, supply voltage and interrupt state as it was at the beginning of the function.
Configuring the CRYPTO library
The emBoot-Secure library handles most of the configuration required for the crypto library, emCrypt, internally. Depending on the signature algorithm and hash function configured in BOOT_Conf.h, the necessary functions of the library are activated. Remaining user-specific runtime configuration is performed in the callback function CRYPTO_X_Config(), which is invoked when SBTL_Init() is called. Any remaining user-specific compile-time configuration is performed in the file CRYPTO_Conf.h.
CRYPTO_X_Config: Exponentiation and hardware support
For signature checking with RSA or ECDSA, a modular exponentiation algorithm has to be configured in the CRYPTO_X_Config() function. The default implementation of CRYPTO_X_Config() provided in the board-specific BOOT_Config_<board>.c file selects a reasonably fast modular exponentiation algorithm with low RAM requirements.
If the microcontroller or its periphery offer cryptographic accelerators, for example a hash calculator implemented in hardware, that can also be activated in this function.
More information can be found in the section CRYPTO_X_Config.
CRYPTO_Conf.h: Software optimization
For many cryptographic algorithms, a time-memory tradeoff can be made: An implementation can either be small (with respect to its code size) and more computation-intensive, or use more space to store pre-computed values that speed up computations.
Algorithms are selected based on the optimization goal configuration in CRYPTO_Conf.h. An optimization goal specifies the application developer’s preference in the tradeoff between code size and performance.
By default, emCrypt selects a balanced configuration that provides reasonable performance at a reasonable code size for most applications. It is recommended to try the balanced default configuration first and assess its performance. If more performance is needed or the code size needs to be reduced, the configuration can be adapted as described below.
Optimization goals can be configured at two levels:
Algorithm-specific optimization goals specify the preferred goal for a particular algorithm.
The global optimization goal sets the general preference. It is applied to all algorithms that do not have an algorithm-specific optimization goal set (fallback).
There are seven optimization goals to choose from:
Optimization goal
Description
SEGGER_OPT_GOAL_SIZE_MIN
Lowest resource requirements without performance restriction. Should be used on constrained systems only.
SEGGER_OPT_GOAL_SIZE_SMALL
Favor low resource requirements at reasonable performance.
SEGGER_OPT_GOAL_SIZE
Favor lower resource requirements at slightly lower performance.
SEGGER_OPT_GOAL_BALANCED
Balance between performance and resource requirements. The common case default.
SEGGER_OPT_GOAL_SPEED
Favor performance at slightly higher resource requirements.
SEGGER_OPT_GOAL_SPEED_HIGH
High performance with reasonable resource requirements.
SEGGER_OPT_GOAL_SPEED_MAX
Maximum performance without resource restriction. May fit only larger systems.
All optimization goal settings default to SEGGER_OPT_GOAL_BALANCED.
An optimization goal configuration can be changed by defining a macro in the file CRYPTO_Conf.h.
The global optimization goal can be set like this:
The SHA384 hash function is also configured through the CRYPTO_OPT_GOAL_SHA512 optimization goal. The SHA384 hash is a truncated SHA512 hash and uses the same implementation internally.
While the performance of the hash functions affects the boot time of the target device, the performance of the encryption algorithm only affects the time required to install a firmware update.
Version numbers
The emBoot-Secure library uses 32 bit unsigned integers to represent version numbers. If the 32 bit version number of an installed firmware image is lower than that of an update package, the update package will be installed. Internally, the bootloader and the application firmware can use their own way to display the version number, for example by interpreting the 32 bit integer as a number of the form M.mm.rrr.
The version number of the application firmware is stored inside the header which is generated during the creation of signed firmware images or update packages. The bootloader can read out this version number by requesting the FirmwareInfo structure for a firmware area using the SBTL_GetFirmwareInfo() function.
Bootloader update packages also contain the version number of the bootloader, which is independent of the firmware application’s version number. When the bootloader is installed, however, the header is lost since the bootloader’s memory region has to start with the vector table. While the bootloader is running, the the emBoot-Secure library needs to know the version number of the currently running bootloader, in order to compare it with version numbers of bootloader update packages. Since it can not read the version number from a header field, it uses the SBTL_GetBootloaderVersion() function instead to determine it.
For more information about how to embed version information into both the bootloader and the application firmware, see Specifying version numbers.
Adding keys to the bootloader
This section explains how to create keys for use with the emBoot-Secure library using an example. For a detailed background about which key types, sizes and algorithms to use, see Passwords, keys, and key files. In this example, keys are generated using the key generation tool, a command-line program that ships with emBoot-Secure. Alternatively, the SEGGER Signature Server can be used for key generation, see Initialization of the Signature Server.
Both ECDSA and RSA keys are supported. In this example, a 2048 bit RSA key will be used. To generate a signing key pair, the key generation tool is used. Using the following command, a 2048 bit RSA key is generated. The public part of the signing key is stored in the file KeyFile1.pub. Since the private key has to remain secret, the -p parameter is specified to enable encryption of the key. The key generation tool asks for a password to encrypt the key before writing it to the file KeyFile1.prv.
KeyToolgen-rsa-s2048--outKeyFile1-p
The private key has to be carefully guarded (see Security recommendations for keys and key files). In order to provide the public key to the bootloader, it is converted to a C file using the key generation tool:
KeyToolrsa2c--inKeyFile1.pub--outsignkey1.c
The resulting C file contains an implementation of SBTL_GetRSAPublicKey(), which returns the key data. This additional source code file has to be added to the bootloader project and linked into the final bootloader image.
If the ECDSA signature scheme is used instead of RSA, the key generation and conversion process is similar. The resulting C file contains a function SBTL_GetECPublicKey() in that case.
For encryption of update packages with AES, a key is required as well. It is generated using the key generation tool. Again, the parameter -p is specified to enforce encrypted storage of the key in the file. The key generation tool writes the encrypted key to the file EncKeyFile1.sec.
KeyToolgen-aes--outEncKeyFile-p
To include this AES key into the bootloader, it is also converted to a C file, this time implementing the SBTL_GetAESKey() function:
KeyToolaes2c--inEncKeyFile.sec--outenckey1.c
The file enckey1.c now contains the AES encryption key as plain text. This additional source code file has to be added to the bootloader project and linked into the final bootloader image as well.
Starting application firmware
When the bootloader has verified the authenticity of the application firmware image, it can launch the application firmware. Before the launch, the bootloader has to take a few preparatory steps.
Deactivating hardware
The bootloader may have activated a hardware cryptographic accelerator module or external flash memory to load the update package. If these are not needed by the application firmware, it should turn these components off again.
Clock and supply voltage configuration
The startup code of the bootloader may have reconfigured the clock and supply voltage settings. If the application firmware contains startup code which also modifies these settings, and expects the processor to be in the default state after reset, the bootloader has to revert these settings. The exact requirements depend on the way in which the clock settings and supply voltages were changed. On some processors, performing the activation steps again in the same order may not cause faults. In that case, the bootloader can leave the settings as they are. Alternatively, the application firmware’s startup code can be modified to leave the clock and supply voltage settings as they were set up by the bootloader.
Turning off interrupts
The processor handles interrupts using the vector table. When the bootloader launches the application, the bootloader’s vector table is still active and any interrupt would cause a jump back into bootloader code. Therefore, the bootloader must disable interrupts, giving the application firmware’s startup code a chance to activate it’s own vector table.
Jumping to the entry point
When the bootloader’s main() function determines whether authentic application firmware is installed, it uses the SBTL_ScanFirmware() function, which stores information about the firmware image into a SBTL_FIRMWARE_INFO structure. This information also contains the address of the application firmware’s entry point. The bootloader can jump to this address using the function pointer stored in the SBTL_FIRMWARE_INFO structure. An abridged code sample follows, see Bootloader update in normal mode for details about the omitted parts.
This section describes how to combine the high level functions provided by the emBoot-Secure library API to create a customized bootloader. Three example bootloader implementations, which ship with emBoot, are explained in detail to understand how the bootloader is implemented. It is assumed that the required callback functions which were explained in the previous sections have been implemented and that the emBoot-Secure library has been configured by adjusting the BOOT_Conf.h file.
Bootloader update in normal mode
This section describes the simplest bootloader implementation which can update itself using normal bootloader update mode. The code is shipped with emBoot-Secure in the file Application/BL_NormalMode.c. The internal flash memory could be configured as described in Simple configuration.
/********************************************************************** (c) SEGGER Microcontroller GmbH ** The Embedded Experts ************************************************************************ ** (c) 2022 - 2026 SEGGER Microcontroller GmbH ** ** www.segger.com Support: www.segger.com/ticket ** ************************************************************************ ** emBoot-Secure * Secure bootloader for embedded applications ** ** Please note: Knowledge of this file may under no ** circumstances be used to write a similar product. ** Thank you for your fairness ! ** ************************************************************************ ** emBoot version: Internal ** ***********************************************************************----------------------------------------------------------------------Purpose : Sample bootloader application for bootloader updates in normal mode.-------------------------- END-OF-HEADER -----------------------------*/#include"BOOT.h"#include"cmsis_compiler.h"/*********************************************************************** Static variables************************************************************************/// Work memory for SBTL_Verify and SBTL_UnwrapstaticSBTL_WORK_MEMORY_workMemory;// Buffer for reading sectors to memory during flashingstaticSBTL_FLASH_BUFF_sectorBuffer;/*********************************************************************** main()** Function description* Application entry point*/intmain(void){SBTL_FIRMWARE_INFOFirmwareInfo;intr;SBTL_Init();SBTL_LOG(("Bootloader version %d starting...",SBTL_GetBootloaderVersion()));// Look for firmware updates, and also check whether the// currently installed firmware can be verified.r =SBTL_ScanFirmware(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r !=0){SBTL_Panic("Scanning for valid firmware failed.");}if(FirmwareInfo.Area ==SBTL_MEM_AREA_FIRMWARE){// Boot into already installed firmware// If applicable, de-initialize any hardware which is not needed// by the application firmware and also reset the clocks and// supply voltages to safe settings.// Disable interrupts__disable_irq();// Jump to firmware entry pointFirmwareInfo.EntryPoint.Jump();}if((FirmwareInfo.IsBootLoaderUpdate ==0)&&SBTL_MEM_AREA_IS_UPDATE(FirmwareInfo.Area)){// Install normal firmware updater =SBTL_UpdateFirmware(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r !=0){// Error updating the firmwareSBTL_LOG(("Error updating the firmware, code: %d",r));SBTL_Panic("Error updating the firmware.");}// Reboot and start firmwareSBTL_ResetHardware();}if((FirmwareInfo.IsBootLoaderUpdate ==1)&&SBTL_MEM_AREA_IS_UPDATE(FirmwareInfo.Area)){// Install bootloader update// Prepare for the bootloader updater =SBTL_PrepareBootloaderUpdate(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r <0){SBTL_LOG(("Error updating the bootloader, code: %d",r));SBTL_Panic("Error updating the bootloader.");}// Perform the bootloader update.// This function will never return.SBTL_PerformBootloaderUpdate(&_sectorBuffer);}// This place is never reached.SBTL_Panic("Bootloader logic failed.");}
Static working memory
Allocates static working memory for the unpacking of the update package and signature validation, as well as a buffer to hold parts of the unpacked update package during flash programming.
Scan for update packages
SBTL_ScanFirmware() is called to determine which action the bootloader should take. It scans the firmware update areas for the presence of a valid update package. If a valid update package is found, it’s version number is compared against the version number of the currently installed firmware. If that is the case, information about that update package is copied to the FirmwareInfo structure. If no suitable update package is available, the installed firmware is verified and header of the installed firmware is copied into the FirmwareInfo structure. If neither a valid update package can be found nor a valid installed application firmware image, an error is returned.
Launch installed application firmware
If the FirmwareInfo.Area contains the area index of the currently installed application firmware image, that image is started. If applicable, any hardware which was configured by the bootloader may need to be deinitialized and the clock and supply voltage settings be returned to default safe settings. In any case, interrupts have to be disabled to ensure no interrupt handlers are triggered during the transition, since the vector table of the bootloader is still active. Afterwards, a jump to the firmware entry point is performed using the function pointer in the FirmwareInfo structure.
Install application update package
If the FirmwareInfo structure points to an area containing an application firmware update, the update process is started. The function SBTL_UpdateFirmware() is called to perform the update and afterwards, the microcontroller is reset. After the reset, the bootloader will verify the newly installed application firmware image again and start it.
Install bootloader update package
If the FirmwareInfo structure points to a bootloader update package, a two-step update process is performed. First, the bootloader update package is unpacked into RAM. Afterwards, the bootloader image is written into flash memory using the SBTL_PerformBootloaderUpdate() function. This function has been placed in RAM, since during the update process, the bootloader code in flash memory is overwritten and can therefore not be executed any more. The function in RAM can continue execution until flashing has finished and then restart the target hardware to boot into the updated bootloader.
Bootloader update in bank swap mode
Bank swap mode is only available on targets with two flash banks which can be swapped, as described in section Configuration with dual bank flash. The code for this example is shipped with emBoot-Secure in the file Application/BL_BankSwapMode.c. The diagram below shows the steps of the update process. The blue numbered dots indicate the same steps in both the diagram and the source code.
Figure: Bootloader update in bank swap mode
/********************************************************************** (c) SEGGER Microcontroller GmbH ** The Embedded Experts ************************************************************************ ** (c) 2022 - 2026 SEGGER Microcontroller GmbH ** ** www.segger.com Support: www.segger.com/ticket ** ************************************************************************ ** emBoot-Secure * Secure bootloader for embedded applications ** ** Please note: Knowledge of this file may under no ** circumstances be used to write a similar product. ** Thank you for your fairness ! ** ************************************************************************ ** emBoot version: Internal ** ***********************************************************************----------------------------------------------------------------------Purpose : Sample bootloader application for bootloader updates in bank swap mode.-------------------------- END-OF-HEADER -----------------------------*/#include"BOOT.h"#include"cmsis_compiler.h"/*********************************************************************** Static variables************************************************************************/// Work memory for SBTL_Verify and SBTL_UnwrapstaticSBTL_WORK_MEMORY_workMemory;// Buffer for reading sectors to memory during flashingstaticSBTL_FLASH_BUFF_sectorBuffer;/*********************************************************************** main()** Function description* Application entry point*/intmain(void){SBTL_FIRMWARE_INFOFirmwareInfo;intr;SBTL_Init();SBTL_LOG(("Bootloader version %d starting...",SBTL_GetBootloaderVersion()));// Determine bank swap stater =SBTL_GetBankSwapState();SBTL_LOG(("Active flash bank: %d",r));if(r ==0){// Banks are currently not swapped,// this is the "normal bootloader".// Look for firmware updates, and also check whether the// currently installed firmware can be verified.r =SBTL_ScanFirmware(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r !=0){SBTL_Panic("Scanning for valid firmware failed.");}if(FirmwareInfo.Area ==SBTL_MEM_AREA_FIRMWARE){// Boot into already installed firmware// If applicable, de-initialize any hardware which is not needed// by the application firmware and also reset the clocks and// supply voltages to safe settings.// Disable interrupts__disable_irq();// Jump to firmware entry pointFirmwareInfo.EntryPoint.Jump();}if((FirmwareInfo.IsBootLoaderUpdate ==0)&&SBTL_MEM_AREA_IS_UPDATE(FirmwareInfo.Area)){// Install normal firmware updater =SBTL_UpdateFirmware(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r !=0){// Error updating the firmwareSBTL_LOG(("Error updating the firmware, code: %d",r));SBTL_Panic("Error updating the firmware.");}// Reboot and start firmwareSBTL_ResetHardware();}if((FirmwareInfo.IsBootLoaderUpdate ==1)&&SBTL_MEM_AREA_IS_UPDATE(FirmwareInfo.Area)){// Install the bootloader update// Load the bootloader update into RAM.r =SBTL_PrepareBootloaderUpdate(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r !=0){gotoerrorEnd;}// Update the shadow bootloader from RAM.r =SBTL_PerformBootloaderUpdate(&_sectorBuffer);if(r !=0){gotoerrorEnd;}// Bootloader update has been written to bank 2.// Swap banks to activate bootloader in bank 2.r =SBTL_SetBankSwapState(1);if(r !=0){gotoerrorEnd;}// Banks have been swapped, reboot.// Function does not return.SBTL_ResetHardware();errorEnd:// Error updating the bootloaderSBTL_LOG(("Error updating the bootloader, code: %d",r));SBTL_Panic("Error updating the bootloader.");}}else{// Banks are currently swapped, // this is the "shadow bootloader".// Load "shadow bootloader" into RAMSBTL_LoadActiveBootloaderIntoRAM(&_sectorBuffer);// Overwrite the bootloader on bank 1 with the "shadow bootloader" from RAMr =SBTL_PerformBootloaderUpdate(&_sectorBuffer);if(r !=0){SBTL_LOG(("Writing bootloader to shadow address failed: %d",r));SBTL_Panic("Writing bootloader to shadow address failed.");}r =SBTL_SetBankSwapState(0);if(r !=0){SBTL_LOG(("Swapping banks after updating shadow bootloader failed: %d",r));SBTL_Panic("Swapping banks after updating shadow bootloader failed.");}SBTL_ResetHardware();}// This place is never reached.while(1);}
Static working memory
Allocates static working memory for the unpacking of the update package and signature validation, as well as a buffer to hold parts of the unpacked update package during flash programming.
Determine the bank swap state
The bootloader calls SBTL_GetBankSwapState() to determine whether the banks are currently swapped.
Banks are not swapped
The bootloader determined that the banks are not swapped. It can proceed with the same steps as the bootloader in normal update mode (see previous section) to scan for update packages, launch currently installed firmware or update the installed firmware.
Load the bootloader update into RAM
The bootloader has determined that a bootloader update package is available. Just like in normal update mode, it unpacks the entire bootloader update package in RAM.
Update shadow bootloader in flash memory
The SBTL_PerformBootloaderUpdate() function is used to write the bootloader update from RAM into the flash memory in flash bank 1, overwriting the normal bootloader.
Bank swap: Activate shadow bootloader
The bootloader instructs the hardware to apply flash bank swapping after the next restart. Afterwards, it performs a hardware reset to launch the bootloader on the other flash bank.
Shadow bootloader is active
The code will be executed again from the top, but this time, the call to SBTL_GetBankSwapState() will indicate that the flash banks are swapped. Hence, the first branch of the if-clause will be skipped and the update process will be continued in the next step.
Load shadow bootloader into RAM
Since the authenticity of the shadow bootloader, which is currently running, has already been determined during its installation, it can now simply use itself as the source for the update of the normal bootloader. It loads itself into RAM using the SBTL_LoadActiveBootloaderIntoRAM() function.
The hardware is instructed to disable the bank swap after the next reset. The shadow bootloader’s work is done. It resets the hardware to restart into the normal bootloader.
Bootloader with rescue firmware
This section describes how to implement a bootloader which can install a rescue application firmware image in case the currently installed application firmware becomes unusable. This could be due to an incompatibility with the device hardware which is only discovered after installation, or because a severe bug is present which prevents obtaining new update packages using this software version.
In that case, the bootloader can be supplied with a rescue firmware update package, which is only installed under special circumstances. The rescue firmware image may have reduced functionality and focus on making a new update package available to the bootloader. The exact circumstances under which it is installed depend on the device and the manufacturer’s precautions. A simple option would be a restore button which is pressed by the user while turning the device on.
In order for the bootloader to be able to find a rescue image, the number of areas containing rescue firmware images has to be defined in BOOT_Conf.h:
#defineSBTL_NUM_AREAS_FAILSAFE 1
Also, the rescue firmware image has to be made accessible via the SBTL_ReadArea() implementation when the emBoot-Secure library is requesting data from it:
intSBTL_ReadArea(unsignedArea,U32 Offset,unsignedBuffSize,U8 *pBuff){if(Area ==SBTL_MEM_AREA_FAILSAFE(0)){// Return data for rescue image}// Return data for other regions}
Below, sample code for such a bootloader is provided. For simplicity, code for updating the bootloader itself has been omitted from this sample since it can be found in the previous two sections. The code is shipped with emBoot-Secure in the file Application/BL_RescueImage.c.
/********************************************************************** (c) SEGGER Microcontroller GmbH ** The Embedded Experts ************************************************************************ ** (c) 2022 - 2026 SEGGER Microcontroller GmbH ** ** www.segger.com Support: www.segger.com/ticket ** ************************************************************************ ** emBoot-Secure * Secure bootloader for embedded applications ** ** Please note: Knowledge of this file may under no ** circumstances be used to write a similar product. ** Thank you for your fairness ! ** ************************************************************************ ** emBoot version: Internal ** ***********************************************************************----------------------------------------------------------------------Purpose : Sample bootloader application with rescue update package logic.-------------------------- END-OF-HEADER -----------------------------*/#include"BOOT.h"#include"cmsis_compiler.h"/*********************************************************************** Static variables************************************************************************/// Work memory for SBTL_Verify and SBTL_UnwrapstaticSBTL_WORK_MEMORY_workMemory;// Buffer for reading sectors to memory during flashingstaticSBTL_FLASH_BUFF_sectorBuffer;/*********************************************************************** RescueButtonPressed()** Function description* Checks whether the rescue button is pressed** Return value* > 0: Rescue button is pressed.* == 0: Rescue button not pressed.*/staticintRescueButtonPressed(void){// Put code for reading the state of the rescue button here// Return 1 if pressedreturn0;}/*********************************************************************** main()** Function description* Application entry point*/intmain(void){SBTL_FIRMWARE_INFOFirmwareInfo;intr;SBTL_Init();SBTL_LOG(("Bootloader version %d starting...",SBTL_GetBootloaderVersion()));if(RescueButtonPressed()==1){r =SBTL_FindRescueFirmware(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r !=0){SBTL_Panic("Error finding recovery firmware.");}r =SBTL_UpdateFirmware(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r !=0){SBTL_Panic("Error installing recovery firmware.");}// If applicable, de-initialize any hardware which is not needed// by the application firmware and also reset the clocks and// supply voltages to safe settings.// Disable interrupts and launch firmware__disable_irq();FirmwareInfo.EntryPoint.Jump();}// Look for firmware updates, and also check whether the// currently installed firmware can be verified.r =SBTL_ScanFirmware(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r !=0){SBTL_Panic("Scanning for valid firmware failed.");}if(FirmwareInfo.Area ==SBTL_MEM_AREA_FIRMWARE){// Boot into already installed firmware// If applicable, de-initialize any hardware which is not needed// by the application firmware and also reset the clocks and// supply voltages to safe settings.// Disable interrupts__disable_irq();// Jump to firmware entry pointFirmwareInfo.EntryPoint.Jump();}if(SBTL_MEM_AREA_IS_UPDATE(FirmwareInfo.Area)){// Install normal firmware updater =SBTL_UpdateFirmware(&FirmwareInfo,&_workMemory,&_sectorBuffer);if(r !=0){// Error updating the firmwareSBTL_LOG(("Error updating the firmware, code: %d",r));SBTL_Panic("Error updating the firmware.");}// Reboot and start firmwareSBTL_ResetHardware();}// This place is never reached.SBTL_Panic("Bootloader logic failed.");}
Static working memory
Allocates static working memory for the unpacking of the update package and signature validation, as well as a buffer to hold parts of the unpacked update package during flash programming.
Function for rescue condition
This function stub needs to contain code to check whether a rescue condition has occurred, for example whether the user is pressing a certain button.
Check for rescue condition
The bootloader main function checks whether a rescue firmware restoration is requested.
Scan for rescue update packages
The SBTL_FindRescueFirmware() function is used to scan for rescue update packages. It behaves differently from the SBTL_ScanFirmware used in previous sections, because it only checks for the presence of valid update packages, regardless of their version number.
Install rescue image
The FirmwareInfo structure points to an area containing the rescue update package. The function SBTL_UpdateFirmware() is called to perform the update.
Start rescue firmware image
Since the rescue condition is only valid for as long as the user presses the button, the installed rescue firmware is launched directly, without a reboot. This prevents the bootloader from reinstalling the problematic firmware image instead of launching the rescue version.
Scan for normal updates
This part of the code is only reached if the rescue button was not pressed during startup. The code scans available firmware update packages and compares them against the version of the currently installed application firmware image. Since the code is the same as in the section Bootloader update in normal mode, the annotations are not repeated here.
Adapting application firmware
Application firmware and bootloader code can be created as independent projects, or as two compilation targets in a single project, depending on user preferences and the amount of code shared between them, for example code for accessing update packages in a filesystem. In any case, the application must be adapted to the flash memory partitioning chosen earlier. Also, the bootloader sets up its own vector table and stack region. The application has to activate its own vector table and stack region. Additionally, the bootloader may configure additional hardware elements, like system clocks, supply voltages, and additional hardware needed to install updates, like external SPI flash memory or a hardware hash acceleration module. During the transition from bootloader to application firmware, these settings may need to be reversed or adapted to the applications needs.
This chapters requires either an existing project for the application firmware or an empty (“Hello-World”) application project.
Adapting the linker script
The first step in adapting the application firmware to the bootloader is the adaptation of the linker script.
This is required in order to make room for the bootloader and the firmware header in memory.
The following example of a SEGGER Linker script extends the sample described in Partitioning the non-volatile memory for emBoot-Secure.
Since the APP region is placed directly behind the HEADER region, in most cases its start address is not compatible with the alignment requirements of the vector table. In order to guide the linker to place the vector table at the first available address which fulfills its alignment requirements, the instruction for placing the vector table is placed before any other placement instructions for the APP region. The linker is free to place any fitting sections in the space before the vector table.
// Linker_Application.icf
define region FLASH1 = [from 0x00000000 size 0x00200000];
#define BOOTLOADER_SIZE 128k
// HEADER_SIZE must match value SBTL_FIRMWARE_HEADER_SIZE in Boot_ConfDefaults.h.
#define HEADER_SIZE 64
define region BOOTLOADER = [from 0x00000000 size BOOTLOADER_SIZE];
define region HEADER = [from BOOTLOADER_SIZE size HEADER_SIZE];
define region APP = FLASH - BOOTLOADER - HEADER;
// snipped: definitions of blocks and sections
place in APP
{ block vectors }; // Vector table section
place in APP with minimum size order
{
block tdata_load, // Thread-local-storage load image
block exidx, // ARM exception unwinding block
block ctors, // Constructors block
block dtors, // Destructors block
readonly, // Catch-all for readonly data
readexec // Catch-all for (readonly) executable code
};
Activating the vector table
For many ARM processors, the alignment of the vector table depends on its size. The alignment usually has to be to the next-larger power of two. For the MK66F18 mentioned earlier, the vector table has to have 512 byte alignment. The assembly file which defines the vector table therefore needs to include this information, provided by the .balign directive. Alternatively, the alignment can also be specified in linker scripts.
When the bootloader activates the application, it reads its entrypoint from the header produced by the FirmwareTool
and performs a jump to this address, which is usually the reset handler defined by the application. Since the
microcontroller activated the bootloader’s vector table during startup, the application’s reset handler has to
activate its own vector table. The startup code provided by the microcontroller’s manufacturer, CMSIS code or the compiler vendor
usually does this by referring to the vector section using its symbolic name. For some variants of startup code,
this step has to be manually activated using a compiler flag, while some startup code contains
a hardcoded address such as 0x0 for the location of the vector table. In these cases, either the flag has to
be set or the startup code has to be modified accordingly. In case of startup files delivered with Segger’s embOS, the __VTOR_CONFIG flag has to be defined project-wide.
The vector table not only contains the application’s entry point, but also
the starting address for the stack pointer. When the bootloader jumps to the application’s entry point, the stack
pointer is still pointing to the stack defined by the bootloader. Therefore, the startup code also has to read
the desired starting point of the stack from the application’s vector table. Again, some startup code requires
a compiler flag to be set in order to perform this step, while in other code, this step may be missing. In case of startup files delivered with Segger’s embOS, the __INITIALIZE_STACKPOINTER flag has to be defined project-wide.
While adapting the application firmware to be launchable by the bootloader, proper initialization of the vector table
and stack pointer addresses should be checked by setting a breakpoint into the application’s main() function.
If there is a difference from the expected settings, the startup code should be inspected for additional places in
which it modifies the respective registers. The CMSIS files supplied by the microcontroller’s manufacturer may contain such code, in addition
to the start-up code implemented by the compiler or embedded operating system vendor.
Hardware reconfiguration
When a microcontroller resets, its supply voltages and clock settings are set to safe defaults. The startup code is responsible for adjusting these settings to fulfill the requirements of the firmware. The requirements can be low power consumption, high processing speed or something more balanced. To achieve this state, the startup code adapts the supply voltages to match the desired clock speed and configures the clock sources and dividers. When the bootloader hands over control to the application firmware, its startup code may have already configured non-default clock and supply voltage settings. In the best case, a repetition of the configuration steps in the startup code will not lead to faults and no adaptation is needed. In other cases, either the startup code of the application has to take the state left by the bootloader into account, or the bootloader has to de-initialize these settings.
Passwords, keys, and key files
emBoot-Secure makes use of cryptographic procedures in order to protect firmware images from malicious modification and inspection. These procedures require secrets to operate, typically in form of cryptographic keys.
This section gives a high-level overview of the secrets involved in the security architecture of emBoot-Secure and provides guidance on how to generate, store, protect, and use them.
Overview
emBoot-Secure with and without the Signature Server
There are two possible ways of using emBoot-Secure: It can be used with or without the SEGGER Signature Server. The Signature Server is a dedicated hardware device that can be used to generate and store keys securely and to generate firmware signatures on a trusted device (see chapter The Signature Server). Alternatively, keys and signatures can be generated on a personal computer. The following figures provide an overview of the secrets involved in both scenarios. Each secret is explained in detail in later sections in this chapter.
Figure: Overview of secrets in emBoot-Secure (without Signature Server)
Figure: Overview of secrets in emBoot-Secure (when using the Signature Server)
Overview of user roles
The figure above depicts various user roles, which are explained in detail in the section User roles.
In short, if emBoot-Secure is used without the Signature Server, there is only a single user role: the Release Manager. This role is responsible for creating update packages for new firmware releases.
If the Signature Server is used, the Release Manager becomes a user of the Signature Server and uses the keys stored in the server’s key store. Furthermore, two additional user roles exist for the Signature Server: Administrator and Device Owner. A Device Owner is a user with highest privilege and has access to all keys on the Signature Server.
Administrators have similar privileges to Devices Owners, but can only manage a subset of keys on the Signature Server.
Types of secrets
emBoot-Secure uses three conceptually different kinds of secrets: passwords, symmetric keys, and asymmetric keys (also referred to as key pairs). While passwords are a well-known concept, keys need some explanation.
Cryptographic keys
A cryptographic key, or key for short, is a sequence of bits that is used to control cryptographic operations. Depending on the cryptographic algorithm in use, the key has to meet specific criteria, for example with respect to mathematical properties or its randomness. emBoot-Secure ships with a software program that generates the required keys and takes these requirements into account.
There are two common types of cryptographic keys: symmetric and asymmetric keys.
Symmetric keys
An algorithm that utilizes symmetric keys uses the same key for all operations that it performs. For example, a symmetric encryption algorithm uses the same key for both of its operations: encryption and decryption. emBoot-Secure uses a symmetric encryption algorithm to encrypt update packages.
Asymmetric keys
In contrast, asymmetric keys always appear in pairs of two: a public key and a private key. Both keys are linked together, but serve different purposes. In an asymmetric encryption algorithm, for example, the public key is used for encryption, while the corresponding private key is used for decryption. In emBoot-Secure, asymmetric keys are used to implement digital signatures and authentication.
Storing keys
Symmetric keys and private keys must be stored securely. Because of their complexity, keys cannot easily be memorized. emBoot-Secure provides two options for key storage:
First, keys can be exported to a key file, a small file that can be stored on a digital medium. In order to protect the key file from unauthorized access, it is protected with a password.
Second, some keys can be stored securely in the Signature Server.
Digital signatures
emBoot-Secure ensures that only firmware images that have been approved by the manufacturer can be executed on the target device. This functionality is implemented through the cryptographic concept of digital signatures.
Much like a handwritten signature on a document, a digital signature shows that a particular person (or company) approves of the content of the signed object. In the case of emBoot-Secure, the signed object is the firmware image.
On an abstract level, this digital signature works as follows: The signer uses the firmware image and a private key to compute a signature value. The signature value is a bit string that is appended to the firmware image. It proves that the firmware image is authentic: It is cryptographically guaranteed that only the owner of the private key (i.e., the manufacturer) can generate that bit string.
On the target device, a cryptographic procedure uses a corresponding public key to verify that the signature on the firmware image was in fact generated by the manufacturer (i.e., the owner of the private key). This verification step is performed on every boot and when installing firmware updates. Firmware images with invalid signatures are rejected.
Secrets in emBoot-Secure
This section describes the secrets that appear in the security architecture of emBoot-Secure and that the users interact with.
First, we discuss the minimal set of secrets that is present in any scenario where emBoot-Secure is used.
Then, we discuss additional secrets that are only required when the Signature Server is used.
Signing key pair
Overview: Private signing key
Secret?
Yes
Owner
With Signature Server: Device Owner, Administrator Without Signature Server: Release Manager
On each target device (included in bootloader code)
One goal of emBoot-Secure is to ensure the authenticity of firmware images. This means that only firmware images that are approved by the manufacturer can be executed on a target device. The manufacturer’s approval is expressed through a cryptographic signature, which is attached to a firmware image when it is packaged into an update package to be released. This signature is verified by the target device during the update process and every time the device boots up. If the firmware image does not have a valid signature, the respective process (update or boot) is aborted.
To generate and verify signatures, emBoot-Secure uses an asymmetric signing key pair. When no Signature Server is used, this key pair is generated by a Release Manager on a PC. If a Signature Server is used, a Device Owner or Administrator can generate the key pair on the Signature Server.
In any case, the key pair is only generated once before the first firmware release and remains the same throughout the product’s lifetime.
The signing key pair consists of a public signing key and a private signing key which serve different purposes and have to be treated differently:
The private signing key is used to sign firmware images. Anyone who has access to this key can generate valid update packages that the target device will accept. Therefore, this key remains with the manufacturer and must be kept confidential at all times. In addition, it is recommended to keep backup copies of this key in multiple safe locations.
The private signing key can be stored in a key file on a digital medium, such as a hard drive. More details on how to handle key files are provided in the section Security recommendations for keys and key files. It can also be imported into the Signature Server, where it is stored securely and can be used to create signatures through a protected interface.
Warning
The private signing key is the most important key in the security architecture of emBoot-Secure. If a malicious actor gains access to this key, they can sign arbitrary firmware images that the target device will accept as valid. If the private signing key is lost, it will be impossible to create new update packages that the target device will accept.
The public signing key is used to verify signed firmware images. This key is integrated into the bootloader and ships with the target device. It does not have to be kept confidential.
Password-protected key file in multiple safe locations (see recommendations); on each target device (included in bootloader code)
emBoot-Secure can optionally also encrypt the firmware image in the update package. Encryption provides confidentiality, i.e., it prevents third parties from inspecting the firmware. This security service is based on a symmetric firmware encryption key. The encryption is an optional feature - when the bootloader supports encrypted update packages, it can still process update packages which are not encrypted.
The firmware encryption key is generated on a PC (using the key generation tool) before the first firmware release and remains the same throughout the product’s lifetime. It is stored in a password-protected key file. It is recommended to protect the key file with a strong password. More details on how to handle key files are provided in the section Security recommendations for keys and key files.
It is possible to store multiple encryption keys in a single bootloader. This provides a means to switch to another encryption key in case the first key is compromised.
Secrets related to the Signature Server
Two additional secrets come into play when emBoot-Secure is used together with the Signature Server: the authentication key pair and the signing password. Both secrets restrict access to the Signature Server and the key material enclosed in it.
Specifically, the Signature Server distinguishes multiple user roles: Device Owner, Administrator, and Release Manager (see User roles). In short, Device Owners and Administrators configure the Signature Server and manage its key storage, while Release Managers use those keys to generate signatures for new firmware releases. These user roles use different secrets to authenticate.
Authentication key pair
Overview: Private authentication key
Secret?
Yes
Owner
Device Owner, Administrator
Purpose
Prove the Administrator’s identity to the Signature Server
Device Owners and Administrators are authenticated through their personal authentication key pair. This key pair is generated on the user’s PC. Similarly to a signature key pair, it consists of a public and a private key component. The private authentication key remains with the user and must be kept safe and confidential. It is stored in a key file that should be protected with a strong password. More details on how to handle key files are provided in the section Security recommendations for keys and key files.
The public authentication key is transmitted to the Signature Server and stored there to authenticate the user in the future.
Signing password
Overview: Signing password
Secret?
Yes
Owner
Release Manager
Purpose
Prove the Release Manager’s identity to the Signature Server; verify their identity on the Signature Server
Generation
Configured in the Signature Server by the Administrator
Storage
For proof: memorized by Release Manager or stored in secure password storage; for verification: Signature Server
Release Managers authenticate with a personal signing password. Signing passwords are set up by an Administrator.
Every signing password must be strong and stored only in safe places (e.g., memorized or stored in a secure password manager), as anyone who knows a signing password and has access to the Signature Server is able to produce valid update packages. We recommend following the password guidelines of your local cybersecurity authorities, such as the Federal Office for Information Security (BSI) in Germany.
Choosing a signature scheme and its parameters
emBoot-Secure supports two different signature schemes for signing firmware images, each of which can be further configured with various parameters that impact the overall level of security. Before signing the first firmware release, a signature scheme and the corresponding parameters must be selected.
Naturally, security does not come for free: A higher level of security often also increases the time and memory requirements of the underlying cryptographic algorithms, impacting the boot time of the target device as well as the duration of the update process. This section provides guidance on the selection of schemes, parameters, and algorithms, allowing the user to find a suitable trade-off for their application. Additional information on the performance impact of various parameters is provided in the section Resource use and performance.
Generally, emBoot-Secure supports the following variants of digital signatures:
RSA signatures (RSASSA-PSS) with SHA-1, SHA-256, or SHA-512 hashes and key lengths up to 8192 bits
ECDSA signatures with SHA-1, SHA-256, SHA-384, or SHA-512 hashes on the curves listed below
The following curves are supported for the ECDSA signature scheme:
brainpoolP256r1: 256 bits
brainpoolP320r1: 320 bits
brainpoolP384r1: 384 bits
brainpoolP512r1: 512 bits
NIST P-256 (secp256r1): 256 bits
NIST P-384 (secp384r1): 384 bits
NIST P-521 (secp521r1): 521 bits
Precedence of any applicable regulations
If the target device falls under any cybersecurity regulation, the signature scheme and its parameters should be chosen according to the requirements and/or recommendations of the relevant regulatory bodies.
If this is not the case, the following sections provide some general guidance based on the recommendations of the German Federal Office for Information Security (BSI TR-02102-1) and the National Institute of Standards and Technology of the United States (NIST SP 800-78-5 and NIST SP 800-131A Rev. 2).
Signature scheme
First, a signature scheme must be selected. emBoot-Secure supports RSA and ECDSA signatures.
RSA is an established cryptographic mechanism since the 1970s, while ECDSA was first proposed in the early 1990s.
The German BSI considers cryptography based on RSA and elliptic curves (EC) equally secure, but notes that EC algorithms are more efficient for high security levels (see BSI TR-02102-1, Section 2.3). In particular, RSA requires larger keys and produces larger signatures compared to ECDSA at the same security level. Generating large RSA keys on the Signature Server can take up one hour, while ECDSA keys can be generated within seconds.
Note
If you have the choice, prefer ECDSA over RSA to get smaller signatures at the same level of security.
Key size and curves
Next, a key size (for RSA) or a curve (for ECDSA) has to be selected. These parameters impact the level of security of the resulting signature significantly.
For RSA: The German BSI recommends to use keys that are at least 3000 bits long (see BSI TR-02102-1, Table 1.2). NIST recommends at least 3072 bits for long-term applications (see NIST SP 800-78-5, Table 2).
For ECDSA: The key size depends on the chosen curve. The German BSI recommends using one of the “Brainpool” curves (see BSI TR-02102-1, Section 2.3) with a size of at least 250 bits (see BSI TR-02102-1, Table 1.2).
All Brainpool curves supported by emBoot-Secure fulfill this key size requirement.
NIST recommends using one of their own curves, at least P-256 or higher (see NIST SP 800-78-5, Table 2). All NIST curves supported by emBoot-Secure fulfill this requirement.
The major difference between the Brainpool and NIST curves lies in the entity that selected the cryptographic parameters for the curves. Brainpool is a working group of German institutions, universities, and companies. NIST is an institute of the United States. There is no noticeable performance difference between Brainpool curves and NIST curves of (approximately) the same length.
Note
If you have the choice, choose the following parameters for a reasonable level of security:
For RSA: Use a key size of at least 3072 bits.
For ECDSA: Use at least a 256 bit curve from the preferred standardization body.
Hash function
Finally, a hash function has to be selected.
The SHA-1 hash function is considered insecure and should be avoided whenever possible; it should only be used where performance is crucial (see section Resource use and performance) or where compatibility with legacy systems has to be maintained.
The remaining hash functions, SHA-256, SHA-384, and SHA-512, are generally considered secure (see BSI TR-02102-1, Section 4, and NIST SP 800-131A Rev. 2 Rev. 2, Table 8), but require increasing computation time and storage. For most applications, SHA-256 provides an appropriate level of security.
Note
If you have the choice, use at least the SHA-256 hash function. Avoid SHA-1.
Summary and final recommendation
In summary, if no external regulations impose other requirements on the target device, the following configuration is a reasonable choice in most scenarios:
A firmware image can optionally be encrypted using a symmetric cipher. If encryption is enabled, the firmware image is encrypted when it is packaged into an update package. The update package is then decrypted on the target device during the update process. Afterwards, the firmware image is stored in plain in the target’s flash memory.
emBoot-Secure implements this feature using a strong encryption algorithm, the Advanced Encryption Standard (AES), with a key length of 128, 192, or 256 bits. This algorithm is generally considered secure (see BSI TR-02102-1, Section 3.1, and NIST SP 800-131A Rev. 2, Table 1). It is used in Galois/Counter Mode (GCM), which is considered a secure way of using AES to decrypt larger amounts of data (see BSI TR-02102-1, Section 3.1.1, and NIST SP 800-38D). An additional benefit of AES-GCM is that an additional layer of authentication is provided, allowing the system to detect malicious or accidental modifications as early as possible. If a modification of the update package is detected at this stage, it is flagged as invalid and not considered for installation.
Note that firmware encryption has inherent limitations, even when used with strong ciphers. The encryption protects the confidentiality of
the firmware image only while it is “in transit”, i.e., as long as it is packaged in the update package.
Malicious actors with physical access to a target device can attempt to extract the firmware encryption key or the decrypted firmware image
itself directly from the target’s flash or memory. Any protection of the firmware and the encryption key inside the device may
be supported by the target hardware.
Security recommendations for keys and key files
There are a few things to consider when operating with files that contain private keys. This applies to private signing keys (when stored outside the Signature Server) as well as the private authentication keys of the Signature Server. Files containing public keys can be treated more leniently, as they do not contain any confidential information.
Generally, long and complex passwords are considered stronger than short and simple passwords. Dictionary words or company names, such as the name of the manufacturer of the target device, do not qualify as strong passwords. Passwords should be memorized or stored in secure locations, such as secure password managers.
Only use dedicated media to store key files
Whenever a private key is stored on a digital medium (e.g., in a file on a hard disk), it leaves traces on the medium that persist even if the file is removed or the medium is formatted. This is due to the way most digital media work internally: when a file is removed, the associated data structure is not immediately wiped from the medium. Instead, only an entry in the index of the file system is removed. This means that the actual private key data remain on the medium (until they are overwritten by new data eventually) and can be recovered with data recovery software or in specialized hardware labs.
Therefore, it is recommended to store private keys only on digital media that are dedicated for this purpose. Besides the Signature Server, this could be a dedicated external hard drive that is only used to keep private keys.
It should also be avoided to save a private key to a computer’s local hard disk temporarily (for example, after it was generated) and then copy it over to an external medium for long-term storage. This process leaves traces of the private key on the computer’s local hard disk.
Keep backup copies in safe places
It is further recommended to keep multiple copies of important key files, especially of the private signing key. A commonly used rule of thumb is the “3-2-1 backup strategy”: store at least three copies of the key, on at least two different types of media, and keep at least one of the copies in a different location (e.g., in a safe deposit box at a bank).
It is important to choose reliable storage media for this key storage. The use of USB flash drives, SD cards, and similar flash media is not recommended due to their poor long-term reliability. As a backup of last resort, key files can also be printed out on paper.
An appropriate backup strategy is required even when the Signature Server is used. The Signature Server can be used to hold one of the copies of a key, but it should not hold the only copy. Being a hardware device, the Signature Server is not immune to failure. In addition, an Administrator could accidentally remove a key.
Although it may seem convenient, it is considered bad practice to store private key files in source code repositories, as those tend to have complex and intransparent access control structures and the storage devices that contain the repository are typically out of the user’s control.
The Signature Server
The Signature Server is a hardware device that stores private signing keys securely and uses them to generate signatures for update packages. It restricts access to those signing keys through an interface that requires authentication.
This chapter explains the communication interfaces of the Signature Server, its user roles, how to connect to it, how to initialize it, and how to operate it.
Hardware overview
This section describes the external features of the Signature Server. The following figure provides an overview.
No.
Component
Front
(1)
USB-C port (power supply and communication)
(2)
Ethernet port
(3)
Push button
Top
(4)
Status LEDs
Ports and push button
There are two ports on the front of the server: a USB-C port (1) and an Ethernet port (2).
The USB port is used to power the device and as a communication interface for administrative operations, such as managing keys.
The Signature Server consumes less than 1 watt of power and can be powered either by a computer or a dedicated power adapter.
The Ethernet port is used as a communication interface to request and transmit new signatures.
Furthermore, there is a push button (3) on the front of the Signature Server. This button is used to enable the USB command interface (see Connecting to the USB interface) and to confirm dangerous operations, such as a factory reset.
Status LEDs
On the top of the Signature Server is a row of three status LEDs (4): Power, Ready, and Activity. Each LED can light up in one of three colors, red, green, or orange, indicating different states of the device.
LED patterns in normal operation
During normal operation of the Signature Server, the Power LED lights up green.
If the Power LED flashes green, the USB command interface is enabled (see Connecting to the USB interface).
The Ready LED indicates the Signature Server’s global state (see Signature Server global states), and the Activity LED indicates the status of command execution.
When the Signature Server updates its own firmware or encounters an error condition during startup, the Power LED lights up in orange. In this case, the Ready and Activity LEDs are used as status indicators.
Power
Ready
Activity
Description
Signature Server in startup phase
Starting Signature Server firmware
Invalid Signature Server firmware
Firmware update in progress
Bootloader update in progress (update phase 1)
Bootloader update in progress (update phase 2)
Physical security
The Signature Server should be kept in a safe and trusted environment at all times.
The keys stored on the Signature Server cannot be used or exported without prior authentication. However, everyone with physical access to the device can unlock the USB command interface and, at the very least, reset the Signature Server to factory state, erasing all the keys stored on the device.
Signature Server global states
The Signature Server can be in one of the following states:
Factory state
The Signature Server does not contains any keys, either because it is a new device or a reset to factory state has been performed.
In this state anybody can take ownership of the Signature Server, see Initialization of the Signature Server.
Owned
A Device Owner key has been set and the Signature Server is owned by this Device Owner.
Operational
The device has been configured and at least one signature key and a corresponding Release Manager is installed.
Fault
The Signature Server can’t access the keys anymore due to a problem with the key store flash memory (corrupted data, read/write access error).
In this case the Signature Server may be power-cycled in order to recover from a nonrecurring flash read problem.
But if the Signature Server remains in “Fault” state or shows this state multiple times, it should be taken out of service.
User roles
The Signature Server distinguishes three user roles with different privilege levels: Device Owners, Administrators and Release Managers.
In short, Device Owners are permitted to configure the Signature Server and to manage all keys stored on it. They can also set up Administrator users.
Administrators have the same permissions as Device Owners, except that they can only manage a subset of the keys stored on the Signature Server.
Release Managers use specific keys on the Signature Server to generate signatures for update packages.
There is a single Device Owner for each Signature Server, but there can be multiple Administrators and multiple Release Managers. It is recommended to make use of this permission scheme and set up individual user credentials for each person that needs to access the Signature Server. User credentials should not be shared.
If the same person acts as an Administrator (or Device Owner) and as a Release Manager, they are assigned two credentials.
Device Owner role
Overview: Device Owner role
Tasks
Manage server configuration, create Administrators, manage signing passwords, perform firmware updates (of the Signature Server)
The Device Owner puts the Signature Server into operation: This role is automatically assigned to the first user who uploads a public authentication key.
A Device Owner accesses the Signature Server via the USB command interface and authenticates themselves with their personal private authentication key. To validate the Device Owner’s identity, the Signature Server stores the Device Owner’s public authentication key.
The Device Owner is permitted to manage the server’s configuration and to perform firmware updates if needed. In addition, the Device Owner is responsible for creating Administrator accounts by importing the public authentication keys of the Administrators into the device.
The Device Owner can further manage all private signing keys on the server (e.g., import or generate new keys, or export or remove existing keys), and can also manage Release Manager users if needed. If the
Signature Server is used by a very small group of people, there may be no need to set up distinct Administrator users, as the Device Owner can perform all operations that an Administrator can perform as well.
An Administrator accesses the Signature Server via the USB command interface and authenticates themselves with their personal private authentication key. To validate the Administrator’s identity, the Signature Server stores the Administrator’s public authentication key.
The Administrator role is very similar to the Device Owner role. Administrators can also configure the Signature Server, and they can manage private signing keys that are stored in the Signature Server’s key store. More precisely, they are permitted to import, export, generate, and remove private signing keys. In contrast to Device Owners, however, Administrators can be restricted to only have access to a subset of keys.
In addition, Administrators manage Release Managers (see Signing password) and can grant them permission to use private signing keys.
An Administrator uses the Signature Server administration tool to interact with the Signature Server and optionally the key generation tool to create key pairs for signing.
Release Manager role
Overview: Release Manager role
Tasks
Generate signatures using private signing keys stored in the Signature Server
A Release Manager accesses the Signature Server via USB or Ethernet and authenticates themselves with their personal signing password. This password is set by an Administrator or Device Owner.
When the Release Manager prepares a new firmware release, they use the firmware preparation tool to connect to the Signature Server and to generate a signature for the update.
Release Managers can only use private signing keys for which they were granted permission (see Granting permission).
Sample Signature Server configuration
This section shows an example of a Signature Server configuration for two products using emBoot-Secure.
Responsible for the key management of product 1 is the Administrator Admin1a and his substitute Admin1b.
There are two release managers for product 1 using signature keys SignKey1a and SignKey1b.
Responsible for the key management of product 2 is the Administrator Admin2.
The release manager for product 2 is RelManager2 using signature key SignKey2.
Figure: Overview of user roles on the Signature Server: Two teams working on separate products.
The output of the ’list’ command of the Signature Server (see Listing users and keys) looks like:
Name Usage Typ Att Accessible to------------------------------------------------Owner ECDSA Own OwnerAdmin1a ECDSA Adm Admin1aAdmin1b ECDSA Adm Admin1bSignKey1a ECDSA Sig noEx Admin1a,Admin1b,RelManager1a,RelManager1bSignKey1b ECDSA Sig noEx Admin1a,Admin1b,RelManager1a,RelManager1bRelManager1a PWD Usr Rem Admin1a,RelManager1aRelManager1b PWD Usr Rem Admin1a,RelManager1bAdmin2 ECDSA Adm Admin2SignKey2 RSA Sig Admin2,RelManager2RelManager2 PWD Usr Rem Admin2,RelManager2
Connecting to the Signature Server
The Signature Server can be controlled via USB or Ethernet. Both interfaces can be used to request new signatures, but key management commands, such as generating, importing, and exporting keys, can only be sent via the USB interface.
Connecting to the USB interface
In order to connect to the Signature Server via USB, the USB command interface must first be unlocked as follows:
Connect the USB cable to the Signature Server and to the user’s PC.
Wait for the Signature Server to start up. The Signature Server is ready when the Power LED lights up green and no error is indicated (see Status LEDs).
Push and hold the button on the front of the device for one second. The Power LED begins flashing green to indicate that the USB command interface is enabled. The Signature Server administration tool and the firmware preparation tool can now be used to communicate with the Signature Server.
This unlocking procedure must be repeated whenever the Signature Server was unplugged, lost power, or did not receive a command for 20 minutes.
The USB command interface does not require any custom drivers on modern operating systems.
On Linux systems, however, the Signature Server’s USB command interface can only be accessed by processes running with root privileges by default. In order to use the interface with regular user privileges, a udev rule has to be configured. The emBoot-Secure shipping package contains a sample configuration file 99-Segger-SigServer.rules, which can be copied to /etc/udev/rules.d on the user’s machine. Refer to the Linux manual page for udev for more information.
Configuring and connecting to the Ethernet interface
The Ethernet interface uses DHCP to acquire an IPv4 address by default. It also provides it’s default hostname SignatureServer-<Serialnumber> to the DHCP server such that its name can be resolved by a local DHCP server. It also advertises its presence using mDNS. See Specifying a Signature Server address for more details about how to connect to the server in this case.
It’s configuration can be changed once a Device Owner has been taken ownership of the Signature Server, see section Setting up the Device Owner account.
Custom network parameters can be set up via the USB command interface and the Signature Server administration tool. The following properties of the Signature Server can be configured:
This section guides the user through the initialization process that brings the Signature Server from the factory state into the operational state.
Setting up the Device Owner account
The first setup step is to set up the Device Owner account to manage the Signature Server and the Administrators (see Device Owner role for more information). To this end, the Device Owner needs to generate an authentication key pair and import it into the Signature Server. The purpose of this key pair is explained in the section Authentication key pair. In short, it identifies and authenticates the Device Owner and has to be passed to the Signature Server administration tool whenever an administrative command is executed.
Generating an authentication key pair
The authentication key pair can be an RSA or an ECDSA key pair. It is generated with the key generation tool. For example, an ECDSA key pair on a 256-bit curve can be generated as follows:
This command may take some time, especially if large RSA keys are generated. It creates two key files, auth_key.prv (containing the private authentication key) and auth_key.pub (containing the public authentication key). The tool will ask for a password to protect the private key file. A strong password should be chosen for this purpose.
The private key file should be stored only in safe locations and backup copies should be created. For further recommendations on how to deal with key files, see Security recommendations for keys and key files.
Importing the authentication key pair
While the private key file remains with the Device Owner, the public key needs to be imported into the Signature Server. The import of an authentication key is an administrative operation, which has to be performed via the USB interface as follows:
Use the USB cable to connect the Signature Server to the Device Owner’s PC.
The tool will ask for the password of the private authentication key file that was selected during generation in the previous section.
Note that the --in and --auth-key parameters in the example command above refer to the same authentication key pair. This ony applies when importing the first authentication key. For any later import operations, a previously imported authentication key pair must be used. In other words: The first Device Owner can enroll themselves with their own key, but any additional Administrators have to be enrolled by an existing Device Owner.
If the import was successful, the tool confirms the operation.
Setting up an Administrator account
Once the Device Owner has been set up, an Administrator account can be generated. For authentication purposes, another authentication key pair has to be created. The Administrator generates this key pair using the key generation tool and provides the public authentication key to the Device Owner. Assuming the Administrator’s public authentication key is stored in E:\admin_auth_key.pub, the Device Owner uses the following command to create an Administrator account named Admin:
The tool will ask for the password of the Device Owner’s private authentication key file and confirm the operation once completed. The tasks in the following sections can be carried out by the Administrator.
Generating the first signing key pair
Next, a signing key pair has to be generated and placed in the Signature Server’s key store. This key pair can later be used to generate signatures for firmware images. More details can be found in the section Signing key pair.
There are two ways to generate a signing key pair: It can either be generated on the Administrator’s PC using the key generation tool and then imported into the Signature Server, or it can be generated on the Signature Server itself. The following sections explain both approaches.
Note that the properties of the signing key pair decide about the security level of the signatures that are generated later. Refer to the section Choosing a signature scheme and its parameters for guidance on this matter. In the following examples, a key pair for ECDSA signatures is generated, using a 256-bit curve.
Alternative 1: Generating a signing key pair on a PC
A new signing key pair can be generated with the key generation tool, for example:
KeyTool gen-ecdsa -s 256 -p --out E:\sign_key
This command may take some time, especially if large RSA keys are generated. It creates two key files, sign_key.prv (containing the private signing key) and sign_key.pub (containing the public signing key). The tool will ask for a password to protect the private key file. A strong password should be chosen for this purpose.
The private key file should be stored only in safe locations and backup copies should be created. For further recommendations on how to deal with key files, see Security recommendations for keys and key files.
Next, the private signing key has to be imported into the Signature Server. The import of a signature key is an administrative operation, which has to be performed via USB and while the USB command interface is unlocked. Use the Signature Server administration tool to import the private signing key, for example:
The tool will ask for the password of the private signature key file that was selected above and for the password of the Administrator’s private authentication key file.
If the import was successful, the tool confirms the operation.
Alternative 2: Generating a signing key pair on the Server
Alternatively, the signing key pair can be generated on the Signature Server itself. This operation must be triggered though the Signature Server administration tool while the Signature Server is connected via USB and the USB command interface is unlocked. For example:
The tool will ask for the password of the Administrator’s private authentication key file. The command may take some time to complete, especially if large RSA keys are generated. Once completed, the public signing key is exported to a key file on the Administrator’s PC. This public key will be included in the bootloader for signature verification later.
If the key pair was successfully generated, the tool confirms the operation.
Key export
It is strongly recommended to keep backup copies of the private signing key (see Security recommendations for keys and key files). For this purpose, the generated key can be exported from the Signature Server via the USB interface. While the USB command interface is unlocked, the Signature Server administration tool can be used to export the key, for example:
The tool will ask for a password to protect the private signature key file with (choose a strong password here) and for the password of the Administrator’s private authentication key file.
If the export was successful, the tool confirms the operation.
Protecting a private signing key from being exported
Regardless of how a private signing key was generated, it can be exported from the Signature Server by Administrators later, for example for backup purposes. If this is not desired, this behavior can be changed: A key can be prevented from ever being exported again by setting its “no-export” attribute.
Warning
Setting the “no-export” attribute on a key is final and cannot be undone.
Only set this attribute on keys that are already backed up. Once the “no-export” attribute has been set, there is no way to ever export the key again from the Signature Server.
The “no-export” attribute of a private signing key can be set through the Signature Server administration tool while the Signature Server is connected via USB and the USB command interface is unlocked. For example:
The tool will ask for the password of the Administrator’s private authentication key file.
If the command was executed successfully, the tool confirms the operation.
Setting up a Release Manager user
A Release Manager user can use the Signature Server to generate signatures and is authenticated with a personal signing password. Refer to the sections Release Manager role and Signing password for more information.
A Release Manager user is set up by an Administrator through the Signature Server administration tool while the Signature Server is connected via USB and the USB command interface is unlocked. For example:
The tool will ask for the password of the Administrator’s private authentication key file and for the new password to be set for the Release Manager. Choose a strong password here.
If the command was executed successfully, the tool confirms the operation.
Granting access to a signing key
The Release Managers need to be granted permission to use a signing key for signature generation when creating update packages. For each signing key, the Release Managers who are authorized to use it for signing are configured individually. The Administrator uses the Signature Server administration tool to grant permission to one or more Release Managers at a time. For example:
The tool will ask for the password of the Administrator’s private authentication key file and confirm the successful execution of the command.
This step completes the initialization of the Signature Server. The Ready LED should now light up green (see Status LEDs), and the Signature Server is ready to generate signatures, as described in section Creating firmware for the target.
Installing updates
Update packages may be provided by SEGGER Microcontroller to enhance the functionality of the Signature Server. In order to install an update on the Signature Server, the update package is uploaded using the Signature Server administration tool by Device Owners or Administrators. The update is installed when the Signature Server is rebooted. See Uploading firmware updates for more information about the command which is used to upload updates. The Signature Server administration tool can be used to check the version number of the application firmware and the bootloader to verify that the update was installed as expected, see Checking the status of a Signature Server.
The key store, which contains both the signing keys and user authentication data, is unaffected by updates. However, maintaining a backup copy of signing keys is recommended in any case.
Creating firmware for the target
This chapter describes how application firmware can be prepared for flashing into the target during manufacturing, and how both application firmware and bootloader update packages are created.
It is assumed that a functioning bootloader has been implemented as described in the previous sections, and that at least a “Hello, world” application firmware has been adapted to be startable by a bootloader.
Creating initial firmware for manufacturing
During manufacturing, both the bootloader and a signed application firmware image have to be programmed into the target’s flash memory. Since the bootloader and the application firmware are in different regions of flash memory, they can either be programmed one after the other, or the two files containing them have to be combined into a single file. For simplicity, a two step process is assumed here.
The bootloader can be flashed into the target unchanged. The application firmware image has to be signed, otherwise the bootloader will not start it.
Alternative 1: Using a signing key file
The following command uses a private signing key stored in a local file to create an update package:
This command assumes that both the application.elf and BOOT_Conf.h files are in the current working directory, while the emBoot-Secure include directory, which contains the BOOT_ConfDefaults.h, is available under the relative path ../Inc. The version number of the update package is set to 10 (see Version numbers).
asks for the password for the key stored in KeyFile1.prv,
reads the application firmware image from application.elf and signs it,
and writes the signed application firmware image to application_signed_V10.srec.
Alternative 2: Using the Signature Server
In order to sign an application firmware image with the Signature Server, the device must have been initialized as described in section Initialization of the Signature Server.
A Release Manager user can then connect to the Signature Server via Ethernet or USB (with the USB command interface unlocked, see Connecting to the USB interface) and use the firmware preparation tool to request a signature for a given application firmware image, for example:
This command assumes that both the application.elf and BOOT_Conf.h files are in the current working directory, while the emBoot-Secure include directory, which contains the BOOT_ConfDefaults.h, is available under the relative path ../Inc. The version number of the update package is set to 10 (see Version numbers).
With this command, the firmware preparation tool:
asks for the password of a Release Manager with permissions to use SignKey1,
connects to a Signature Server via USB,
requests a signature from the Signature Server for the application firmware image application.elf,
receives the signature in response,
combines both and writes the signed application firmware image to application_signed_V10.srec.
The signed application application_signed_V10.srec together with the bootloader firmware image can then be flashed into the target devices.
Creating a firmware update
The following command uses a private signing key stored in a local file to create a signed and encrypted update package:
This command assumes that required files application.elf, BOOT_Conf.h, EncKeyFile1.prv and EncFile1.sec are in the current working directory. The emBoot-Secure include directory, which contains the BOOT_ConfDefaults.h, must be available under the relative path ../Inc. The version number of the update package is set to 11 (see Version numbers).
With this command, the firmware preparation tool:
asks for the password for the encryption key stored in EncKeyFile1.sec,
asks for the password for the private signing key stored in KeyFile1.prv,
reads the application firmware image from application.elf and signs it,
compresses the application firmware image, if compression is enabled in BOOT_Conf.h,
encrypts the compressed data using the encryption key stored in EncKeyFile1.sec,
and writes the completed update package to Application_Update_V11.upd.
If a signing key stored in a Signature Server should be used for signing instead of a local file, the -k parameter is adjusted as in the example from the previous section:
-k sigs:SignKey1@usb:
The resulting update file Application_Update_V11.upd can then be distributed to the target devices.
Creating a bootloader update
The process of creating a bootloader update package is very similar to that for producing an application update package. The main difference is the specification of the --btl parameter to inform the firmware preparation tool that a bootloader is packaged instead of an application. The firmware preparation tool needs this information to verify that the size and memory layout of the bootloader is compatible with the configuration provided in BOOT_Conf.h.
This command assumes that required files bootloader.elf, BOOT_Conf.h, EncKeyFile1.prv and EncFile1.sec are in the current working directory. The emBoot-Secure include directory, which contains the BOOT_ConfDefaults.h, must be available under the relative path ../Inc. The version number of the bootloader update package is set to 2 (see Version numbers).
The tool will request the passwords for both the encryption key file and the private signing key. If a Signature Server should be used instead for signing, the -k parameter can simply adapted to:
-k sigs:SignKey1@usb:
The resulting update file Bootloader_Update_V2.upd can then be distributed to the target devices.
emBoot-Secure configuration switches
This chapter documents all compile time options for emBoot.
All compile-time switches and their default values
can be found in the file BOOT_ConfDefaults.h.
To change the default configuration of emBoot-Secure customized values for compile-time switches
can be added to BOOT_Conf.h. The file BOOT_ConfDefaults.h should not be changed
for easy updates of emBoot.
Configuration switches for firmware update behavior
SBTL_NUM_AREAS_UPDATE
Description
Defines the number of areas which can contain update packages.
The maximum number of update package areas is 16.
Definition
#defineSBTL_NUM_AREAS_UPDATE 1
SBTL_NUM_AREAS_FAILSAFE
Description
Defines the number of areas which contain failsafe firmware
images.
The maximum number of failsafe areas is 16.
Definition
#defineSBTL_NUM_AREAS_FAILSAFE 0
SBTL_FIRMWARE_ALLOW_DOWNGRADE
Description
Defines whether downgrades, i.e. installation of firmware
with a version number lower than the installed firmware, are
allowed.
Definition
#defineSBTL_FIRMWARE_ALLOW_DOWNGRADE 0
SBTL_BOOTLOADER_UPDATE_MODE
Description
Defines the bootloader updated mode, if any.
SBTL_BOOTLOADER_UPDATE_MODE_NONE:
No bootloader updates allowed.
SBTL_BOOTLOADER_UPDATE_MODE_NORMAL:
Normal bootloader updates: Bootloader update is loaded into RAM
and replaces the currently installed bootloader.
SBTL_BOOTLOADER_UPDATE_MODE_BANKSWAP:
Bank swap mode: For controllers with two flash banks.
The bootloader in the first bank is responsible for starting the
application and installing updates. When it needs to update
itself, it updates the bootloader in the second bank.
On success, it swaps banks and the bootloader in the second
bank is started. It updates the bootloader in the first bank
and reverts the bank swap, relinquishing control back
to the bootloader in the first bank.
In case the update fails due to power loss, one of the two
bootloaders is still available to continue the update process.
Defines whether downgrades, i.e. installation of a bootloader
with a version number lower than the installed bootloader, are
allowed.
Definition
#defineSBTL_BOOTLOADER_ALLOW_DOWNGRADE 0
SBTL_FW_VERSION_SYMBOL
Description
Name of the symbol in the firmware, where the version number is
stored. The symbol must have an address inside read-only data of the
firmware. The version number must be stored as U32 in little endian.
If set, the FirmwareTool can automatically retrieve the version
from a firmware image in ELF format.
Definition
#defineSBTL_FW_VERSION_SYMBOL ""
SBTL_BTL_VERSION_SYMBOL
Description
Name of the symbol in the bootloader, where the version number is
stored. The symbol must have an address inside read-only data of the
bootloader. The version number must be stored as U32 in little endian.
If set, the FirmwareTool can automatically retrieve the version
from a bootloader image in ELF format.
Definition
#defineSBTL_BTL_VERSION_SYMBOL ""
SBTL_FIRMWARE_FILL_BYTE
Description
Gaps in the firmware image will be filled with this value by the
FirmwareTool when wrapping / signing an image.
Definition
#defineSBTL_FIRMWARE_FILL_BYTE 0x00
Configuration switches for flash memory layout
The flash memory layout needs to be communicated to emBoot-Secure using configuration flags. For information about how to apply those to sample memory layouts, see Sample memory configurations.
Areas are described in terms of start addresses, sector sizes and sector counts. Each area can be composed of up to 10 separate regions with different sector sizes and counts, if needed. The configuration flags listed below describe the first region in an area (region 0). To configure regions 1 through 9, the numbers need to be appended to the configuration flags, for example, for region 7, the flag SBTL_FIRMWARE_START_ADDR is named SBTL_FIRMWARE_START_ADDR7.
Three areas can be described using configuration switches:
Application firmware image area
This area contains the active application firmware image. The bootloader erases this area and subsequently writes to it when it installs update packages. The respective configuration flags are:
Flag name
Description
SBTL_FIRMWARE_START_ADDR
Start address of the first firmware image region.
SBTL_FIRMWARE_SECTOR_SIZE
Size of sectors in the first firmware image region.
SBTL_FIRMWARE_SECTOR_COUNT
Number of sectors in the first firmware image region.
Bootloader target image area
For bootloader updates in normal update mode, the following configuration flags describe the part of flash memory containing the active bootloader. If bank swap update mode is enabled, this area represents the “shadow bootloader”, see Bootloader update in bank swap mode for details. In both cases, a bootloader update is written into this region:
Flag name
Description
SBTL_BOOTLOADER_TARGET_START_ADDR
Start address of the first bootloader target image region.
SBTL_BOOTLOADER_TARGET_SECTOR_SIZE
Size of sectors in the first bootloader target image region.
SBTL_BOOTLOADER_TARGET_SECTOR_COUNT
Number of sectors in the first bootloader target image region.
Bootloader source image area
This area is only of relevance when bootloader updates in bank swap mode are active. In this case, this area describes the part of flash memory containing the active bootloader, which is copied to the target area during the second step of the update process.
Flag name
Description
SBTL_BOOTLOADER_SOURCE_START_ADDR
Start address of the first bootloader source image region.
SBTL_BOOTLOADER_SOURCE_SECTOR_SIZE
Size of sectors in the first bootloader source image region.
SBTL_BOOTLOADER_SOURCE_SECTOR_COUNT
Number of sectors in the first bootloader source image region.
Configuration switches related to algorithms
These configuration switches control which signature algorithm, hashing function, encryption and compression is used. They can be enabled by setting them to one in the file BOOT_Conf.h. Example:
#defineSBTL_ALGO_SIGN_RSA_WITH_SHA512 1
At least one signature algorithm/hash pair has to be activated. Compression and encryption can be optionally enabled. Enabling the flags for compression and encryption only enable the bootloader to process compressed and encrypted update packages, they do not enforce that compression and encryption are actually used in update packages. If several algorithms are activated at the same time, the bootloader will be able to process update packages packaged using any of them. This is especially useful for the compression techniques. If application firmware evolves over time, another compression algorithm may provide better compression than when the project was released. Therefore, if enough code and RAM space are available for the bootloader, both compression methods should be activated to be future proof.
Activating several signature/hashing or compression algorithms at the same
time increases code size, since several implementations have to be included
in the final binary. The size of static RAM structures used by these algorithms
will be the size be determined by the algorithm of each category with the highest RAM requirements.
Static RAM reservations are shared by the algorithms, since they will not be
running at the same time. See Resource use and performance for more information.
Switch
Explanation
Signature and hashing algorithms
SBTL_ALGO_SIGN_RSA_WITH_SHA256
RSA signature with SHA256 hash
SBTL_ALGO_SIGN_RSA_WITH_SHA512
RSA signature with SHA512 hash
SBTL_ALGO_SIGN_RSA_WITH_SHA1
RSA signature with SHA1 hash
SBTL_ALGO_SIGN_ECDSA_WITH_SHA256
ECDSA signature with SHA256 hash
SBTL_ALGO_SIGN_ECDSA_WITH_SHA384
ECDSA signature with SHA384 hash
SBTL_ALGO_SIGN_ECDSA_WITH_SHA512
ECDSA signature with SHA512 hash
SBTL_ALGO_SIGN_ECDSA_WITH_SHA1
ECDSA signature with SHA1 hash
Compression algorithms
SBTL_ALGO_COMP_SMASH2
Use SEGGER’s SMASH-2 compression algorithm.
SBTL_ALGO_COMP_SMASH2_T2
Use SEGGER’s SMASH-2 compression algorithm for better compression of ARM Thumb-2 instructions.
Encryption
SBTL_ALGO_ENC_AES_GCM
Use AES in Galois/Counter Mode (AES-GCM).
SBTL_RSA_MAX_KEY_LENGTH
Description
Defines the maximum supported RSA key length in bits.
Should be set no larger than the largest RSA key used,
since it is used to reserve static memory.
Definition
#defineSBTL_RSA_MAX_KEY_LENGTH 4096
SBTL_ECDSA_MAX_KEY_LENGTH
Description
Defines the maximum supported ECDSA key length in bits.
Should be set no larger than the largest ECDSA key used,
since it is used to reserve static memory.
Definition
#defineSBTL_ECDSA_MAX_KEY_LENGTH 521
SBTL_COMP_SMASH_MAX_WINDOW_SIZE
Description
Configures the maximum window size which can be handled when
decompressing SMASH-2 compressed images.
During decompression, a static RAM region with the same size
as the compression window has to be used for housekeeping.
Actual window size in bytes is 256 * 2^SBTL_COMP_SMASH_MAX_WINDOW_SIZE.
Valid values are from 0 (= 256 byte window size) up to 6 (= 16KB window size).
Default is 4 (= 4KB window size).
Definition
#defineSBTL_COMP_SMASH_MAX_WINDOW_SIZE 4
Miscellaneous configuration switches
SBTL_FW_VERSION_SYMBOL
Description
Name of the symbol in the firmware, where the version number is
stored. The symbol must have an address inside read-only data of the
firmware. The version number must be stored as U32 in little endian.
If set, the FirmwareTool can automatically retrieve the version
from a firmware image in ELF format.
Definition
#defineSBTL_FW_VERSION_SYMBOL ""
SBTL_BTL_VERSION_SYMBOL
Description
Name of the symbol in the bootloader, where the version number is
stored. The symbol must have an address inside read-only data of the
bootloader. The version number must be stored as U32 in little endian.
If set, the FirmwareTool can automatically retrieve the version
from a bootloader image in ELF format.
Definition
#defineSBTL_BTL_VERSION_SYMBOL ""
SBTL_DEBUG
Description
emSecure can be configured to display debug messages and warnings
to locate an error or potential problems. This can be useful for debugging.
In a release (production) build of a target system, they are typically not required
and should be switched off.
To output the messages, emSecure uses the logging routines contained
in BOOT_ConfigIO.c which can be customized.
Definition
#defineSBTL_DEBUG 0
SBTL_LOG_BUFFER_SIZE
Description
Maximum size of a debug / warning message (in characters) that can be output.
A buffer of this size is created on the stack when a message is output.
Definition
#defineSBTL_LOG_BUFFER_SIZE 200
SBTL_FIRMWARE_HEADER_SIZE
Description
Defines the size of the firmware header.
Do not change without consultation with SEGGER Microcontroller GmbH.
If this field is changed, linker scripts will also need to be adjusted.
Update are not compatible between compilations with different header
sizes.
Definition
#defineSBTL_FIRMWARE_HEADER_SIZE 64
SBTL_ALLOW_UNSIGNED_INSTALLED_FIRMWARE
Description
During development of a bootloader and application pair, it can be
helpful to allow the bootloader to start unsigned firmware.
Setting this flag to 1 will cause the bootloader to start
unsigned firmware. Care has to be taken to disable this flag before shipping.
A good way to enable it is via the build-system, but only for debug
builds. In this way, the flag will not make it into release builds.
Definition
#defineSBTL_ALLOW_UNSIGNED_INSTALLED_FIRMWARE 0
SBTL_RAM_FUNCTION
Description
Places a function in RAM. This is needed by functions used for manipulating flash memory.
SBTL_RAM_FUNCTION needs to be placed in the line above the function. Depending on the
compiler, all functions below this macro may be placed in RAM. The macro must be placed
before each function to ensure cross-compiler compatibility.
Read information from the header of a firmware or update file.
This function does not check the validity of the data in the area.
It is intended to be used to quickly identify areas which
may contain valid firmware, for example while a bootloader
is searching for updates. This allows a complete, slow signature
verification to only be performed if the firmware in this area
is of interest for installation or launching.
Use SBTL_Verify() to verify the signature of the area.
Success. Relevant information in the two structures is identical.
≠ 0
Information in both structures does not match.
SBTL_ScanFirmware()
Description
Scans through the firmware areas provided by the user and
determines whether to install new firmware.
If no suitable firmware update is found, this function will
return information about the currently installed firmware
(pFirmwareInfo->Area = SBTL_MEM_AREA_FIRMWARE). The caller
should proceed to launch this firmware.
For more information about this function, see emBoot-Secure documentation.
SBTL_ALLOW_UNSIGNED_INSTALLED_FIRMWARE: Can be set to 1 for debugging purposes, when the developer needs to flash firmware images repeatedly during development and needs to verify the transition from the bootloader to the application. USE WITH CAUTION!
SBTL_FindRescueFirmware()
Description
Scans through the rescue firmware images for a valid image.
The scan checks the rescue firmware images starting at the lowest
index. It stops at the first valid image and fills *pFirmwareInfo
with information about that image.
Reads data from an area and verifies the area’s signature it.
In order to read data from an area with this function, reserve memory
for an SBTL_UNWRAP_CTX context. Then provide the index of the area to
SBTL_UnwrapInit() which will initialize the SBTL_UNWRAP_CTX. Then call
this function to read the data from the area and verify its signature.
After all data has been read, SBTL_CloseArea() has to be called to
close the area.
If only the signature of an area is to be verified without any need
for the data, use SBTL_Verify() instead.
Maximum number of bytes to be read. Must be ≥ SBTL_FIRMWARE_HEADER_SIZE on first call.
pData
Buffer to receive the data.
pNumBytesReceived
Number of bytes returned are stored here.
Return value
= 0
Success. Length of data read is stored in *pNumBytesReceived (may be 0). Call again for more data.
< 0
Error
> 0
End of data reached and signature verified successfully. *pNumBytesReceived contains the length of data read (may be 0).
SBTL_Verify()
Description
Verify data from area.
In order to verify an area with this function, reserve memory
for an SBTL_UNWRAP_CTX context. Then provide the index of the area to
SBTL_UnwrapInit() which will initialize the SBTL_UNWRAP_CTX. Then call
this function to verify its signature.
After the signature has been verified, SBTL_CloseArea() has
to be called to close the area.
In contrast to SBTL_Unwrap(), this function will not return any
data from the area, but merely verify its signature.
Pointer to an SBTL_FIRMWARE_INFO structure containing information about the firmware to be installed.
pWorkMemory
Pointer to a memory region large enough for an SBTL_WORK_MEMORY structure (uninitialized).
pFlashBuffer
Pointer to a memory region large enough for an SBTL_FLASH_BUFF structure (uninitialized).
Return value
= 0
Success, firmware has been updated.
≠ 0
Error, flashing the firmware failed.
SBTL_PrepareBootloaderUpdate()
Description
Prepares for a bootloader update.
Loads the bootloader image from the area indicated by pFirmwareInfo
into RAM and verifies it. On success, the caller can call
SBTL_PerformBootloaderUpdate() to write the image into flash memory.
After writing the bootloader update, this function calls
SBTL_ResetHardware() in order to start the updated
bootloader. If writing the bootloader image to flash fails,
the system will halt.
Pointer to an SBTL_FLASH_BUFF which contains the bootloader.
Return value
= 0
Bootloader loaded into RAM, caller can proceed with flashing.
≠ 0
Error while loading the bootloader into RAM.
SBTL_LoadActiveBootloaderIntoRAM()
Description
Loads the active bootloader into RAM.
This function is only needed during a bootloader update in
bank swap mode, after the bootloader on bank 1 has updated the
shadow bootloader on bank 2 and activated it. This function then
loads the updated shadow bootloader from bank 2 into RAM, such that
it can be used to update the bootloader in bank 1.
Product ID the firmware / update package belongs to.
Version
Version number of the firmware / update package.
Area
Area where the firmware / update package is stored. See SBTL_MEM_AREA_… macros.
IsBootLoaderUpdate
Value 1 if the package is a bootloader update, 0 otherwise.
EntryPoint.Addr
Address of firmware entry point
EntryPoint.Jump()
Function pointer for jumping to firmware entry point.
Functions to be provided by the application
SBTL_GetBootloaderVersion()
Description
Returns the version number of the currently installed bootloader.
This function only has to be implemented if the bootloader is
configured to update itself (see SBTL_BOOTLOADER_UPDATE_MODE).
If the version number which is returned here is stored in a
const static variable, the firmware preparation tool can read
it from the resulting ELF file. See SBTL_BTL_VERSION_SYMBOL
for more information.
Version number of the currently installed bootloader.
SBTL_ReadArea()
Description
Reads data from a firmware area.
Constraints:
Only one area will be read at a time. After an area has been read, SBTL_CloseArea() will be called, even if the initial reading from the area failed.
Reading of an area will be sequential and starts at offset zero.
This function may return fewer bytes than requested, even if more data is available in the area. In that case, the caller will adjust the offset accordingly and request the remaining data until either all required data has been read or the end of the area is reached (signaled by a return value of 0).
Index of the requested key. Can be ignored, if the bootloader only contains a single AES key.
pKeySize
Returns the size of the key in bytes.
Return value
Pointer to the AES key.
SBTL_WriteFlash()
Description
Writes firmware/bootloader data to the internal flash.
The caller must ensure that FlashAddr and Size match the boundary
conditions of the flash memory regarding sector size and alignment.
This function must take care of the erasure of flash memory, depending
on the flash geometry. For example, if the flash can be erased at a sector
level, it has to erase each sector as it is written. If a number of sectors
have to be erased simultaneously due to hardware constraints, the function
has to perform erasure when the FlashAddr points to the beginning of the
first sector.
This function is also responsible for preparing the microcontroller for
flash programming. It is strongly advised to disable interrupts during
the writing process unless otherwise noted in the microcontroller’s
documentation. Other requirements may included adjustment of clock
core/bus clock frequencies and supply voltages.
Note that this function may need to be placed in RAM because it runs
while flash memory writing/erasing functions are executed.
Be sure not to call any functions which reside in flash while
the flash memory is being programmed!
If bootloader flashing in normal mode is enabled, this function
must be placed in RAM.
Error codes can either be chosen from the list of SBTL_ERR_… codes
or custom codes can be used for flash-algorithm specific errors.
Performs user configurable configuration for the cryptographic component.
The function SBTL_Init() initializes the cryptographic component
emCrypt, which in turn calls this function during
initialization.
The modular exponentiation function to be used for
public key processing has to be configured here. Since the
public keys are rather small, a reasonably fast function with
low memory requirements is CRYPTO_MPI_ModExp_Basic_Fast.
The CRYPTO_MPI_ModExp_Basic_Fast can be enabled like this:
In the emBoot-Secure library, update packages and installed firmware images are organized into areas, which are addressed via indices. This section explains the utility macros which can be used to represent and check region numbers both in callback functions and data returned from library functions.
SBTL_MEM_AREA_FIRMWARE
This index represents the currently installed application firmware image. When information from this area is requested from the callback function SBTL_ReadArea(), it can simply be copied from the flash region into the RAM buffer supplied by the caller. The SBTL_ScanFirmware() function will populate the supplied SBTL_FIRMWARE_INFO structure with information about this region when the currently installed application firmware image is to be launched by the bootloader.
SBTL_MEM_AREA_UPDATE(n)
Returns the area index for the n-th area which may contain update packages for either the application firmware or the bootloader. In the SBTL_ReadArea() function, it can be used to match the index supplied by the caller against the manufacturer defined update package storage locations. There can be up to 16 areas containing update packages.
SBTL_MEM_AREA_FAILSAFE(n)
Returns the area index for the n-th area which may failsafe application update packages. In the SBTL_ReadArea() function, it can be used to match the index supplied by the caller against the manufacturer defined update package storage locations. There can be up to 16 areas containing failsafe update packages.
SBTL_MEM_AREA_IS_UPDATE(x)
Returns 1 if the index points to an area containing an update package, otherwise 0.
SBTL_MEM_AREA_IS_FAILSAFE(x)
Returns 1 if the index points to an area containing a failsafe update package, otherwise 0.
The key generation tool
The KeyTool can be used to generate and convert cryptographic keys needed by emBoot.
Key generation tool invocation
KeyTool.exe/KeyTool is a command line tool for PC (Windows / Linux).
General command line syntax:
KeyTool<operation><options>…
The supported <operation>s are explained in the following sections.
General options
--version
Print the version of the key generation tool and the underlying emCrypt library.
Private and secret keys may be stored password encrypted in files. To access such a file a password must be provided.
By default, the key generation tool prompts for every password required and reads the password from the console.
To use the key generation tool in batch scripts, passwords may be provided in other ways using the --pass option.
<pwd-opt>
pass:<password>
The actual password is <password>, given on the command line.
Note that the command line is visible to other processes and users,
for example the ps utility on Linux.
<password>
The actual password is <password>, given on the command line.
Note that the command line is visible to other processes and users,
for example the ps utility on Linux.
console
Prompt user to enter password on the console.
file:<file>
Read the password from the file <file>.
Only the first line of the file (until the first
newline character) is used as the password.
env:<var>
Obtain the password from the environment variable <var>.
Note that environment variables may be visible to other processes and users.
Generating an ECDSA key pair (KeyTool)
The following command generates an ECDSA key pair and writes it into files. A file for the private key another one for the
public key are created. The private key file can be encrypted with a password.
Either the name of the elliptic curve to be used can be specified or the key size in bits. If the key size is
specified, Brainpool curves are used by default. To use curves provided by NIST, the --NIST parameter has
to be specified.
Bit size of the ECDSA key to be generated. This option determines the elliptic curve which is used.
Possible values are 256, 320, 384, 512 or 521. Default is 256.
--curve<name>
Specify the elliptic curve to be used by name.
--out<path>
Pathname of the key files to be created. For the private key file .prv will be appended
to the pathname and .pub for the public key file. The default file names are emBootSecureKey.prv
and emBootSecureKey.pub.
-p
Shorthand for <--pass console>, i.e., encrypt the private key file with a password that is read from the console.
--pass<pwd-opt>
Encrypt the private key file with a password provided as described under Providing passwords.
The following command generates an RSA key pair and writes it into files. One file for the private key another one for the
public key are created. The private key file can be encrypted with a password.
Bit size of the RSA key to be generated. Supported values are 2048, 3072, 4096, 6144 or 8192.
Default is 3072.
--out<path>
Pathname of the key files to be created. For the private key file .prv will be appended
to the pathname and .pub for the public key file. The default file names are emBootSecureKey.prv
and emBootSecureKey.pub.
-p
Shorthand for <--pass console>, i.e., encrypt the private key file with a password that is read from the console.
--pass<pwd-opt>
Encrypt the private key file with a password provided as described under Providing passwords.
Note
RSA keys with large sizes may take a long time to generate.
Bit size of the AES key to be generated.
Possible values are 128, 192 or 256. Default is 128.
--out<path>
Pathname of the key file to be created. The extension .sec will be appended
to the file name. The default file name is emBootSecureKey.sec.
-p
Shorthand for <--pass console>, i.e., encrypt the key file with a password that is read from the console.
--pass<pwd-opt>
Encrypt the key file with a password provided as described under Providing passwords.
Converting an RSA key to C
The following command reads a public RSA key from either a public or private RSA key file and converts it into a C file,
that can be compiled into the bootloader project. The resulting C file will contain the definition of the SBTL_GetRSAPublicKey() function, which is used by the emBoot-Secure library to obtain public keys.
If a bootloader needs to be able to work with several public keys for verification of signatures, they have to be merged into a single C file by specifying them to a single invocation of the key generation tool. The order of the keys is important, because the keys are retrieved from the resulting SBTL_GetRSAPublicKey() function using an index, which is based on the order in which the keys are provided to the key generation tool. When an update package is signed using the firmware preparation tool, that index has to be provided such that it can be recorded inside the update package. Keys must not be reordered, because otherwise, there will be a key index mismatch between the bootloader and the update package, preventing signature validation.
Input file that contains either a public or private RSA key.
Multiple key files can be specified. All Keys will be output to a single C file.
If any encrypted private key file is given, a password is required. See Providing passwords.
--out<path>
Pathname of the C file to be created.
If <path> does not already have a file extension, then .c will be appended.
If this option is not specified, the C code is send to stdout.
Converting an ECDSA key to C
The following command reads a public ECDSA from either a public or private ECDSA key file and converts it into a C file,
that can be compiled into the bootloader project. The resulting C file will contain the definition of the SBTL_GetECPublicKey() function, which is used by the emBoot-Secure library to obtain public keys.
If a bootloader needs to be able to work with several public keys for verification of signatures, they have to be merged into a single C file by specifying them to a single invocation of the key generation tool. The order of the keys is important, because the keys are retrieved from the resulting SBTL_GetECPublicKey() function using an index, which is based on the order in which the keys are provided to the key generation tool. When an update package is signed using the firmware preparation tool, that index has to be provided such that it can be recorded inside the update package. Keys must not be reordered, because otherwise, there will be a key index mismatch between the bootloader and the update package, preventing signature validation.
Input file that contains either a public or private ECDSA key.
Multiple key files can be specified. All Keys will be output to a single C file.
If any encrypted private key file is given, a password is required. See Providing passwords.
--out<path>
Pathname of the C file to be created.
If <path> does not already have a file extension, then .c will be appended.
If this option is not specified, the C code is send to stdout.
Converting an AES key to C
The following command reads an AES key from a key file and converts it into a C file,
that can be compiled into the bootloader project. Note that the C file will contain the AES key in plain text. The C file will contain a definition of the SBTL_GetAESKey() function, which is called by the emBoot-Secure library when the AES key is needed for decrypting an update package.
If a bootloader needs to be able to work with several encryption keys, they have to be merged into a single C file by specifying them to a single invocation of the key generation tool. The order of the keys is important, because the keys are retrieved from the resulting SBTL_GetAESKey() function using an index, which is based on the order in which the keys are provided to the key generation tool. When an update package is encrypted using the firmware preparation tool, that index has to be provided such that it can be recorded inside the update package. Keys must not be reordered, because otherwise, there will be a key index mismatch between the bootloader and the update package, preventing decryption of the update package.
Input file that contains the AES key.
Multiple key files can be specified. All Keys will be output to a single C file.
If any encrypted key file is given, a password is required. See Providing passwords.
--out<path>
Pathname of the C file to be created.
If <path> does not already have a file extension, then .c will be appended.
If this option is not specified, the C code is sent to stdout.
--pass<pwd-opt>
Password for decryption of the AES key, provided as described under Providing passwords.
Changing the passwords of private key files
The key generation tool can read a private key from a file and save it to another file with either a changed password or in unencrypted form using the change-password operation. If no --pass/--newpass arguments are specified, the respective passwords are read from the terminal, unless the --unencrypted parameter is supplied, which will cause the key to be written to the new file without encryption.
Input file that contains the AES key.
Multiple key files can be specified. All Keys will be output to a single C file.
If any encrypted key file is given, a password is required. See Providing passwords.
--out<key-out-file>
Pathname of the C file to be created.
If <path> does not already have a file extension, then .c will be appended.
If this option is not specified, the C code is sent to stdout.
--pass<pwd-opt>
Password for decryption of the key in the input file, provided as described under Providing passwords.
--newpass<pwd-opt>
Password for encryption of the key in the output file, provided as described under Providing passwords.
--unencrypted
Store the key without encryption in the output file.
The firmware preparation tool
The firmware preparation tool (FirmwareTool) is used to process firmware images and turn them into update packages for distribution or signed firmware images for initial flashing.
The process of creating an update package from a firmware image is called “wrapping”, reflecting the separate layers of the update package (signing, compression, encryption). The resulting binary files are suitable for distribution to devices in the field.
During device manufacturing, both the bootloader and a signed application firmware image have to be flashed into the target device. Since the bootloader will only launch signed firmware, a signature has to be added to the initial application firmware as well. It is rendered into a Motorola S-Record file which can be processed as usual by the firmware flashing utilities.
Supported file formats
Usual file extension
File input
File output
Description
.srec
✅
✅
Motorola S-Record format
.hex
✅
Intel HEX file format
.elf
✅
Executable and Linking Format (ELF)
.bin
✅
Binary files
.upd
✅
SEGGER wrapped / signed firmware format (Update package)
Motorola S-Record file format
S-Record files produced by linkers store firmware code and data in hexadecimal format along with their designated addresses on the target hardware. They also contain the address of the firmware entry point (usually the reset handler or the main() function). The FirmwareTool can read these files to create either update packages or signed firmware images.
Signed firmware images are written to S-Record files, in order to be consumed by firmware flashing tools.
Intel HEX file format
HEX files are similar to S-Record files and also contain code and data in hexadecimal format. The FirmwareTool can only read this file format.
ELF file format
The ELF file format contains code and data in binary form, along with some symbol names. The FirmwareTool extracts the relevant parts and deduces both the firmware entry point address as well as the base address of the firmware. The FirmwareTool can only read this file format.
Binary files
Binary files contain the raw code and data of the firmware. Since there is no metadata, the application entry point and the base address of the firmware in the file have to be provided using the --entry-point and --binary-fw-base-addr arguments, respectively.
SEGGER wrapped / signed firmware files
These files are produced by the FirmwareTool during the firmware wrapping process.
Input file format detection
The FirmwareTool automatically detects the format of the input file, independent of the file extension, except for binary files.
In order to process a binary file, the command line option --binary-fw-base-addr must be specified.
Firmware preparation tool option reference
FirmwareTool.exe/FirmwareTool is a command line tool for PC (Windows / Linux).
General command line syntax:
FirmwareTool<operation><options>…
The supported <operation>s are explained in the following sections.
General options
--version
Print the version of the key generation tool and the underlying emCrypt library.
Path name of the BOOT_Conf.h file used to configure the bootloader
-I<incpath>
Path to an include directory containing files included by BOOT_Conf.h.
The file BOOT_ConfDefaults.h must be available via this path.
-D<macro>
Allows the definition of a preprocessor macro used for processing of the configuration file.
--pass<pwd-opt>
Provide a password for a signature key. See Providing passwords for details.
Specifying version numbers
As described in the section Version numbers, version numbers are represented by 32 bit unsigned integers in emBoot-Secure. When an update package or signed firmware image is created, the firmware preparation tool needs to know the version number of the application firmware or bootloader it is processing. The version number can either be specified as a command line parameter or be read out from an ELF file.
Specifying the version number as a command line parameter
The version number can be specified as decimal number, hexadecimal number (prefixed with 0x) or in dot notation with up to four components (major, minor, patch, etc.), like “1.23.5”. Each component specified in dot notation is mappend to a byte in the 32 bit version number, starting with the highest byte. For example, the version number specification
-v3.12.5.127
is equivalent to specifying:
-v0x30C057F
Reading the version number from an ELF file
If the application firmware or bootloader is read from an ELF file, the firmware preparation tool can be configured to read the version number from a symbol in the ELF file. The configuration flags SBTL_FW_VERSION_SYMBOL can be set to the name of a symbol in the application firmware image which holds the version number:
In this case, the firmware preparation tool will search for a symbol with the name ApplicationVersion, which can be defined in the application firmware code like this:
constU32 ApplicationVersion =101;
Depending on the linker optimization settings, the symbol may be removed if it is not referenced in the application. If that happens, either the symbol needs to be referenced in application code, or placed in a linker section which is marked for the linker to keep even without being referenced.
The equivalent flag for specifying the name of the symbol holding the bootloader version is SBTL_BTL_VERSION_SYMBOL.
Specifying base address and entry point
When processing firmware images in binary format, the firmware base address and the entrypoint have to be specified manually. When reading SREC, HEX or ELF files, the firmware preparation tool determines these values automatically.
The firmware base address specifies the address at which the firmware image starts relative to the flash region reserved for it. The firmware preparation tool verifies that it does not overlap with the header which needs to be in front of the firmware image, and provides for padding in case there is a gap between the header and the start of the firmware image.
--binary-fw-base-addr<addr>
The firmware preparation tool also has to be informed about the address of the entry point, which is usually the reset handler, as follows:
--entry-point<address>
Specifying key indices
The bootloader can be provided with multiple public signing keys to verify signatures of update packages, as well as multiple keys which can be used for update package encryption. During the conversion of the keys to C files using the key generation tool, they are assigned an 0-based index. The firmware preparation tool needs to record this index in the update package for the bootloader to know which key it has to use for decryption/signature validation.
The index of the signing key is provided using this option:
--sign-key-index<index>
The index of the encryption key is provided using this option:
--enc-key-index<index>
Specifying algorithms
The bootloader can be configured to provide update package decryption, decompression and validation using several algorithms by setting the appropriate flags in the file BOOT_Conf.h, see section Configuration switches related to algorithms. When multiple algorithms for the same operation (encryption, compression or signing) are enabled, an algorithm has to be specified during update package creation.
The signature algorithm can be specified using the following option, with <algo> being one of: rsa+sha256, rsa+sha512, rsa+sha1, ecdsa+sha256, ecdsa+sha384, ecdsa+sha512 or ecdsa+sha1.
--signature-algo<algo>
The compression algorithm can be specified using the following option, with <algo> being one of: smash2, smash2T2 or none.
--compression-algo<algo>
The encryption algorithm can be specified using the following option, with <algo> being either aes-gcm or none.
--encryption-algo<algo>
Providing a signing method
The firmware preparation tool is designed to support both signing update packages using the Signature Server as well as using private signing keys provided via local files.
To instruct the tool to use a private signing key from a local file, the name of the file can either be provided directly or prefixed with the file: protocol identifier. The password for the key file can be provided as well, using the <pwd-opt> options discussed in section Providing passwords:
--key<file:key-file>--pass<pwd-opt>
--key<key-file>--pass<pwd-opt>
When using a Signature Server to sign the update package, the protocol and address of the server have to be specified. The format is the same as for the --server parameter as explained in section Specifying a Signature Server address. Additionally, the name of the signing key on the server has to be specified.
Assuming the Signature Server can be found on the local network via its hostname SignatureServer-12345678, and the key SignKey1 is to be used, the following parameters have to be provided, either directly or prefixed with the sigs: protocol identifier:
The Release Manager’s password is provided by the --pass parameter, using the <pwd-opt> options discussed in section Providing passwords.
Creating an update package
An application firmware image or bootloader image is wrapped into an update package using the following command, resulting in an update file in binary format:
Password to use for authentication to a Signature Server, see Providing passwords for details.
Specifying a Signature Server address
The protocol and connection details to use when connecting to a Signature Server can be specified to the Signature Server administration tool in two ways:
Using the --server<address> option.
Using the environment variable SIGSERVER_ADDRESS, by setting it to the value which would otherwise be passed to the --server option.
Specification of a port number is optional. If no port number is specified, the default value of 33030 is used.
To establish a connection to a Signature Server with a known IP address, the address can be specified as follows, with an optional port number:
--servernet:IP_address[:port]
A Signature Server can also be reached via a hostname if the local network supports this. When using DHCP for network configuration, the Signature Server provides a hostname to the DHCP server, which may provide this information to the local DNS server to make the server reachable via the hostname. Depending on the configuration of the local DNS server, a suffix or domain name may be appended to the hostname. In the simplest case, the Signature Server can be addressed by its hostname like this
--servernet:hostname[:port]
The Signature Server also announces its hostname and IP address via mDNS. On modern operating systems, these
hostnames can be resolved with the suffix .local, provided the Signature Server and the host computer
are in the same network, or broadcast messages are bridged between the two networks.
The default hostname is SignatureServer-Serialnumber.
A Signature Server can be addressed via its hostname using mDNS like this:
--servernet:hostname.local[:port]
Connections to a Signature Server via USB require that the USB interface is enabled by pressing
the push button on the Signature Server, see Ports and push button. If more than one SignatureServer is
connected to the host computer, the serial number of the target server must be specified. In case of a
single server, specification of the serial number is optional.
--serverusb:[serial_number]
Authentication for commands
The Signature Server provides two authentication methods: key-based authentication (similar to SSH’s public key authentication) and password authentication.
For administrative commands, key-based authentication is required, while for signing firmware, passwords are used.
For password-based authentication to a server, the --auth-pass<pwd-opt> parameter is used. See Providing passwords for details about how passwords can be specified with this parameter.
For key-based authentication, a public-private key pair is required, see Generating an authentication key pair for details. A private key should be stored encrypted, requiring a password for decryption during the authentication phase. The path to the private key can be specified in two ways:
Using the environment variable SIGSERVER_AUTH_KEY
Using the --auth-key<key-file> option:
By default, the password for the private authentication key will be read from the console. A different method can be chosen by using the --auth-key-pass<pwd-opt> option, following the conventions defined under Providing passwords.
--auth-key<key-file>--auth-key-pass<pwd-opt>
Checking the status of a Signature Server
The following command reports the status (see Signature Server global states), serial number, software version, bootloader version and the network configuration of the Signature Server.
No authentication is required.
Sample output for an operational server using DHCP:
Server serial number: 12345678
Server bootloader version: 1.0.1
Server software version: 1.0.0
Server state: Operational
Server IP configuration: DHCP
Server port number: 33030 (default)
Server hostname: 'SignatureServer-12345678'
Server domain name: not set
Listing users and keys
The following command lists the private keys and configured users (Device Owner, Administrators and Release Managers). No authentication is required.
The SigServerAdmin tool prints a list of the following form. The meaning of the column Accessible to depends on the context:
For keys, it lists which Administrators can manage each key and which Release Managers may use it for signing.
For users, it lists which Administrators can manage the user.
Server contains 5 items:
Name Usage Typ Att Accessible to
------------------------------------------------
Owner RSA Own Owner
Admin1 RSA Adm Admin1
RelMan1 PWD Usr Rem Admin1, RelMan1
key1 RSA Sig Admin1, RelMan1
key2 ECDSA Sig Admin1, RelMan1
The meaning of the abbreviations used in the Usage, Typ and Att columns is as follows:
Usage
RSA
RSA key
ECDSA
ECDSA key
PWD
Password based authentication
Typ
Own
Device Owner
Adm
Administrator
Usr
Release Manager
Att
Rem
Account can be used via network
noEx
Key can’t be exported
Managing Release Manager passwords
The set-password command can be used to create a Release Manager account with a password, or to change the password of an existing account.
Release Manager accounts can only be created by Device Owners and Administrators, who have to use key-based authentication. Permission to administer the Release Manager user is granted only to the Administrator who created the user. To grant permission to other Administrators, see Granting permission. The following command creates a new user with a password, which can be used for signing.
A Release Manager can change their own password using the following variant of the previous command. Note that the current password for the user needs to be specified via --auth-pass, while the new password is specified via --pass:
Current user password to use for authentication to a Signature Server, see Providing passwords for details.
Deleting users or keys
The following command deletes an entity, such as a user, a private signing key or an authentication key, from the Signature Server.
Key-based authentication is required.
The Signature Server manages permissions of both Administrators and Release Managers. When keys are generated or imported, they can only be administered by the Administrator who created them. Release Managers can also only be administered by the Administrator who created them.
Release Managers can be granted permission to use signing keys to sign firmware.
Administrators can be granted permission to administer Release Managers and keys by either the Device Owner or other Administrators.
Key-based authentication is required.
Given a key or Release Manager, referred to by <entity-name>, the following command grants permission to one or more user accounts to use or administer that entity:
Permissions to administer keys and Release Managers, or to use keys for signing, can be revoked. Administrators can revoke permissions for entities for which they have permissions, while the Device Owner can revoke permissions for any entity.
Key-based authentication is required.
Given a key or Release Manager, referred to by <entity-name>, the following command revokes permission to use or administer that entity from one or more user accounts:
Device Owner and Administrator accounts are created by importing the public part of their authentication key pair into the Signature Server. The first public authentication key which is imported defines the Device Owner.
Importing signing keys
A signing key is created by importing the private part of the signing key pair. Permission to administer the imported key is granted only to the Administrator who imported the key. To grant permission to other Administrators, see Granting permission. Release Managers also need to be granted permission to use the key for signing in the same way.
Keys can only be imported by the Device Owner and Administrators.
The private part of a signing key pair can be exported from a Signature Server, unless the key is marked as no-export.
It is recommended to specify a password for encryption of the exported private key.
Key-based authentication is required.
Export of a key from the Signature Server can be prohibited by flagging a key as “no-export”.
This can be achieved with the following command, which requires key-based authentication.
The following command verifies that a signature made with a private signing key stored in the Signature Server with name <key-name> can be verified using the public key stored in <key-file>. It can be used by Release Managers which have been granted permission to use key <key-name> using their password.
The following command generates an ECDSA key pair. The private key is stored in the Signature Server under the specified name. The “no-export” flag is not automatically set on this new key. The public key is written into a file. Key-based authentication is required.
Permission to administer the generated key is granted only to the Administrator who generated the key. To grant permission to other Administrators, see Granting permission. Release Managers also need to be granted permission to use the key for signing.
Either the name of the elliptic curve to be used can be specified or the key size in bits. If the key size is
specified, Brainpool curves are used by default. To use curves provided by NIST, the --NIST parameter has
to be specified.
Name to assign to the newly generated key, up to 16 characters long.
-s<keysize>
Bit size of the ECDSA key to be generated. This option determines the elliptic curve which is used.
Possible values are 256, 320, 384, 512 or 521. Default is 256.
The following command generates an RSA key pair. The private key is stored in the Signature Server under the specified name. The “no-export” flag is not automatically set on this new key. The public key is written into a file. Key-based authentication is required.
Permission to administer the generated key is granted only to the Administrator who generated the key. To grant permission to other Administrators, see Granting permission. Release Managers also need to be granted permission to use the key for signing.
The Signature Server’s hostname is used when it requests an IP address from a DHCP server. It also advertises itself using mDNS
using the hostname. See Specifying a Signature Server address for details about how the hostname is used.
Changes are applied after a restart of the Signature Server.
Key-based authentication is required for setting it with the following command:
The Signature Server’s domain name is used when it requests an IP address from a DHCP server.
Changes are applied after a restart of the Signature Server.
Key-based authentication is required for setting it with the following command:
The port number on which the Signature Server listens for incoming network connections
normally does not need manual changes.
Changes are applied after a restart of the Signature Server.
Key-based authentication is required for setting it with the following command:
By default, the Signature Server is configured to use DHCP for network configuration. It can also be assigned a static IP address, along with network mask and gateway. To enable DHCP, the IP address has to be set to 0.0.0.0.
Changes are applied after a restart of the Signature Server.
When configuring the Signature Server to use DHCP, the parameters --mask and --gateway must not be specified.
Key-based authentication is required to change these settings.
The update is installed during the next reboot. The update installation process must not be aborted.
Resetting to factory state
The Signature Server can be reset to factory state. This function can be used to securely erase all keys from a Signature Server. Keys are securely deleted by erasing the internal flash memory area which stores them, leaving no option of key recovery. It can also be used to regain access to a Signature Server in case administrative credentials were lost, at the cost of erasure of all keys in the server. A factory reset must be initiated via a USB connection.
To perform a factory reset, the SigServerAdmin tool has to be invoked as follows:
SigServerAdminfactory-reset--server<address>
The activity LED on the Signature Server will start flashing red, and the factory reset has to be confirmed by pressing the push button on the Signature Server for at least three seconds within 20 seconds after the command has been initiated. Once the factory reset has been performed, the Ready-LED will turn off, indicating factory delivery state, see Status LEDs.
This chapter provides estimates on the resource requirements (in terms of RAM and ROM) and the performance of the emBoot-Secure bootloader on a target system.
The most critical performance factor is the signature verification, which takes place at every boot and therefore impacts the boot time of the device. With respect to RAM usage, the peak is reached during a firmware update and depends on the parameters that emBoot-Secure is configured with. The ROM usage depends on the selected features, algorithms, and their optimization goals.
The following table shows the hardware and the toolchain details of the real-world target
system used for benchmarking.
Detail
Description
CPU
STM32H7, Cortex-M7, 400 MHz
Toolchain
Embedded Studio Release 8.26, segger-cc Version 20.1.1, ARM Thumb-2 instructions
Compiler Optimization Level
Level 2 balanced
Crypto Library
emCrypt Version 2.50.0
Runtime performance (signature verification)
The most critical operation with respect to the runtime performance of the emBoot-Secure bootloader is the verification of the signature of an application firmware image. This operation happens on every boot and whenever an update is installed. The verification is performed in two steps: First, a hash of the (decompressed, decrypted) firmware image is computed. Second, the actual verification is computed.
Signature verification, step 1: Hash computation
A significant fraction of the signature verification depends on the selected hash function. The following measurements describe the average performance of the supported hash functions, based on software implementations of the respective hash algorithms, with their optimization definitions set to SEGGER_OPT_GOAL_SPEED (see Configuring the CRYPTO library). The measurements were collected on the aforementioned Cortex-M7 MCU.
Hash function
Throughput
SHA-1
12.48 MB/s
SHA-256
8.92 MB/s
SHA-384
4.56 MB/s
SHA-512
4.56 MB/s
On this particular MCU, it would take around 0.22 seconds to hash a 2MB (uncompressed) firmware image with the SHA-256 hash function. The same image could be hashed with SHA-512 or SHA-384 in 0.44 seconds or with SHA-1 in 0.16 seconds.
After the hash of the firmware image has been computed, the signature verification has to be computed. This computation depends on the selected signature scheme.
RSA
The runtime of an RSA verification depends on the selected key length. On the aforementioned Cortex-M7 MCU, the following runtime can be expected on average.
RSA key length
Verification time
3072 bit
4.82 ms
4096 bit
7.76 ms
8192 bit
30.20 ms
ECDSA
The runtime of an ECDSA verification depends on the selected curve. On the aforementioned Cortex-M7 MCU, the following runtime can be expected on average.
ECDSA curve
Verification time
brainpoolP256r1
21.93 ms
brainpoolP320r1
32.62 ms
brainpoolP384r1
49.88 ms
brainpoolP512r1
94.20 ms
NIST P-256 (secp256r1)
19.75 ms
NIST P-384 (secp384r1)
31.68 ms
NIST P-521 (secp521r1)
61.49 ms
RAM usage
The RAM memory consumption of the bootloader is dominated by its internal data structure, SBTL_WORK_MEMORY,
which is used to perform the necessary operations (signature verification, decompression, and decryption). The size of the data structure depends
on the selected algorithms and their parameters. The data structure is defined as a static variable. This allows the amount of consumed memory
to be determined at compilation time.
Signature verification
The memory footprint of the signature verification depends on the signature scheme, the selected key size, and the selected hash function. Generally, ECDSA is more RAM-efficient than RSA, and smaller key sizes require less memory. The difference between SHA-1 (smallest hash function) and SHA-512 (largest hash function) is about 200 bytes in RAM. The following table shows the approximate RAM usage of various configurations.
Signature scheme
Key size
Hash function
RAM
Comment
ECDSA
256
SHA-1
2.3 kB
Minimal configuration
ECDSA
256
SHA-256
2.3 kB
Recommended configuration
ECDSA
256
SHA-512
2.5 kB
ECDSA
521
SHA-256
4.3 kB
ECDSA
521
SHA-512
4.5 kB
Maximal ECDSA configuration
RSA
3072
SHA-1
3.7 kB
Minimal RSA configuration
RSA
3072
SHA-256
3.7 kB
Recommended RSA configuration
RSA
3072
SHA-512
3.8 kB
RSA
4096
SHA-256
4.9 kB
RSA
4096
SHA-512
5.0 kB
RSA
8192
SHA-512
9.6 kB
Maximal configuration
Decompression (optional)
If the update package is compressed, it has to be decompressed during an update. The approximate RAM resource usage of the decompression step depends on the selected algorithm and its window size, as shown in the table below.
Compression algorithm
Window size
RAM
None
—
0.0 kB
SMASH2
1 kB
1.2 kB
SMASH2
4 kB
4.3 kB
SMASH2_T2
1 kB
1.4 kB
SMASH2_T2
4 kB
4.5 kB
Decryption (optional)
If the update package is encrypted, it has to be decrypted during an update. This step requires additional resources in RAM, which are approximated in the following table.
Encryption algorithm
RAM
None
0.0 kB
AES-GCM
0.5 kB
ROM usage
The overall ROM usage of the bootloader is composed of basic bootloader functions, MCU-specific functions, and the code and data required to run the selected algorithms for signature verification, decompression, and decryption. The following section provides an overview of the usual ROM usage of a bootloader. The sections afterwards provided more detailed information about how specialized optimizations on the cryptographic algorithms increase ROM size requirements.
ROM usage overview
The following table provides estimates for each individual component of the bootloader, which were collected on a Cortex-M7 MCU. The core bootloader logic encompasses the emBoot-Secure library, the board specific flash memory driver and the bootloader’s main() function. The size of this component changes based on the additional features which are enabled. Signature verification code ranges between 5 kB for RSA and 9 kB for ECDSA. The total bootloader size ranges between 9 and 40 kB. Additional components, like the libC provided by the compiler vendor and startup code provided by the microcontroller’s manufacturer, are not included in this estimate, since they are very project-specific. When compiling the bootloader using SEGGER’s Embedded Studio for a typical Cortex-M7 MCU, another 3 kB of ROM size are added.
Component
ROM size range
Core bootloader logic
3 - 5 kB
RSA/ECDSA signature verification
5 - 9 kB
Hash function
1 - 8 kB
Decryption
0 - 17 kB
Decompression
0 - 1 kB
Total bootloader size
9 - 40 kB
In the code sample considered, the bootloader obtains the update package from a section of flash memory. If the bootloader needs to access external flash memory, optionally with a filesystem, the size will increase accordingly.
Hash computation optimization
The additional ROM usage due to the hash function depends on the selected algorithm and the configured optimization level, which is set at compile time by the CRYPTO_OPT_GOAL_SHA* macros in the CRYPTO_Conf.h file (see Configuring the CRYPTO library). The following table shows estimates for various hash functions and optimization levels.
Hash function
CRYPTO_OPT_GOAL_SHA*
ROM
size-optimized
SHA1
SEGGER_OPT_GOAL_BALANCED (default)
0.8 kB
SHA256
SEGGER_OPT_GOAL_BALANCED (default)
1.0 kB
SHA384
SEGGER_OPT_GOAL_BALANCED (default)
2.1 kB
SHA512
SEGGER_OPT_GOAL_BALANCED (default)
2.0 kB
speed-optimized
SHA1
SEGGER_OPT_GOAL_SPEED
4.1 kB
SHA256
SEGGER_OPT_GOAL_SPEED
8.0 kB
SHA384
SEGGER_OPT_GOAL_SPEED
7.4 kB
SHA512
SEGGER_OPT_GOAL_SPEED
7.3 kB
(Note: The SHA384 hash function is also configured through the CRYPTO_OPT_GOAL_SHA512 macro.)
Optimization of decryption
If the update package is encrypted, it has to be decrypted during an update. Decryption is based on the AES algorithm in GCM mode. For both components, AES and GCM, optimization can be configured independently, which influences their respective ROM footprint. The configuration is made through definitions in the file CRYPTO_Conf.h (see Configuring the CRYPTO library).
The following table shows the approximate additional ROM usage of the decryption function depending on the value of CRYPTO_OPT_GOAL_AES.
Encryption algorithm
CRYPTO_OPT_GOAL_AES
ROM
None
—
0.0 kB
AES-GCM
SEGGER_OPT_GOAL_SIZE
4.4 kB
AES-GCM
SEGGER_OPT_GOAL_BALANCED (default)
12.3 kB
AES-GCM
SEGGER_OPT_GOAL_SPEED
16.4 kB
Support
Contacting support
Before contacting support please make sure that you are using the latest version of the emBoot-Secure package.
Also please check the chapter Configuring debugging output and run your application with enabled debug support.
If you are a registered emBoot-Secure user there are different ways to contact the emBoot-Secure support:
Please include the following information in the email or ticket:
The emBoot-Secure version.
Your emBoot-Secure license number.
If you are unsure about the above information you can also use the name of the emBoot-Secure zip file (which contains the above information).
A detailed description of the problem
The configuration files BOOT_Conf*.* and CRYPTO_Conf.h.
Any error messages.
Please also take a few moments to help us improve our services by providing a short feedback once your support case has been solved.
Where can I find the license number?
The license number is part of the shipped zip file name.
For example emBoot_BASE_V2.0.0_BOOT-01234_DD92169C_260224.zip where BOOT-01234 is the license number.
The license number is also part of every *.c- and *.h-file header. For example, if you open BOOT.h you should find the license number as with the example below:
*************************************************************************emBoot-Secure version:V2.10.0*************************************************************************----------------------------------------------------------------------Licensing informationLicensor:SEGGER Microcontroller GmbHLicensed to:Customer nameLicensed SEGGER software:emBoot-SecureLicense number:BOOT-01234License model:SSLLicensed product:-Licensed platform:Cortex-M,GCCLicensed number of seats:1----------------------------------------------------------------------Support andUpdate Agreement (SUA)SUA period:2023-05-30-2023-11-30Contact to extend SUA:sales@segger.com----------------------------------------------------------------------Purpose :emBoot-Secure library
Glossary
AES
Advanced Encryption Standard, a symmetric encryption algorithm.
Administrator
A user role in the Signature Server’s permission system. Administrators manage signing keys and Release Manager accounts.
Application, application firmware
Software which runs on the target device and provides its core functionality.
Authentication key pair
Key pair used for by an Administrator to authenticate with the SignatureServer. The public key is stored in the Signature Server and the private key is used to prove the Administrator’s identity (similar to SSH).
Bootloader
Software which is started by the microcontroller during startup. It verifies the installed application firmware and installs updates.
Device Owner
The user role in the Signature Server’s permission system with highest privileges. A Device Owner initializes, configures, and administers the Signature Server and creates Administrator accounts.
ECDSA
Elliptic Curve Digital Signature Algorithm. A digital signature algorithm based on (asymmetric) elliptic curve cryptography.
Firmware encryption key
Key used for symmetric encryption of the firmware image during update package creation, and later decryption during update installation.
Firmware image
A “raw” firmware image produced by the build system, which is neither signed, nor compressed, nor encrypted. It can further be distinguished between an application firmware image, which contains the software that delivers the target’s core functionality, and a bootloader image, which contains the bootloader code.
Firmware preparation tool
Creates a secure update package from a firmware image. This tool is included in the shipping package as FirmwareTool(.exe).
GCM
Galois/Counter Mode. A standardized way to use the AES encryption algorithm to encrypt and authenticate larger amounts of data.
Key generation tool
Software tool which generates and converts public-private key pairs for usage within the emBoot-Secure ecosystem. This tool is included in the shipping package as KeyTool(.exe).
Manufacturer
Manufacturer of the target device, i.e., the company that uses emBoot-Secure in their product(s).
Release Manager
Person who builds the firmware and is responsible for signing it. Also a user role in the Signature Server’s permission system.
RSA
An asymmetric cryptosystem, named after its inventors (Rivest, Shamir, Adleman). In emBoot-Secure, RSA is used as one possible implementation of digital signatures.
Signing password
Password used to authenticate the process of signing a firmware image with a private key.
Signature Server
Secure hardware device which can optionally be used for storage of private signing keys. Can generate signatures during update package creation without exposing private keys.
Signature Server administration tool
Software tool which allows to configure the Signature Server and manage its internal key store. This tool is included in the shipping package as SigServerAdmin(.exe).
Signing key pair
Pair of private and public key used to sign a firmware image and to verify an update package.
Shipping package
The software package that is provided by SEGGER and comprises all necessary files to create products using the emBoot-Secure bootloader, along with examples and software utilities.
SMASH
Small Microcontroller Advanced Super-High format. SEGGER’s proprietary format for compressing data.
Target device
Device on which the secure bootloader runs and starts the application software.
Update package
Signed and optionally compressed and encrypted firmware image, which can be distributed, transferred to target devices, and installed.