MSPM0 Customer Secure Code and Bootloader (CSC) User’s Guide

1. Introduction

The Customer Secure Code (CSC) is an implementation of the publicly available mcuboot for devices in the MSP Family with advanced security features, such as the device family MSPM0L122x_MSPM0L222x, in order to allow for customers to have additional and more advanced secure booting features in their development and deployment. When paired with an example such as the customer_secure_image_with_bootloader example, this represents a full solution for updates and verification of new images on the device. However, the customer secure code rigorous definition only refers to the verification of the image and configuring security settings, not loading the image onto the device. The full set of features and execution flow will vary depending on the specific device used and features present on the device.

The Customer Secure Code rigorously defined has the following features:

  • It can verify one or more application images using Elliptic Curve Digital Signature Algorithm (ECDSA) with NIST P-256 curve and hashing algorithm SHA-256

  • It takes up less than 18 kB of flash per bank (allowing for two 110kB images on a 256kB device)

  • mcuboot is open source and can be modified to fit the end developer’s needs, additionally the CSC has it’s own set of security features and is easily configurable via a header file or SysConfig to tailor the solution to the end needs of the user

  • It does not require additional HW support in order to verify images, but can utilize a secure verification via CMAC for quicker (< 100ms) booting from a power on reset (POR) when the image is unchanged.

  • It sets up security features on the device such as write, read, and IP protect firewalls

  • It sets up the KEYSTORE and the bank-swapping policy, and dynamically manage and revoke keys as the user intends

  • It can provide rollback protection

  • It can (and should in production) be made immutable and act as part of the Root of Trust (RoT) chain during a boot.

  • Provide easy feature configuration through the SysConfig tool, such that users can quickly build a CSC tailored to their needs

Some things the current CSC (rigorously defined) doesn’t do:

  • It does not load application images onto a device (doesn’t replace the bootloader), however a bootloader example is given where the bootloader resides within the application (allowing it to be securely updateable)

  • It does not guarantee a full secure boot implementation on a device

NOTE: currently some features are still being developed as time goes on, so please contact TI with any questions and priorities of additional needs

2. Using the Examples

It is recommended to run the existing example pair of the customer_secure_code and customer_secure_image_with_bootloader in order to better understand the development flow for each component before developing further. The example provided has a test key and several pre-built images that can get the developer acquainted with running and validating an example successfully. Both of these projects should be imported into a compatible CCS version (12.7.1+). This example uses the MSPM0L2228 LaunchPad with settings shown in the project README.

2.0 Prerequisites

To run the initial setup, make sure Python 3.7 or newer is installed with the latest pip package and run the following command to download the necessary requirements.

python -m pip install --user -r source/third_party/mcuboot/scripts/requirements.txt

2.0.1 Python Versioning in OSX or Linux

The functions and pre-build steps will use Python 3.7 with the command python in order to envoke the python executable. Thus, the command python --version should yield 3.7 or greater.

In Linux or Mac setups, python can refer to a separate version, so it is recommended either to alias the python3 command to python, or if two distinct versions are needed, to modify the post build step in the example to use python3 instead.

2.1 Application Image Example Building

The application image example customer_secure_image_with_bootloader and the example customer_secure_sample_image are CCS projects that contain two configurations for creating two images: one that flashes green, and one that flashes blue. These images are both designed for execute in place, where the swapping is covered by bank-swapping.

NOTE: The application images cannot run in isolation on a device without the boot application present.

In order to switch the configurations, one can navigate to the properties of the project and select Manage Configurations to set the active configuration or build both configurations simultaneously using Build All.

It is recommended to build both the configurations to be able to test more functionality of the boot application.

This process also includes a post-build step that can be found in the Steps tabs of Properties → Build. This takes care of signing the image and outputting it into a binary and ti-txt file with important information about it. The output file will resemble sample_image_signed_<compile address>_<version>_<color>

The elements of the built image binary name are as follows:

  • compile address: the address of where the image is compiled to be executed from, it should be loaded into (bank offset)+compile address. On a 256 kB device, a compile address of 0x4800 would be loaded into either 0x4800 (in an open device) or 0x24800 (once the device is in the field and operating).

  • version: the version of the image

  • color: the led flashing color of the image

