6.2. Creation of a Secondary Bootloader

This section describes the implementation steps for the development of a secondary bootloader application for the DA1453x/DA1458x.

6.2.1. Introduction

The secondary bootloader is used in order to provide the users with a bigger flexibility so that they can customize their product’s booting procedure. Compared to the ROM booter, the secondary bootloader may be used in order to additionally support booting multi images and therefore enable the device to support SUOTA. The secondary bootloader in general supports either booting from external SPI or I2C slave peripherals (such as external SPI Flashes or I2C EEPROMs) and/or booting from serial peripherals such as the UART peripheral.

In both cases the image will be transferred from either of the aforementioned interfaces to RAM in order to be executed. The secondary bootloader can support booting encrypted and/or signed images. For that reason, there is a reserved OTP area which is located right above the OTP CS area or the OTP Header (for DA14585/DA14586 ICs). In the case of such encrypted and/or signed images the bootloader expects the keys for decryption and/or verification to be written by the user in that area so that these can be later used while booting to decrypt and/or verify the image.

Each encrypted and or signed image carries information about which keys will decrypt and/or verify it. More specifically, a total number of 5 decryption keys and 5 verification keys are supported. When an image is copied from UART or SPI/I2C to RAM for decryption and/or verification, it should carry information about which key (out of the 5 AES keys) decrypts it and which key(out of the 5 ECC keys) verifies it. These keys can also be revoked ONLY in the case of the external memory booting and ONLY if the image is signed, which means an image may also carry information about which keys it should revoke.

An extension of the secondary bootloader based on dual images is also presented in this section. The dual image bootloader is a building block for a Software Update Over The Air (SUOTA) enabled application. Finally the secondary bootloader code structure, the steps to test it and a methodology to measure the boot time are presented.

It is recommended to read Appendix Section 6.1, which describes the boot procedures supported by the DA1453x/DA1458x ROM code.

6.2.2. Boot from UART (Either 1-wire UART or 2-wire UART):

The bootloader may boot from the UART peripheral.

  • #define UART_SUPPORTED

will enable UART booting from 2-wire UART (da145xxx_config_basic.h)

  • #define ONE_WIRE_UART_SUPPORTED

will enable UART booting from 1-wire UART (da145xxx_config_basic.h)

That means that it can support downloading an image from UART directly to RAM. Depending on the image type, the image should be provided in different formats:

For a simple binary(non-encrypted and not signed) the user should build their application code and download the bare binary through UART.

The bootloader supports booting encrypted and/or signed images from UART. A raw binary image can be encrypted and/or signed with the mkimage tool. The resulting image is an image (same as a SUOTA single image) that has an image header that carries information about the image and which keys decrypt it (if it is encrypted) and/or verify it (if it is signed).

These configuration settings are included in the da145xxx_config_basic.h.

#define AES_ENCRYPTED_IMAGE_SUPPORTED     (1)

Will make the bootloader support only encrypted images

#define SECURE_BOOT_ECC_IMAGE_SUPPORT     (1)

Will make the bootloader support only signed images

Both the above macros can be defined simultaneously. In that case the bootloader will assume that only encrypted AND signed images are downloaded through UART. These images are expected to be first encrypted and THEN signed by the mkimage tool.

6.2.3. Boot from External Memory (Either via SPI or via I2C)

The bootloader can boot from an external SPI or I2C memory, These configuration settings are included in the da145xxx_config_basic.h.

  • #define SPI_FLASH_SUPPORTED

Will enable booting from an external SPI Flash

  • #define I2C_EEPROM_SUPPORTED

will enable booting from an external I2C EEPROM

By default the secondary bootloader will support booting multi images (a pair of single images - with image headers- along with a product header created by the mkimage tool).

The images can be plainly generated by the mkimage tool without any encryption or signing or they can be encrypted and/or signed

#define AES_ENCRYPTED_IMAGE_SUPPORTED     (1)

Will make the bootloader support only encrypted images

#define SECURE_BOOT_ECC_IMAGE_SUPPORT     (1)

Will make the bootloader support only signed images

Both the above macros can be defined simultaneously. In that case the bootloader will assume that only encrypted AND signed images are downloaded through the SPI or I2C memory. These images are expected to be first encrypted and THEN signed by the mkimage tool.

