Mistake on this page?
Report an issue in GitHub or email us

Porting PSA targets

This document describes the process of adding new PSA targets to Mbed OS, focusing on target configurations, build and validation. Mbed OS relies on TF-M for its implementation of PSA, so the PSA target you are adding to Mbed OS must already be supported by TF-M.

Before reading this document, please read porting a custom board and porting targets, which provide step-by-step instructions to porting a new target to Mbed OS.

Glossary

  • NSPE: Non-Secure Processing Environment.
  • PSA: Platform Security Architecture.
  • SPE: Secure Processing Environment.
  • TF-M: Trusted Firmware M (for M-class devices).

Adding new PSA targets

To help create PSA targets, we have added a few generic targets to targets/targets.json:

  • PSA_Target: Root level PSA target.
  • PSA_V7_M: Single v7-M generic PSA target, which doesn't employ hardware isolation between the NSPE and the SPE. PSA secure service emulation enables PSA API compatibility.
  • PSA_DUAL_CORE: Dual-core generic PSA target. A dual-core PSA target has at least two cores that are either Armv7-M or Armv6-M. One core will be used for the SPE and another for the NSPE. Hardware isolation between the cores enables PSA compliance. On dual-core targets, TF-M runs on the SPE and provides PSA services, and Mbed OS runs on the NSPE.
  • PSA_V8_M: Armv8-M generic PSA target, which employs hardware to isolate the NSPE from the SPE. TF-M runs on the SPE and provides PSA services, and Mbed OS runs on the NSPE.

NSPE generic targets

SPE binaries are generated by TF-M build tools, not Mbed-OS build tools. Therefore, when adding a new PSA target to Mbed OS, you don't need to define an SPE target; it's enough to define an NSPE target. Therefore, for dual-core (PSA_DUAL_CORE) and Armv8-M (PSA_V8_M), we have defined only PSA NSPE generic targets.

Inheritance

The Mbed OS build tools have limited support for multiple inheritance. Because of this, a PSA target must inherit from the generic PSA target corresponding to the new target's architecture (one of PSA_V7_M, PSA_DUAL_CORE and PSA_V8_M) or from one of its family targets, but cannot inherit from both the generic and family targets at once. We cover family inheritance cases in each target section in this document.

Note: The examples in this document are taken from targets/targets.json.

Example of a single-core Armv7-M PSA target's inheritance:

    "K64F": {
        "inherits": ["PSA_V7_M"]
    }

Naming convention for dual-core and Armv8-M targets

As explained above, dual-core and Armv8-M PSA targets require only an NSPE target name. For Armv8-M non-PSA targets, you can define both SPE and NSPE target names.

The naming convention is:

  • TargetName: PSA non-secure target (NSPE).
  • TargetName_NPSA_S: Non-PSA secure target.
  • TargetName_NPSA: Non-PSA non-secure target.

Adding single-core PSA targets

Mbed OS's PSA service emulation provides PSA compatibility for single-core PSA targets.

The following example shows a PSA-enabled single-core target, K64F:

    "K64F": {
        "supported_form_factors": [
            "ARDUINO"
        ],
        "components_add": [
            "SD",
            "FLASHIAP"
        ],
        "core": "Cortex-M4F",
        "supported_toolchains": [
            "ARM",
            "GCC_ARM",
            "IAR"
        ],
        "extra_labels_add": [
            "Freescale",
            "MCUXpresso_MCUS",
            "KSDK2_MCUS",
            "FRDM",
            "KPSDK_MCUS",
            "KPSDK_CODE",
            "MCU_K64F",
            "Freescale_EMAC"
        ],
        "is_disk_virtual": true,
        "macros_add": [
            "CPU_MK64FN1M0VMD12",
            "FSL_RTOS_MBED",
            "MBED_SPLIT_HEAP",
            "MBED_TICKLESS"
        ],
        "inherits": [
            "PSA_V7_M"
        ],
        "detect_code": [
            "0240"
        ],
        "device_has_add": [
            "USTICKER",
            "LPTICKER",
            "RTC",
            "CRC",
            "ANALOGIN",
            "ANALOGOUT",
            "EMAC",
            "I2C",
            "I2CSLAVE",
            "INTERRUPTIN",
            "PORTIN",
            "PORTINOUT",
            "PORTOUT",
            "PWMOUT",
            "RESET_REASON",
            "SERIAL",
            "SERIAL_FC",
            "SERIAL_ASYNCH",
            "SLEEP",
            "SPI",
            "SPI_ASYNCH",
            "SPISLAVE",
            "STDIO_MESSAGES",
            "TRNG",
            "FLASH",
            "USBDEVICE",
            "WATCHDOG"
        ],
        "release_versions": [
            "2",
            "5"
        ],
        "device_name": "MK64FN1M0xxx12",
        "bootloader_supported": true,
        "overrides": {
            "network-default-interface-type": "ETHERNET"
        },
        "supported_c_libs": {
            "arm": [
                "std",
                "small"
            ],
            "gcc_arm": [
                "std",
                "small"
            ],
            "iar": [
                "std"
            ]
        }
    }