The version and other parameters can be modified in the signedArgs.json file included in the project. Currently, only version is supported in the v1.0. This is the version with which the images are signed. If different versions are desired, edit the version field of the file following the format specified, and rebuild the example.

2.2 Running the Boot Example

Build both examples. Before flashing the device, proceed to Properties → Debug and select the MSPM0 Flash Settings from the list on the left hand side of the Debug page. Then configure the Erase method to erase necessary sectors only (shown below), and Configure reset type to Hard Reset (if available).

After this, begin to Debug the project. The main function should now be entered. There shouldn’t be any valid images present on the device now, so running the example should result in a flashing red LED.

2.3 Loading the Binary Images

To load the binary images onto the device, follow these steps once the boot application is being debugged:

  1. Open the Memory browser for the device, which can be found by navigating to View → Memory Browser. To load the binary image, pause the running of the device and click the green silicon package with the arrow and select Load Memory

  2. Point to the specific sample image built in Build Application Image. It is recommended to load the green image first. Select the binary file type from the drop down list as shown below. Click Next at the bottom.

  3. Finally, enter the start address. This should match the value of the first memory slot, as well as the value listed in the file name. Once written, select Finish.

  4. Also add the Customer Secure Code into the other bank, in the customer secure code project, go to the file Debug/customer_secure_code_LP_MSPM0L2228_ticlang-bank1-0x20000.bin and add this at address 0x20000.

  5. Verify that the boot application has not been erased by checking early in flash memory in the memory browser (such as 0x0000). Also verify the image has been successfully loaded into the image slot by typing the starting address into the memory browser. If both elements are present, then the device can be reset using the reset button on the LaunchPad. This will issue a stronger BOOTRST than the debuggers SYSRST and enact the secure policy. During the boot, the RED LED will be solid while it is performing the boot routine. The highest version image that is correctly signed should be run, regardless of bank. The LED should transition from RED to a GREEN or BLUE LED (depending on which image was run).

  6. Perform an Update: Make sure the debugger is disconnected at this point and the device is running (it may interfere with serial bootloading over the same line). Press the left switch (S2 on the launchpad) for the device to enter the BSL sequence. This will turn the LED CYAN and solid (both blue and green simultaneously).

  7. Using Uniflash 8.5 (or newer) open the bootloader version for the MSPM0L2228 Launchpad. Next, add a new encrypted file. The new file should be a newer version of the file previously loaded, preferably one with the opposite LED color. The file should be the text file ending in _encrypted.txt for the given version. Examining the file, there is a header telling the secure bootloader key information, and the image is encrypted. Once the correct COM port is selected, click the Load Image button and the update will happen, a BOOTRST will automatically occur, and the new image should be jumped to.

  8. The device LED should become solid RED after the programming, and then the LED should transition to the color of the updated image.

3 Developing using the Customer Secure Code

While the examples provide a good starting point for some development techniques, this section elaborates on some of the developments that will likely be necessary in order to take full advantage of the CSC.

3.1 Creating and Using Keys

ECDSA is currently the only supported authentication method for mcuboot. ECDSA is an asymmetric algorithm, meaning there is a separate public and private key. The public key will be stored in the device flash and the private will be maintained by the developer securely. Included in the mcuboot folder is the imgtool.py python script that can sign images and create keys.

In order to generate a new key, the user can enter the following command creating a key called newkey.pem (or whatever name is suitable):

cd source/third_party/mcuboot/
scripts/imgtool.py keygen -k newkey.pem -t ecdsa-p256

The public key is then derived from the .pem file, encoded in the DER format. It is autogenerated from the following instruction.

scripts/imgtool.py getpub -k newkey.pem

this will output to the console the public key information (encoded in DER format), which is then copied and pasted into boot_keys.c in the EC256 section (specifying the supported algorithm).

The private key must now also be pointed to using its file location, and this can be provided when signing as a path within the SDK using the privateKeyPath argument.

IMPORTANT: for final deployment, it is very important to keep the private key secure and managed such that it is not easily accessible to sign images. Keeping the key on a local share drive is not a secure location! TI does not currently provision/store keys on behalf of other entities.

For more information about generating keys, one can visit the imgtool ReadMe.

3.2 Creating and Signing the Application Image