The bootloader supports key revokation ONLY when booting images from an external SPI or I2C memory. For key revokation to be supported, the image has to be first successfully verified so that the we know that the image requesting a key revokation is an image that was created from a “trusted” source. That means that key revokation can only be performed by signed images.

For increased security against malicious images, the user may define the following in bootloader.h

#define INVALIDATE_BAD_IMAGES                           (1)

This will make sure that if a bad or invalid image is found in the SPI flash /I2C EEPROM after SUOTA, its image header will be invalidated/erased. This will ensure that in the next SUOTA session, this invalidated image bank will be prioritized for SUOTA instead of the other “good” image bank.

A bad image is an image that has an invalid image header, or has failed to be verified (during image verification in the case of signed images support), or after decryption the image’s CRC does not align with the CRC of its header.

Together with the new SUOTA secure features, where only one SUOTA session is allowed per boot, an attacker will not be able to brick the device by filling both image banks with a bad/malicious image.

6.2.4. OTP Key Storage

The OTP Key Storage of the secondary bootloader is an area in the OTP where the bootloader assumes that Decryption and Verification keys are stored. Currently up to 5 Decryption keys are supported and up to 5 ECC/Verification keys are supported. For all the DA453x ICs, the key storage area is right above the OTP CS area. For DA14585/DA14586 the key storage area is above the OTP Header area. The structure and addresses of the Key storage can be seen below:

6.2.4.1. The key storage is summarized below for each platform:

Table 33 Key storage

Target chip / Key

DA14531 / DA14531-01

DA14585 / DA14586

DA14535/DA14533

AES Keys and IV storage area

7F87CC8

7F8FBD0

7F82CC8

ECC keys storage area

7F87D68

7F8FC70

7F82D68

AES Revokation area

7F87EA8

7F8FDB0

7F82EA8

ECC Revokation area

7F87EBC

7F8FDD8

7F82EBC

6.2.4.2. AES IV and Keys Storage area

The table below is shown the AES IV and Keys Storage area which is the area where 5 initialization vectors and keys are supposed to be written during production so that the bootloader can later use these pairs to decrypt downloaded images.

Table 34 AES IV and Keys Storage area

Target chip / Key

DA14531 / DA14531-01

DA14585 / DA14586

DA14535/DA14533

AES Key and IV Entry 0

7F87CC8

7F8FBD0

7F82CC8

AES Key and IV Entry 1

7F87CE8

7F8FBF0

7F82CE8

AES Key and IV Entry 2

7F87D08

7F8FC10

7F82D08

AES Key and IV Entry 3

7F87D28

7F8FC30

7F82D28

AES Key and IV Entry 4

7F87D48

7F8FC50

7F82D48

6.2.4.3. AES Key and IV Entry format

Each AES and Key entry consists of an Initialization Vector and an AES key.

Table 35 AES Key and IV Entry format

AES Key

AES IV

16 bytes

16 bytes

6.2.4.4. ECC Keys storage area

This is the area where 5 ECC public keys should be written during production. These keys will later be used from the secondary bootloader to verify any incoming images.

Table 36 ECC Keys storage area

Target chip / Key

DA14531 / DA14531-01

DA14585 / DA14586

DA14535/DA14533

ECC key entry 0

7F87D68

7F8FC70

7F82D68

ECC key entry 1

7F87DA8

7F8FCB0

7F82DA8

ECC key entry 2

7F87DE8

7F8FCF0

7F82DE8

ECC key entry 3

7F87E28

7F8FD30

7F82E28

ECC key entry 4

7F87E68

7F8FD70

7F82E68

6.2.4.5. ECC key entry

Each ECC key entry consists of a 64-byte ECC public key

Table 37 ECC key entry

ECC Public Key

64 bytes

6.2.4.6. AES Revokation area

This area is written by the bootloader if signed or signed and encrypted image requests to revoke a certain AES key and IV entry. It should not be touched during production. Key revokation is only supported when booting an image from an external memory and only if the image is signed.

Table 38 AES Revokation area

Target chip / Key

DA14531 / DA14531-01

DA14585 / DA14586

DA14535/DA14533

AES Revokation Flag 0

7F87EA8

7F8FDB0

7F82EA8

AES Revokation Flag 1

7F87EAC

7F8FDB8

7F82EAC

AES Revokation Flag 2

7F87EB0

7F8FDC0

7F82EB0

AES Revokation Flag 3