Note the config options macros_add, extra_labels_add and device_has_add. To add or remove macros, extra_labels or target capabilities, a PSA target definition must use [macros/extra_labels/device_has]_add or [macros/extra_labels/device_has]_remove (not macros, extra_labels or device_has).

To add or remove a feature, use feature_[add/remove].

As a second example, here is a single-core Armv7-M PSA target that inherits from one of its family targets:

    "GD32_F450ZI": {
        "inherits": [
            "GD32_Target"
        ]
    }

In this case, you must add the following additional attributes:

        "features_add": [
            "PSA"
        ],
        "extra_labels_add": [
            "MBED_PSA_SRV"
        ]

Adding dual-core PSA targets

A target can be categorized as a dual-core target if it has at least two cores that are either Armv7-M or Armv6-M. On dual-core PSA targets, TF-M runs on the SPE and provides PSA services.

An Mbed OS (NSPE) target must contain the following attributes (in addition to other target attributes defined in porting a custom board and porting targets):

  • inherits: PSA generic target PSA_DUAL_CORE, unless the target has to inherit from one of its family targets.

  • tfm_target_name: Target name in TF-M.

  • tfm_bootloader_supported: If TF-M bootloader is supported by the target.

    The supported values are true and false.

  • tfm_supported_toolchains: Supported TF-M toolchains.

    The supported values are ARMCLANG and GNUARM.

  • tfm_default_toolchain: Default TF-M toolchain.

    The supported values are ARMCLANG and GNUARM.

  • tfm_delivery_dir: The directory to which TF-M binaries will be copied.

  • TFM_OUTPUT_EXT: Optional attribute that indicates the output extension of the TF-M secure binary.

The following example shows a PSA enabled dual-core target, PSoC64:

    "CY8CKIT_064S2_4343W": {
        "inherits": [
            "MCU_PSOC6_M4"
        ],
        "features_add": [
            "BLE",
            "PSA"
        ],
        "components_add": [
            "WHD",
            "4343W",
            "CYW43XXX"
        ],
        "components_remove": [
            "QSPIF"
        ],
        "supported_form_factors": [
            "ARDUINO"
        ],
        "device_has_remove": [
            "ANALOGOUT",
            "QSPI"
        ],
        "extra_labels_add": [
            "PSOC6_02",
            "MXCRYPTO_02",
            "CORDIO",
            "TFM",
            "TFM_DUALCPU"
        ],
        "macros_add": [
            "CYB0644ABZI_S2D44",
            "CYBSP_WIFI_CAPABLE",
            "TFM_MULTI_CORE_MULTI_CLIENT_CALL=1"
        ],
        "detect_code": [
            "190A"
        ],
        "post_binary_hook": {
            "function": "PSOC6Code.sign_image"
        },
        "forced_reset_timeout": 5,
        "overrides": {
            "network-default-interface-type": "WIFI"
        },
        "program_cycle_s": 10,
        "tfm_target_name": "psoc64",
        "tfm_bootloader_supported": false,
        "tfm_default_toolchain": "GNUARM",
        "tfm_supported_toolchains": [
            "GNUARM"
        ],
        "tfm_delivery_dir": "TARGET_Cypress/TARGET_PSOC6/TARGET_CY8CKIT_064S2_4343W",
        "TFM_OUTPUT_EXT": "hex"
    }