The mcuboot tool is capable of verifying and jumping to images, however these images must first be created in a format that is understood by mcuboot. This is done by a combination of linker modification to fit the memory map and using the imgtool provided by mcuboot, and included in this SDK under source/third_party/mcuboot/scripts.

The default image memory map of the MSPM0L2228 is provided as a reference for 2 on-chip images of equal size (one in each bank). The flash size required for mcuboot is less than 0x4800 depending on build configurations and optimizations. Consequently, the largest image that can currently fit on this device is ~110kB.

This document is intended as a summary guide in order to allow a developer to begin using the boot image manager for MSP, and not to comprehensively cover the image capabilities. To understand more about advanced features of the headers or develop other features, please consult the online mcuboot documentation such as the mcuboot design documentation.

3.2.1 Building the Unsigned Image

Currently the only supported compiler for the boot application is ticlang. However, the developer can compile their application image with any compiler. Using a favorite IDE, the user can convert the image to a signed image by creating a binary unsigned output file. However, the application must fit in the size of the image slot on the device. In a 64kB flash device with two equal slots, the maximum size supported is 21 kB. Images do not have to be position independent or change information about headers or vectors in order to function appropriately. However, they must be linked to their execution slot.

Additionally, the image cannot run on its own without the boot application present. When developing an application image, it may be better to develop it with respect to 0x0000 on the device, run on a device without the boot application. Then, when an image is ready to be created, change the linking properties to run from the slot.

Important: mcuboot will select between the images using execute in place (XIP), so the images will not be swapped by default. Because of this, the developer must create the image with respect to the image slot that the image will go into. In many cases, this could mean maintaining two images built for primary and secondary slots. Otherwise, unexpected behavior could occur.

Building the image will require several modifications to a standard linker file:

  • The start of the flash will need to be considered as the beginning of the image slot plus the header offset. For example, if the primary image slot starts at 0x5400, and the mcuboot header is of size 0x100, the first element of flash of the application (the interrupt vector table) should be at address 0x5500. NOTE: The interrupt vector table must be 256-bit aligned. Thus, the header has additional padding such that the vector table can be accessed correctly.

  • The size of flash will be the image size minus the size of the header and trailer. The trailer for unencrypted, execute in place is generally very small (<50 bytes) and is not considered in the calculations for the provided example. However, in future configurations, the trailer may need to be considered in image size.

  • The RAM can remain unaltered, as all RAM from the BIM will be yielded to the application.

A template of these modifications for a ticlang linker file can be found in the customer_secure_image_with_bootloader example.

After compiling and creating the image, the output should be converted to binary format. The command to do this in CCS is:

${CG_TOOL_ROOT}/bin/tiarmobjcopy ${ProjName}.out --output-target binary ${ProjName}-unsigned.bin

It is recommended to name the output file with the suffix “unsigned” as to avoid confusion. This can be automated by adding it to the post-build steps of the project for your IDE.

3.2.2 Signing the Image

The imgtool provided by mcuboot can then sign this image and provide the appropriate header. This call is done during the post build steps by the wrapping function sign-image.py The following instruction uses the imgtool to sign an image:

./scripts/imgtool.py sign --header-size 0x100 --align 4 --slot-size 0x5400 --pad --version 1.0.0 -s 1 --pad-header --key path/to/private/key.pem ${ProjName}-unsigned.bin ${ProjName}.bin

The information that the developer may need to edit are as follows:

  • Key - the developer must change the key path to their private key (pem file), which can be generated following the steps in Creating and Using Keys. This path can be edited to anywhere in the SDK using the signingArgs.json value privateKeyPath.

  • Version - the developer should include their versioning for the image. This can also be edited in the JSON configurable file with a single version or a list of multiple versions.

  • Slot size - if the memory map has been altered, see Memory Map Customization, the slot size will need to be accounted for.

  • Security Version - the user can change the security version (-s option) of the software for rollback protection, however the feature is not currently supported in the beta release.

This function is included in the python script sign-image.py project (with paths filled in).

3.2.3 Encrypting the Image

Image encryption in Flash is currently not supported. Image encryption over the air to be decrypted by the bootloader is planned for the full release.

3.2.4 Updating the Image