7F87EB4

7F8FDC8

7F82EB4

AES Revokation Flag 4

7F87EB8

7F8FDD0

7F82EB8

6.2.4.7. ECC revokation area

This area is written by the bootloader if a signed image requests to revoke a certain ECC key. It should not be touched during production. Key revokation is only supported when booting an image from an external memory and only if the image is signed.

Table 39 ECC Revokation area

Target chip / Key

DA14531 / DA14531-01

DA14585 / DA14586

DA14535/DA14533

ECC Revokation Flag 0

7F87EBC

7F8FDD8

7F82EBC

ECC Revokation Flag 1

7F87EC0

7F8FDE0

7F82EC0

ECC Revokation Flag 2

7F87EC4

7F8FDE8

7F82EC4

ECC Revokation Flag 3

7F87EC8

7F8FDF0

7F82EC8

ECC Revokation Flag 4

7F87ECC

7F8FDF8

7F82ECC

When a key is revoked, the bootloader will not use that specific key anymore. Any downloaded images that request a revoked key to be used for their their verification and/or decryption will be considered invalid/bad and won’t be booted.

6.2.5. Application Description

6.2.5.1. File Structure

The file structure of the secondary_bootloader project is shown in Figure 82.

../_images/secondary-bootloader-file-structure.png

Figure 82 Secondary Bootloader File Structure

Initialization files and scatter-loading description files are in folder utilities/secondary_bootloader/startup:

  • bootloader_585_armclang.sct: The scatter-loading description file for DA1458x

  • bootloader_531_armclang.sct: The scatter-loading description file for DA14531-00, DA14531-01 and DA14530

  • bootloader_535_armclang.sct: The scatter-loading description file for DA14535

  • ldscript_DA14531.lds.S: The linker script file for DA14531-00, DA14531-01 and DA14530

  • ldscript_DA14535.lds.S: The linker script file for DA14535 and DA14533

  • ldscript_DA14585_586.lds.S: The linker script file for DA1458x

Application (*.c) files are in folder utilities/secondary_bootloader/src:

  • main.c: Contains the main function, the system initialization function and the main loop of the application

  • bootloader.c: Contains the functions to boot from SPI and EEPROM and the implementation of the dual image bootloader

  • uart_booter.c: Contains the functions to boot from UART

  • decrypt Contains the software implementation of the AES decryption

  • user_periph_setup Peripherals setup and initialization

  • ecc_verify.c: Contains the ECC Verify functions for secondary bootloader

  • key_storage.c: This is the Key Storage management file

  • otp_utils.c: This file contains the OTP useful functions

Application (*.h) files are in folder utilities/secondary_bootloader/includes:

  • sdk_defs.h: Contains some memory configuration settings. Also contains the SDK_SEC_BOOTLOADER_LOAD_IMAGE_SIZE_INIT_VALUE configuration macro which is described here Figure 83.

  • periph_setup.h: Contains the configuration settings for the peripherals (UART, SPI, SPI Flash) used by the secondary bootloader application.

  • bootloader.h: Contains the application configuration settings. For details see section Section 6.2.5.2.

  • da1458x_config_basic.h: Splits into da14585_config_basic.h, da14531_config_basic.h and da14535_config_basic.h and holds various configuration settings for the respective device.

  • ecc_verify.h: Header file for the ECC verification functions.

  • key_storage.h: Contains the configuration settings for the Key Storage management source file.

  • otp_utils.h: Header file for the OTP useful functions.

  • decrypt.h Contains the configuration settings for the software implementation of the AES decryption.

  • uart_booter.h: Contains configuration settings for bootting from UART

Driver (*.c) files for the peripheral interfaces are in folder sdk/platform/driver/. Detailed information about the drivers can be found in the API documentation.

  • sdk/platform/driver/spi/spi_58x.c: Driver for the SPI interface of DA1458x Soc

  • sdk/platform/driver/spi/spi_531.c: Driver for the SPI interface of DA1453x Soc

  • sdk/platform/driver/i2c/i2c.c: Driver for the I2C interface

  • sdk/platform/driver/spi_flash/spi_flash.c: Driver for an external SPI Flash memory

  • sdk/platform/driver/gpio/gpio.c: Driver for the GPIO interface

  • sdk/platform/driver/dma/dma.c: Driver for the DMA interface

6.2.5.2. Other Compilation and Configuration Settings