Please note the config options macros_add, extra_labels_add and device_has_remove. To add or remove macros, extra_labels or target capabilities, a PSA target definition must use [macros/extra_labels/device_has]_add or [macros/extra_labels/device_has]_remove (not macros, extra_labels or device_has).

To add or remove a feature, use feature_[add/remove].

By default, a TF-M build generates a bin file. If the target requires a hex file, you need to add the attribute "TFM_OUTPUT_EXT": "hex" to the target definition. The build script will convert bin to hex, then copy the hex to tfm_delivery_dir.

This dual-core PSA target doesn't inherit from PSA_DUAL_CORE because it has to inherit from one of its family targets. Hence, we have added additional attributes:

        "features_add": [
            "PSA"
        ],
        "extra_labels_add": [
            "TFM",
            "TFM_DUALCPU"
        ]

If a dual-core PSA target can inherit from PSA_DUAL_CORE, then there is no need to add these additional attributes.

Adding Armv8-M PSA targets

An Mbed OS (NSPE) target must contain the following attributes (in addition to other target attributes defined in porting a custom board and porting targets):

  • inherits: PSA generic target PSA_V8_M, unless the target has to inherit from one of its family targets.

  • tfm_target_name: Target name in TF-M.

  • tfm_bootloader_supported: If TF-M bootloader is supported by the target.

    The supported values are true and false.

  • tfm_supported_toolchains: Supported TF-M toolchains.

    The supported values are ARMCLANG and GNUARM.

  • tfm_default_toolchain: Default TF-M toolchain.

    The supported values are ARMCLANG and GNUARM.

  • tfm_delivery_dir: The directory to which TF-M binary will be copied.

  • TFM_OUTPUT_EXT: Optional attribute that indicates the output extension of the TF-M secure binary.

The following example shows a PSA-enabled Armv8-M PSA target, ARM_MUSCA_A1:

    "ARM_MUSCA_A1": {
        "inherits": [
            "PSA_V8_M"
        ],
        "default_toolchain": "ARMC6",
        "forced_reset_timeout": 7,
        "release_versions": [
            "5"
        ],
        "core": "Cortex-M33-NS",
        "supported_toolchains": [
            "ARMC6",
            "GCC_ARM",
            "IAR"
        ],
        "device_has_add": [
            "INTERRUPTIN",
            "LPTICKER",
            "SERIAL",
            "SLEEP",
            "USTICKER"
        ],
        "macros_add": [
            "__STARTUP_CLEAR_BSS",
            "MBED_FAULT_HANDLER_DISABLED",
            "CMSIS_NVIC_VIRTUAL",
            "LPTICKER_DELAY_TICKS=1",
            "MBED_MPU_CUSTOM"
        ],
        "extra_labels_add": [
            "ARM_SSG",
            "MUSCA_A1",
            "MUSCA_A1_NS"
        ],
        "post_binary_hook": {
            "function": "ArmMuscaA1Code.binary_hook"
        },
        "secure_image_filename": "tfm_s.bin",
        "tfm_target_name": "MUSCA_A",
        "tfm_bootloader_supported": true,
        "tfm_default_toolchain": "ARMCLANG",
        "tfm_supported_toolchains": [
            "ARMCLANG",
            "GNUARM"
        ],
        "tfm_delivery_dir": "TARGET_ARM_SSG/TARGET_MUSCA_A1"
    }

Please note the config options macros_add, extra_labels_add and device_has_remove. To add or remove macros, extra_labels or target capabilities, a PSA target definition must use [macros/extra_labels/device_has]_add or [macros/extra_labels/device_has]_remove (not macros, extra_labels or device_has).

To add or remove a feature, use feature_[add/remove].

By default, a TF-M build generates a bin file. If the target requires a hex file, you need to add the attribute "TFM_OUTPUT_EXT": "hex" to the target definition. The build script will convert bin to hex, then copy the hex to tfm_delivery_dir. You must also update secure_image_filename to match the new file extension.

If an Armv8-M PSA target cannot inherit from PSA_V8_M because it has to inherit from one of its family targets, you must add the following attributes:

        "features_add": [
            "PSA"
        ],
        "extra_labels_add": [
            "TFM",
            "TFM_V8M"
        ]

