TFM Integration Samples¶
Trusted Firmware-M (TF-M)¶
Overview¶
These TF-M integration examples can be used with a supported Armv8-M board, and demonstrate how the TF-M APIs can be used with Zephyr.
Trusted Firmware Platform Security Architecture (PSA) APIs are used for the secure processing environment (S), with Zephyr running in the non-secure processing environment (NS).
As part of the standard build process, the secure bootloader (BL2) is normally built, in addition to the TF-M S and Zephyr NS binary images. The S and NS images are then merged and signed using the private signing keys, whose public key values are stored in the secure bootloader. This allows the application images to be verified and either accepted or rejected during the image verification process at startup, based on a pair of private keys that you control.
What is Trusted Firmware-M (TF-M)?¶
Trusted Firmware-M (TF-M) is the reference implementation of Platform Security Architecture (PSA).
TF-M provides a highly configurable set of software components to create a Trusted Execution Environment. This is achieved by a set of secure run time services such as Secure Storage, Cryptography, Audit Logs and Attestation. Additionally, secure boot in TF-M ensures integrity of run time software and supports firmware upgrade.
The current TF-M implementation specifically targets TrustZone for ARMv8-M.
Trusted Firmware M source code is available at git.trustedfirmware.org, although a fork of this source code is maintained by the Zephyr Project as a module for convenience sake at https://github.com/zephyrproject-rtos/trusted-firmware-m.
For further information consult the official TF-M documentation
TF-M Requirements¶
The following Python modules are required when building TF-M binaries:
cryptography
pyasn1
pyyaml
cbor>=1.0.0
imgtool>=1.6.0
jinja2
click
You can install them via:
$ pip3 install --user cryptography pyasn1 pyyaml cbor>=1.0.0 imgtool>=1.6.0 jinja2 click
They are used by TF-M’s signing utility to prepare firmware images for validation by the bootloader.
Part of the process of generating binaries for QEMU and merging signed
secure and non-secure binaries on certain platforms also requires the use of
the srec_cat
utility.
This can be installed on Linux via:
$ sudo apt-get install srecord
And on OS X via:
$ brew install srecord
For Windows-based systems, please make sure you have a copy of the utility available on your system path. See, for example: SRecord for Windows
Images Created by the TF-M Build¶
The TF-M build system creates executable files:
tfm_s - the secure firmware
tfm_ns - a nonsecure app which is discarded in favor of the Zephyr app
bl2 - mcuboot, if enabled
For each of these, it creates .bin, .hex, .elf, and .axf files.
The TF-M build system also creates signed variants of tfm_s and tfm_ns, and a file which combines them:
tfm_s_signed
tfm_ns_signed
tfm_s_ns_signed
For each of these, only .bin files are created. The Zephyr build system usually signs both tfm_s and the Zephyr app itself, see below.
The ‘tfm’ target contains properties for all these paths.
For example, the following will resolve to <path>/tfm_s.hex
:
$<TARGET_PROPERTY:tfm,TFM_S_HEX_FILE>
See the top level CMakeLists.txt file in the tfm module for an overview of all the properties.
Signing Images¶
TF-M uses a secure bootloader (BL2) and firmware images must be signed with a private key. The firmware image is validated by the bootloader at startup using the corresponding public key, which is stored inside the secure bootloader firmware image.
By default, tfm/bl2/ext/mcuboot/root-rsa-3072.pem
is used to sign secure
images, and tfm/bl2/ext/mcuboot/root-rsa-3072_1.pem
is used to sign
non-secure images. Theses default .pem keys keys can be overridden using the
CONFIG_TFM_KEY_FILE_S
and CONFIG_TFM_KEY_FILE_NS
values.
The wrapper.py
script from TF-M signs the TF-M + Zephyr binary using the
.pem private key..
To satisfy PSA Certified Level 1 requirements, You MUST replace the default .pem file with a new key pair!
To generate a new public/private key pair, run the following commands:
$ cd $ZEPHYR_BASE/../modules/tee/tfm/trusted-firmware-m/bl2/ext/mcuboot/scripts $ chmod +x imgtool.py $ ./imgtool.py keygen -k root-rsa-3072.pem -t rsa-3072 $ ./imgtool.py keygen -k root-rsa-3072_1.pem -t rsa-3072
You can then replace the .pem file in [TF-M_PATH]/bl2/ext/mcuboot/
with
the newly generated .pem files, and rebuild the bootloader so that it uses the
public key extracted from this new key file when validating firmware images.
Alternatively, place the new .pem files in an alternate location, such as your
Zephyr application folder, and reference them in the prj.conf
file via the
CONFIG_TFM_KEY_FILE_S
and CONFIG_TFM_KEY_FILE_NS
config values.
Warning
Be sure to keep your private key file in a safe, reliable location! If you lose this key file, you will be unable to sign any future firmware images, and it will no longer be possible to update your devices in the field!
After the built-in signing code has run, it creates a tfm_merged.hex file that contains all the binaries, bl2, tfm_s, and the zephyr app.
Custom CMake arguments¶
When building a Zephyr application with TF-M it might be necessary to control the CMake arguments passed to the TF-M build.
Zephyr TF-M build offers several Kconfig options for controlling the build, but doesn’t cover every CMake argument supported by the TF-M build system.
The TFM_CMAKE_OPTIONS
property on the zephyr_property_target
can be used
to pass custom CMake arguments to the TF-M build system.
To pass the CMake argument -DFOO=bar
to the TF-M build system, place the
following CMake snippet in your CMakeLists.txt file.
set_property(TARGET zephyr_property_target APPEND PROPERTY TFM_CMAKE_OPTIONS -DFOO=bar )
Note
The TFM_CMAKE_OPTIONS
is a list so it is possible to append multiple
options. Also CMake generator expressions are supported, such as
$<1:-DFOO=bar>