Some other compilation and configuration settings are included in these header files located under includes folder, Figure 82.

sdk_defs.h

The secondary bootloader application is usually copied and executed in the last RAM addresses. This is in order to have space at the beginning of RAM to copy and execute the user’s application (copy from Flash/EEPROM to RAM, or copy from UART to RAM). Configuration macro SDK_SEC_BOOTLOADER_LOAD_IMAGE_SIZE_INIT_VALUE defines the size of the available RAM space that can be used to copy and execute an image. The default value of this macro is set to 0x9500 which is about 38144 bytes. If the developers enable more features on the secondary bootloader side(thus increasing the secondary bootloader’s binary size), then they should consider decreasing the effective available RAM size (decrease the value of SDK_SEC_BOOTLOADER_LOAD_IMAGE_SIZE_INIT_VALUE).

../_images/bootloader_boot_image.svg

Figure 83 SDK_SEC_BOOTLOADER_LOAD_IMAGE_SIZE_INIT_VALUE macro

Note

For DA1453x P0_0 is used for UART_TX. At the end of firmware download hardware reset functionality on P0_0 is enabled. External application should drive P0_0 to low to avoid hardware reset of the device.

The configuration settings for the peripherals are contained in header file periph_setup.h.

// Select EEPROM characteristics
#define I2C_EEPROM_DEV_SIZE   0x20000           // EEPROM size in bytes
#define I2C_EEPROM_PAGE_SIZE   256               // EEPROM page size in bytes
#define I2C_SLAVE_ADDRESS 0x50              // Set slave device address
#define I2C_SPEED_MODE    I2C_SPEED_FAST    // Speed mode: I2C_SPEED_STANDARD (100 kbits/s), I2C_SPEED_FAST (400 kbits/s)
#define I2C_ADDRESS_MODE  I2C_ADDRESSING_7B // Addressing mode: {I2C_ADDRESSING_7B, I2C_ADDRESSING_10B}
#define I2C_ADDRESS_SIZE  I2C_2BYTES_ADDR   // Address width: {I2C_1BYTE_ADDR, I2C_2BYTES_ADDR, I2C_3BYTES_ADDR}

// SPI Flash settings
// SPI Flash Manufacturer and ID
#define W25X10CL_MANF_DEV_ID   (0xEF10)    // W25X10CL Manufacturer and ID
#define W25X20CL_MANF_DEV_ID   (0xEF11)    // W25X10CL Manufacturer and ID
#define MX25R2035F_MANF_DEV_ID (0xC212)    // MX25R2035F Manufacturer and ID

// SPI Flash options
#define W25X10CL_SIZE   131072            // SPI Flash memory size in bytes
#define W25X20CL_SIZE   262144            // SPI Flash memory size in bytes
#define MX25R2035F_SIZE 262144            // SPI Flash memory size in bytes
#define W25X10CL_PAGE   256               // SPI Flash memory page size in bytes
#define W25X20CL_PAGE   256               // SPI Flash memory page size in bytes
#define MX25R2035F_PAGE 256               // SPI Flash memory page size in bytes

#if !defined (__DA14586__)
#define SPI_FLASH_DEV_SIZE          (256 * 1024)
#endif

//SPI initialization parameters
#define SPI_WORD_MODE  SPI_8BIT_MODE
#define SPI_SMN_MODE   SPI_MASTER_MODE
#define SPI_POL_MODE   SPI_CLK_INIT_HIGH
#define SPI_PHA_MODE   SPI_PHASE_1
#define SPI_MINT_EN    SPI_NO_MINT
#if !defined (__DA14531__)
#define SPI_CLK_DIV    SPI_XTAL_DIV_2
#endif

// UART GPIOs assignment
#if defined (__DA14531__)
#define UART_GPIO_PORT       GPIO_PORT_0
#define UART_TX_PIN          GPIO_PIN_0
#define UART_RX_PIN          GPIO_PIN_1
#define UART_FRAC_BAUDRATE   UART_BAUDRATE_115200
#else
#define UART_GPIO_PORT       GPIO_PORT_0
#define UART_TX_PIN          GPIO_PIN_4
#define UART_RX_PIN          GPIO_PIN_5
#define UART_FRAC_BAUDRATE   UART_BAUDRATE_57600
#endif