The customer_secure_image_with_bootloader has a limited version of the BSL protocol such that a device could be updated in the field over UART via the BSL protocol. It can also be updated using the standard GUI tools such as UNIFLASH and the BSL GUI, although certain functionality like memory readback and factory reset is disabled. In the Beta Implementation, this feature is currently unencrypted and doesn’t require a password.

To update, use the serial bootloader connection in UniFlash with the MSPM0L2228 device. Use the ti-txt file generated in the post-build steps in order to load to the device. If default memory addresses are used, the file should start at 0x24800.

When ready to perform the bootloading, press S2 on the launchpad and the LED will turn cyan and remain solid. This indicated the device is attempting to perform a BSL update.

Select the correct COM port and load the image via UniFlash. Upon completion the device will automatically restart and the CSC will attempt to validate the new image and jump to it.

Important this feature is released as a beta, and does not have all features or security settings that may be included. TI reserves the right to change the above information.

4 Modifying the CSC

The CSC has increase modularity via the configurable file customer_secure_config.h. This is native to the customer_secure_code example but is inherited by sample image examples. It is controlled by the Security Configurator tab in SysConfig and can be used as a reference.

Important This section is still under development so there are more elements and features being supported continuously. If one is not supported yet, it’s in the roadmap. Please contact TI for more information

4.1 Other Image Management Techniques

While execute in-place (XIP) is the default image management technique, there are other methods such as swapping which offers different advantages. Currently only XIP is supported in the beta implementation.

4.2 Customization of the Memory Map

The memory map of the device is something that can be freely altered on the device. This can be changed by opening the file flash_mem_backend.c of the device and adjusting the defines to a user-specified setting. However, it is important to make sure whatever changes are made to the memory map are also accounted for in the applications linker and image size of the signing step.

Note. Some M0L devices have a known issue where the last 8 bytes of the memory cannot be programmed successfully. Because mcuboot works in sectors, it is not recommended to use the final sector of these devices as part of an image slot or scratch slot. The sector can be written to and erased and could be used by the application. The standard linker file for the device will have a slightly smaller flash size if the device is affected.

4.3 Failure behavior

Currently, upon a failure to load a successful image, the mcubootFail function will be entered, which is defined in the customer_secure_code.c file. The default behavior on a failure is to toggle LED2 (Red on the LaunchPad). However, this behavior can be customized to fit the developers needs. For example, a permanent, reduced functionality image could be included if all valid images fail.

4.4 Additional configuration

There are additional configurations available for mcuboot. More information can be found by consulting the mcuboot documentation. However, not all of these features are currently implemented or feasible on MSP.

Additional Customer Secure Code Features are still under development. Contact TI for more information.

5 Security Principles in MSP

5.1 Static Write Protection

To avoid unwanted erasure of the CSC, it is important to configure the NONMAIN region to disallow writes to the area of flash that the boot application will reside in. This requires changes to the default configuration of the examples, as these are designed chiefly for development and debugging.

For more information about the NONMAIN region, consult the device specific Technical Reference Manual.

5.2 Root of Trust Using NONMAIN

With the write protection enabled on NONMAIN, it is still possible for a factory reset to wipe the entire device. Preventing a factory reset (or only allowing it with a password) is a mechanism that allows developers to ensure the booting of the device into NONMAIN.

5.3 Rollback Protection

One of the security features mcuboot provides is rollback protection: where a user can set a security version that new images must match or exceed in order to be accepted by the boot image manger. This prevents an attacker from installing a previous image which may contain a vulnerability that is fixed in later versions.

This feature is not available on current M0L or M0G devices due to the non-main write protect occurring statically once upon startup. Rollback protection generally requires the hardware capability to prevent writes to a region dynamically (after verifying but before jumping to an image).

5.4 Keystore

It is important that unwanted entities do not have access to plaintext keys, but how does a user hide these keys, but still use them in the AES?

The answer is to have a separate section of memory that cannot be read out from the device, but is able to send keys on a separate bus to the AES for use based on the slot that is present. This is the job of the KEYSTORE on our device.

In order to communicate which keys are stored in the Keystore to the application, the CSC outputs in lockable storage the hashes of the keys, which an application can use to index the different slots and identify and use keys without being able to gain information about the key material itself.