Enabling PSA at application level

Having an entropy source is crucial for Mbed TLS and PSA. The entropy source porting document discusses why and how to add an entropy source.

If your target doesn't have a True Random Number Generator (TRNG), configure it as a non-PSA target in targets/targets.json. In this scenario, if an application wants to use the target as a PSA target, then it is the application's responsibility to provide an entropy source and mark that target as a PSA target at the application level. To enable PSA for a target from an application, use the config option target_overrides.

An example of mbed_app.json:

"target_overrides": {
    "K64F": {
        "inherits": ["PSA_V7_M"]
    }
}

Build and validation

The Python script build_tfm.py automates building TF-M and copying the TF-M binary to the location defined by the target attribute tfm_delivery_dir. Another Python script, build_psa_compliance.py, automates building PSA API compliance tests.

The mbed-os-tf-m-regression-tests repository contains build scripts, TF-M regression tests and PSA API compliance tests.

Building TF-M and running regression tests

To build TF-M and regression tests:

  1. Clone the mbed-os-tf-m-regression-tests repository.

  2. Update mbed-os.lib to the copy of Mbed OS that contains new target support, including the targets.json changes described in this document.

  3. Run:

    mbed deploy
    
  4. Run:

    python3 build_tfm.py -m <new target> -t <toolchain> -c ConfigRegressionIPC.cmake
    

    The command builds a TF-M binary the service necessary to run regression tests.

    Note: Use this ConfigRegressionIPC.cmake only to run regression tests. The secure binary copied to Mbed OS (when you are ready to merge your new target) must be generated using the config option ConfigCoreIPC.cmake.

  5. Ensure the TF-M binary was copied to the location defined by the target attribute tfm_delivery_dir. If no binary was created or copied, please raise an issue on the Mbed OS repository.

  6. To build Mbed OS and run regression tests, run:

    mbed compile -m <new target> -t <toolchain>
    
  7. Flash the regression tests binary to the target and ensure all regression tests pass.

Building TF-M and running PSA compliance tests

To build TF-M and compliance tests:

  1. Switch to the mbed-os-tf-m-regression-tests directory.

  2. Edit mbed_app.json and set:

    • regression-test to 0.
    • psa-compliance-test to 1.
  3. Run:

    python3 build_psa_compliance.py -m <new target> -t <toolchain> -s CRYPTO
    

    The command builds PSA API compliance tests for the crypto suite.

  4. Run:

    python3 build_tfm.py -m <new target> -t <toolchain> -c configs/ConfigPsaApiTestIPC.cmake -s CRYPTO
    

    The command builds TF-M including PSA API compliance tests.

  5. To build Mbed OS and run PSA API compliance tests, run:

    mbed compile -m <new target> -t <toolchain>
    
  6. Flash the PSA API compliance tests binary to the target and ensure all PSA API compliance tests pass.

    Note: Any PSA API compliance tests that fail in the TF-M example application will fail in Mbed OS as well.

Building TF-M and creating an Mbed OS pull request

Note: Please ensure that both regression tests and PSA API compliance tests pass before creating an Mbed OS pull request.

To build TF-M and create an Mbed OS pull request:

  1. Switch to the mbed-os-tf-m-regression-tests directory.

  2. Run:

    python3 build_tfm.py -m <new target> -t <toolchain> --commit
    

    The command builds TF-M with the config ConfigCoreIPC.cmake, copies the TF-M binary to the location defined by the target attribute tfm_delivery_dir, and commits the changes to Mbed OS.

    Tip: When you run the Python script build_tfm.py without any options, TF-M is built for all supported targets and the secure binary (TF-M) for each target is copied to the location defined by the target attribute tfm_delivery_dir. When you use the --commit option, a new Mbed OS commit is created with the new or modified TF-M binaries and features/FEATURE_PSA/TARGET_TFM/VERSION.txt.

  3. Switch to the mbed-os directory and check the latest commit.

    If everything looks good, push the changes to your fork of Mbed OS.

  4. Create an Mbed OS pull request against https://github.com/ARMmbed/mbed-os.

    Tip: See the contributing guide for more information about pull requests.

Further reading

For more information, see:

Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.