// SPI GPIO assignment
/****************************************************************************************/
/* SPI configuration                                                                    */
/****************************************************************************************/
// Define SPI Pads
#if defined (__DA14531__)
#if !defined (__FPGA__)
    #define SPI_EN_PORT             GPIO_PORT_0
    #define SPI_EN_PIN              GPIO_PIN_1

    #define SPI_CLK_PORT            GPIO_PORT_0
    #define SPI_CLK_PIN             GPIO_PIN_4

    #define SPI_DO_PORT             GPIO_PORT_0
    #define SPI_DO_PIN              GPIO_PIN_0

    #define SPI_DI_PORT             GPIO_PORT_0
    #define SPI_DI_PIN              GPIO_PIN_3
#else
    #define SPI_EN_PORT             GPIO_PORT_0
    #define SPI_EN_PIN              GPIO_PIN_11

    #define SPI_CLK_PORT            GPIO_PORT_0
    #define SPI_CLK_PIN             GPIO_PIN_7

    #define SPI_DO_PORT             GPIO_PORT_0
    #define SPI_DO_PIN              GPIO_PIN_9

    #define SPI_DI_PORT             GPIO_PORT_0
    #define SPI_DI_PIN              GPIO_PIN_10
#endif

#elif !defined (__DA14586__)
    #define SPI_EN_PORT             GPIO_PORT_0
    #define SPI_EN_PIN              GPIO_PIN_3

    #define SPI_CLK_PORT            GPIO_PORT_0
    #define SPI_CLK_PIN             GPIO_PIN_0

    #define SPI_DO_PORT             GPIO_PORT_0
    #define SPI_DO_PIN              GPIO_PIN_6

    #define SPI_DI_PORT             GPIO_PORT_0
    #define SPI_DI_PIN              GPIO_PIN_5
#endif

// EEPROM GPIO assignment
// Define I2C Pads
#define I2C_SCL_PORT                GPIO_PORT_0
#define I2C_SCL_PIN                 GPIO_PIN_2

#define I2C_SDA_PORT                GPIO_PORT_0
#define I2C_SDA_PIN                 GPIO_PIN_3

W25X10CL SPI Flash memory devices are supported. The W25X10CL arrays are organized into 512 programmable pages of 256 bytes each. Up to 256 bytes can be programmed at a time. The W25X10CL has 32 erasable sectors of 4 kB, 4 erasable 32 kB blocks and 2 erasable 64 kB blocks respectively. W25X20CL SPI Flash memory devices are also supported.

Other SPI Flash memory types can be supported if the above configuration settings (SPI_FLASH_DEFAULT_SIZE, SPI_FLASH_DEFAULT_PAGE, etc.) are changed.

GPIO Port 0 is used by default as it is supported by all DA1458x (WLCSP34, QFN40 and QFN48) and DA1453x (WLCSP17 and FCGQFN24) packages.

6.2.6. System Initialization

The secondary bootloader application executes in the retention memory, and allows the application code to be loaded into the System RAM. The secondary bootloader does the following actions:

  1. In the main function, the secondary bootloader reloads the Watchdog timer with the max value and configures the Watchdog timer to trigger a HW reset upon expiration.

    SetBits(WATCHDOG_CTRL_REG, NMI_RST, 1);    // WDOG will generate HW reset upon expiration
    SetWord16(WATCHDOG_REG, 0xFF);             // Reset WDOG
    SetWord16(RESET_FREEZE_REG, FRZ_WDOG);     // Start WDOG
    
  2. Initializes the system.

    system_init();
    
  3. Boots from UART if the UART boot option is enabled and the UART RX pin is logic HIGH. Otherwise boots from SPI or I2C.

6.2.7. Getting Started

This section describes how to program the secondary bootloader into the OTP memory, program an application example (integrated processor Proximity Reporter) into the SPI Flash memory and measure the system’s boot time. A comparison with a normal booter (ROM booter in Development Mode) is also provided.

The SmartSnippets Toolbox provides tools for external SPI Flash and OTP memory programming.

6.2.7.1. Building the Application and Secondary Bootloader Images

Build the Proximity Reporter application image for DA14585 target to generate the executable file prox_reporter_585.hex.

Build the secondary bootloader image for the same target according to the following steps:

  1. Open the Secondary Bootloader project:

    • For Keil 5: \utilities\secondary_bootloader\secondary_bootloader.uvprojx.

  2. Configure the project according to section Section 6.2.5.2.

  3. Compile the project to generate the executable file secondary_bootloader_585.hex. This file is in directory <utilities\secondary_bootloader\out_DA14585\Objects.

6.2.7.2. Writing Application HEX File into SPI Flash Memory

The SmartSnippets SPI Flash Programmer tool is used to download an application image file to an external SPI Flash memory connected to DA1453x/DA1458x.

The following instructions demonstrate how to do this with SmartSnippets Toolbox in UART mode when a DA14585 device is connected.

  1. Open SmartSnippets and select the chip version.

    ../_images/secondary-bootloader-Open-SmartSnippets-and-select-the-chip-version.png

    Figure 84 Select Chip Version

  2. Open the Board Setup tool and select the appropriate UART and SPI flash pin configuration as shown in Figure 85.

    ../_images/secondary-bootloader-board-setup.png

    Figure 85 Board Setup

  3. Open the SPI Flash Programmer tool: Programmer –> Flash code, select the application image file and burn it at SPI flash memory offset 0. When asked whether to make the SPI Flash memory bootable, there are two options to consider depending on the chip version and bootloader configuration:

    • Bootable SPI Flash: SmartSnippets will automatically add an AN-B-001 header at offset 0 of the SPI flash memory. The secondary bootloader will copy only the number of bytes defined in the SPI Flash header.

    • Non-bootable SPI Flash: SmartSnippets will not add an AN-B-001 header at offset 0 of the SPI flash memory. The secondary bootloader will copy 32 KB from SPI Flash memory starting at offset 0x0. Using this setup the maximum boot time can be measured.

    ../_images/secondary-bootloader-write-SPI-flash.png

    Figure 86 SPI Flash Programmer

6.2.7.3. Writing Bootloader HEX File into OTP Memory

The SmartSnippets OTP Programmer tool enables the download of default firmware into the System RAM and to write a user-defined HEX or BIN file into the OTP memory. The tool can be used to write a secondary bootloader in the OTP memory of a DA1453x/DA1458x.

The next steps are required to write the executable secondary_bootloader_585.hex into OTP memory with SmartSnippets in UART mode:

  1. Open SmartSnippets and select the chip version as in Figure 84.

  2. Open the Board Setup tool and select the appropriate UART as in Figure 85.

  3. Open the OTP Programmer tool and select the image file to download.

    ../_images/writing-hex-in-OTP-programmer.png

    Figure 87 OTP Programmer

  4. Burn the secondary_bootloader_585.hex into the OTP memory at offset 0. Enable Application Flag 1 and Application Flag 2, set DMA Length (Length = size / 4) and burn the OTP header.

    ../_images/writing-hex-in-OTP.png

    Figure 88 OTP Programmer

Note

For more info about SmartSnippets Toolbox, see the “SmartSnippets Toolbox, User manual”.

6.2.7.4. The mkimage Tool

The mkimage tool is used to create single (SUOTA) images. It is also used to created multi images (a pair of single images with a product header appended to them that is burned in the external memory to reserve the space needed to support SUOTA)

The tool supports two use cases:

  • Single image: Create a binary application image file (*.img), that contains both the application image header and the application firmware.

  • Multi-part image: Create the entire contents of the external non-volatile memory as a single multi-part binary image file (*.img), that can be written into a non-volatile memory with the SmartSnippets Toolbox.

The source code of the mkimage tool is in folder \utilities\mkimage of the SDK.

6.2.7.4.1. Creation of an Application Image File

The command line syntax to create an application image file (*.img) is:

Single image Creation

mkimage.exe single <in_file> <version_file> <out_file> [enc [<key> <iv>]]
  • single Instructs the tool to create the <out_file> application image (*.img file).

  • <infile> Specifies the raw application firmware binary file (.BIN file).

  • <version_file> C header file that contains the version, time stamp and housekeeping information for the image header. It must be formatted similar to the SDK header file sdk\platform\include\sdk_version.h. It contains definitions such as:

#define SDK_VERSION "v_6.0.12.1020"
#define SDK_VERSION_DATE "2019-10-09 14:25 "
#define SDK_VERSION_STATUS "REPOSITORY VERSION v_6.0.12.1020"

This command can also create a single encrypted image by providing an AES key and AES IV that will be used to encrypt the image. The key and IV used here should also be burned in the OTP key storage to later be used by the secondary bootloader to successfully decrypt the image.

Apart from creating an encrypted single image, the key decryption info should also be written in the image’s header.

This can be achieved with the following command:

set the aes/iv key

mkimage.exe set_decryption_info file_to_modify aes_iv_key_index[aes_iv_revokation_index]

This command will be used to set the aes/iv key index in the image’s image header.

The first argument is the file that will be edited file_to_modify.

The second argument is the aes/iv key index that tells the bootloader which of the 5 OTP keys to use for decrypting the image aes_iv_key_index. The valid range for aes_iv_key_index is [0, 4].

The third argument aes_iv_revokation_index is optional and if provided it will write the image header with an AES/IV key revokation index, this will tell the bootloader which of the 5 AES/IV Key Entries should be revoked. The valid range for aes_iv_revokation_index is [0, 4]. .

Note

If key revokation is desired, the image should be signed afterwards. An unverified image cannot revoke a key. Also, key revokation is only supported by images coming from an external memory (SPI or I2C).

A new command has been added that supports single image signing. This means that before running the sign command, the mkimage single command has to be ran first. Then the mkimage set_decryption_info command should be ran (if the image was encrypted) to set the decryption key information in the image header. As a last step before running the mkimage sign command, the user should also run the mkimage set_verification_info command to set the key verification index/info in the image’s header. Then after all these steps have been done the image can be signed. It is important to always sign the image as a last step after all the changes to image header have been done. The reason is because part of the image header is also used to sign the image.

set ECC key index

mkimage.exe set_verification_info <file_to_modify> ecc_key_index[ecc_revokation_index]

This command shall be used to set the ecc key index in the image’s header. The given ECC key index will tell the bootloader which of the 5 OTP ECC key entries should be used for verifying this image. The range of this value is 0 to 4.

The first argument is the file that will be edited file_to_modify.

The second argument is the ECC key index that tells the bootloader which of the 5 ECC OTP keys to use for verifying the image ecc_key_index.

The third argument ecc_revokation_index is optional and if provided it will write the image header with an ECC key revokation index. The valid range for ecc_revokation_index is [0, 4].

Note

If key revokation is desired, the image should be signed afterwards. An unverified image cannot revoke a key. Also, key revokation is only supported by images coming from an external memory.

Create sign image

mkimage.exe sign <input_image> <output_image> ecc_key

The input image’s name input_image should be provided followed by the output image’s name output_image.

the user should also provide the ECC private key ecc_key that should be used for signing. The key should be provided as a 64 hex string without any prefix (no 0x).

At the end of the signed image generation, the tool should print out the ECC private key, public key and signature so that the user is informed about all of them and also be able to use the public key on their application for verifying their signed images (burn it in the OTP Key storage along with other ECC public keys).

The resulting image is the given single image with its signature appended at the end of it (64 bytes).

Getting an ECC public key from a given ECC private key

mkimage.exe ecc_pubkey ecc_private_key

The user should provide their ECC private key ecc_private_key for which they want the ECC public key. The key should be provided as a 64 hex string without any prefix (no 0x).

The command should print out the ECC public key that is associated with the given private key.

Getting an ECC private and public key pair

mkimage.exe  ecc_keygen

Note

This is a helper command for generating ecc private keys along with their associated public keys. The users may use their own secure method for obtaining an ECC private key and use the ecc_pubkey command described above to obtain its associated public key

6.2.7.4.2. Image header

To support the new security features, the image header has been updated to include additional information:

Table 40 Single Image Header

Status code

Description

0

Signature (0x70 = ‘p’)

1

Signature (0x51 = ‘Q’)

2

Valid Flag

3

Image ID

4-7

Code Size

8-11

CRC

12-17

Version

28-31

Timestamp

32

Flags

33

Encryption Pad

34-39

Key information

40-63

Reserved

  • Bytes 0-1: Signature field that identifies this header as a single image header.

  • Byte 2: Image valid flag (0x00 invalid, 0xAA valid).

  • Byte 3: Image identifier.

  • Bytes 4-7: Size (in bytes) of the following image.

  • Bytes 8-11: CRC of image.

  • Bytes 12-27: Image version information (ASCII string).

  • Bytes 28-31: Image timestamp.

  • Byte 32: Flags (0x00 not signed or encrypted, 0x01 encrypted, 0x02 signed, 0x03 signed and encrypted).

  • Byte 33: Encryption pad: Information on the padding that was done during encryption.

  • Bytes 34-39: The key information (6 bytes total).

ECC key information

This is filled with the mkimage set_verification_info command

  • ECC key index (1 byte): The ECC key index in the OTP storage that should be used to verify this image

  • ECC revokation valid flag (1 byte): A flag that marks the ECC revokation index valid or not

  • ECC revokation index (1 byte): The ECC revokation index (the index of the ECC key entry that should be revoked in the OTP key storage)

AES key information

This is filled with the mkimage set_decryption_info command

  • AES key index (1 byte): The AES key index in the OTP storage that should be used to decrypt this image

  • AES revokation valid flag (1 byte): A flag that marks the AES revokation index as valid or not

  • AES revokation index (1 byte): The AES revokation index (the index of the AES key entry that should be revoked in the OTP key storage)

11/ Bytes 33-63: Reserved for future use.

6.2.7.4.3. mkimage example

Below it shows how an encrypted and signed image is created:

Create the single encrypted image

  • create an encrypted image with key 06a9214036b8a15b512e03d534120006  and IV 3dafba429d9eb430b422da802c9fac41

mkimage single rawfile.bin sdk_version.h my_image.img enc 06a9214036b8a15b512e03d534120006 3dafba429d9eb430b422da802c9fac41
  • Set the AES/IV key index that is going to be used for decrypting this image (let’s say that the key pair above was put at index 0 in our current example)

mkimage set_decryption_infomy_image.img 0
  • Set the ECC key index that is going to be used for verifying this image (let’s say that the ECC public key that results from the ECC private key that we are going to sign the image with, is placed in the ECC key entry 1)

mkimage set_verification_infomy_image.img 1

Sign the image with the private key that associates with the public key that was burned in ECC key Entry 1

mkimage sign my_image.img my_signed_encrypted_image.img C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721

This command will return the private ECC key that we used along with the ECC public key that results from that private key as well as the image’s signature:

Private Key:

c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721

Public Key:

60fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb67903fe1008b8bc99a41ae9e95628bc64f2f1b20c2d7e9f5177a3c294d4462299

Signature:

585c2dcf99ed6538f7292b1de70f9963a716b4d572ac11063cc86c65e7c465eb39a5dbfb629f014b977224750bd57f93c9d0087a9cd41410a10d2b5fe9648e15

The ECC public key should be written in the device’s OTP in the ECC key entry 1.

6.2.7.4.4. Creating an Application Image File

The image created from the above example can either be boot from UART in the secondary bootloader or downloaded via SUOTA to the device (stored in an external memory) or can be used to create a multi image for the user to burn during production in their device’s SPI or I2C external memory: The command line syntax to create a multi-part binary image file (*.img) with the entire contents of a non-volatile memory is:

mkimage.exe multi spi|eeprom [<bloader>] <in_img1> <off1> <in_img2> <off2> <off3> [cfg off4[,bdaddr]] <out_file>

multi Instructs the tool to create the <out_file> binary image file (*.img) with the entire contents of the SPI Flash memory (option: spi) or the I2C EEPROM (option: eeprom).

The multi-part image consists of:

  1. AN-B-001 header plus the bootloader firmware <bloader> at offset 0, if <bloader> is provided.

  2. <img1> (*.img image) at offset <off1>

  3. <img2> (*.img image) at offset <off2>

  4. Product header at offset <off3>

mkimage multi spi my_signed_encrypted_image.img 0x0000 my_signed_encrypted_image.img 0x19000 0x38000 my_multi_signed_encrypted_image.bin

The cfg option configures the following product header fields:

  • The application specific ‘Configuration Offset’ is initialized from off4. If off4 is not provided, then the ‘Configuration Offset’ field shall be set to 0xFFFFFFFF.

  • The BD Address is initialized from ‘bdaddr’. If bdaddr is not provided, then the BD Address field shall be set to FF:FF:FF:FF:FF:FF. If bdaddr is provided, it is required that no space exists between off4, the comma character and the ‘bdaddr’.

The offsets can be given either as decimal or as hexadecimal numbers.

The BD address ‘bdaddr’ can be given as XX:XX:XX:XX:XX:XX where X is a hex digit. For example, 80:EA:CA:01:02:03.