diff --git a/doc/guides/tfm/build.rst b/doc/guides/tfm/build.rst index c67b5d1f76b..a6ffbb061ca 100644 --- a/doc/guides/tfm/build.rst +++ b/doc/guides/tfm/build.rst @@ -1,3 +1,5 @@ +.. _tfm_build_system: + TF-M Build System ################# diff --git a/samples/tfm_integration/tfm_secure_partition/CMakeLists.txt b/samples/tfm_integration/tfm_secure_partition/CMakeLists.txt new file mode 100644 index 00000000000..636ba5f1c19 --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/CMakeLists.txt @@ -0,0 +1,36 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.20) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +get_target_property(TFM_BINARY_DIR tfm TFM_BINARY_DIR) +configure_file( + ${CMAKE_CURRENT_LIST_DIR}/dummy_partition/tfm_manifest_list.yaml.in + ${CMAKE_CURRENT_BINARY_DIR}/dummy_partition/tfm_manifest_list.yaml +) + +set_property(TARGET zephyr_property_target + APPEND PROPERTY TFM_CMAKE_OPTIONS + -DTFM_EXTRA_MANIFEST_LIST_FILES=${CMAKE_CURRENT_BINARY_DIR}/dummy_partition/tfm_manifest_list.yaml + -DTFM_EXTRA_PARTITION_PATHS=${CMAKE_CURRENT_LIST_DIR}/dummy_partition +) + +project(tfm_secure_partition) + +target_sources(app PRIVATE + src/main.c + src/dummy_partition.c +) + +target_include_directories(app PRIVATE + ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/interface/include +) + +target_compile_definitions(app + PRIVATE TFM_PARTITION_DUMMY_PARTITION +) diff --git a/samples/tfm_integration/tfm_secure_partition/README.rst b/samples/tfm_integration/tfm_secure_partition/README.rst new file mode 100644 index 00000000000..0160e02c199 --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/README.rst @@ -0,0 +1,51 @@ +.. _tfm_secure_partition: + +TF-M Secure Partition Sample +############################ + +Overview +******** + +A Secure Partition is an isolated module that resides in TF-M. It exposes a number of functions or "secure services" to other partitions and/or to the non-secure firmware. +TF-M already contains standard partitions such as crypto, protected_storage, or firmware_update, but it's also possible to create your own partitions. + +This sample creates a dummy secure partition and secure service for TF-M and instructs the TF-M build system to build it into the secure firmware. +The dummy secure service is then called in the main file (in the non-secure firmware). + +This dummy partition has a single secure service, which can index one of 5 dummy secrets inside the partition, and retrieve a hash of the secret. + +The partition is located in the ``dummy_partition`` directory. It contains the partition sources, build files and build configuration files. +The partition is built by the TF-M build system, refer to :ref:`tfm_build_system` for more details. + +For more information on how to add custom secure partitions refer to TF-M's guide: https://tf-m-user-guide.trustedfirmware.org/docs/integration_guide/services/tfm_secure_partition_addition.html + +When adapting this partition for your own purposes, please change all occurences of "dummy_partition", "DUMMY_PARTITION", "dp", and "DP" to your own partition name. +Also, look through both the secure and non-secure CMakeLists.txt file and make relevant changes, as well as the yaml files inside "partition". + +Building and Running +******************** + +This sample can be built with or without CONFIG_TFM_IPC, since it contains code for both. + +On Target +========= + +Refer to :ref:`tfm_ipc` for detailed instructions. + +On QEMU: +======== + +Refer to :ref:`tfm_ipc` for detailed instructions. + +Sample Output +============= + + .. code-block:: console + + *** Booting Zephyr OS build v2.6.0-rc1-ncs1-1-g58213e91eef1 *** + Digest: be45cb2605bf36bebde684841a28f0fd43c69850a3dce5fedba69928ee3a8991 + Digest: 1452c8f04245d355722fdbfb03c69bcfd380b7dff911a3e425013397251f6a4e + Digest: d3b4349010abb691b9584b6fd6b41ec54596ef7b98d853fb4f5bfa690f50f222 + Digest: 5afbcfede855ca834ff5b4e8a44a32206a51381f3cf52f5001a3241f017ac41a + Digest: 983318380c325099da63de2e7ca57c1630693b28b4754e08817533295dbfcfbb + Status: -135 diff --git a/samples/tfm_integration/tfm_secure_partition/dummy_partition/CMakeLists.txt b/samples/tfm_integration/tfm_secure_partition/dummy_partition/CMakeLists.txt new file mode 100644 index 00000000000..79df6666058 --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/dummy_partition/CMakeLists.txt @@ -0,0 +1,54 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +add_library(tfm_app_rot_partition_dp STATIC) + +target_include_directories(tfm_app_rot_partition_dp + INTERFACE + $ + PRIVATE + ${CMAKE_BINARY_DIR}/dummy_partition +) +target_include_directories(tfm_partitions + INTERFACE + ${CMAKE_BINARY_DIR}/dummy_partition +) + +target_sources(tfm_app_rot_partition_dp + PRIVATE + dummy_partition.c +) + +# The generated sources +target_sources(tfm_app_rot_partition_dp + PRIVATE + $<$: + ${CMAKE_BINARY_DIR}/dummy_partition/auto_generated/intermedia_tfm_dummy_partition.c> +) +target_sources(tfm_partitions + INTERFACE + $<$: + ${CMAKE_BINARY_DIR}/dummy_partition/auto_generated/load_info_tfm_dummy_partition.c> +) + +target_link_libraries(tfm_app_rot_partition_dp + PRIVATE + tfm_secure_api + psa_interface + secure_fw + platform_s + tfm_psa_rot_partition_crypto +) + +target_link_libraries(tfm_partitions + INTERFACE + tfm_app_rot_partition_dp +) + +target_compile_definitions(tfm_partition_defs + INTERFACE + TFM_PARTITION_DUMMY_PARTITION +) diff --git a/samples/tfm_integration/tfm_secure_partition/dummy_partition/dummy_partition.c b/samples/tfm_integration/tfm_secure_partition/dummy_partition/dummy_partition.c new file mode 100644 index 00000000000..71318703d0b --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/dummy_partition/dummy_partition.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "tfm_secure_api.h" +#include "tfm_api.h" + +#define NUM_SECRETS 5 + +struct dp_secret { + uint8_t secret[16]; +}; + +struct dp_secret secrets[NUM_SECRETS] = { + { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} }, + { {1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} }, + { {2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} }, + { {3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} }, + { {4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} }, +}; + +typedef void (*psa_write_callback_t)(void *handle, uint8_t *digest, + uint32_t digest_size); + +static psa_status_t tfm_dp_secret_digest(uint32_t secret_index, + size_t digest_size, size_t *p_digest_size, + psa_write_callback_t callback, void *handle) +{ + uint8_t digest[32]; + psa_status_t status; + + /* Check that secret_index is valid. */ + if (secret_index >= NUM_SECRETS) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Check that digest_size is valid. */ + if (digest_size != sizeof(digest)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = psa_hash_compute(PSA_ALG_SHA_256, secrets[secret_index].secret, + sizeof(secrets[secret_index].secret), digest, + digest_size, p_digest_size); + + if (status != PSA_SUCCESS) { + return status; + } + if (*p_digest_size != digest_size) { + return PSA_ERROR_PROGRAMMER_ERROR; + } + + callback(handle, digest, digest_size); + + return PSA_SUCCESS; +} + +#ifndef TFM_PSA_API + +#include "tfm_memory_utils.h" + +void psa_write_digest(void *handle, uint8_t *digest, uint32_t digest_size) +{ + tfm_memcpy(handle, digest, digest_size); +} + +psa_status_t tfm_dp_secret_digest_req(psa_invec *in_vec, size_t in_len, + psa_outvec *out_vec, size_t out_len) +{ + uint32_t secret_index; + + if ((in_len != 1) || (out_len != 1)) { + /* The number of arguments are incorrect */ + return PSA_ERROR_PROGRAMMER_ERROR; + } + + if (in_vec[0].len != sizeof(secret_index)) { + /* The input argument size is incorrect */ + return PSA_ERROR_PROGRAMMER_ERROR; + } + + secret_index = *((uint32_t *)in_vec[0].base); + + return tfm_dp_secret_digest(secret_index, out_vec[0].len, + &out_vec[0].len, psa_write_digest, + (void *)out_vec[0].base); +} + +#else /* !defined(TFM_PSA_API) */ +#include "psa/service.h" +#include "psa_manifest/tfm_dummy_partition.h" + +typedef psa_status_t (*dp_func_t)(psa_msg_t *); + +static void psa_write_digest(void *handle, uint8_t *digest, + uint32_t digest_size) +{ + psa_write((psa_handle_t)handle, 0, digest, digest_size); +} + +static psa_status_t tfm_dp_secret_digest_ipc(psa_msg_t *msg) +{ + size_t num = 0; + uint32_t secret_index; + + if (msg->in_size[0] != sizeof(secret_index)) { + /* The size of the argument is incorrect */ + return PSA_ERROR_PROGRAMMER_ERROR; + } + + num = psa_read(msg->handle, 0, &secret_index, msg->in_size[0]); + if (num != msg->in_size[0]) { + return PSA_ERROR_PROGRAMMER_ERROR; + } + + return tfm_dp_secret_digest(secret_index, msg->out_size[0], + &msg->out_size[0], psa_write_digest, + (void *)msg->handle); +} + + +static void dp_signal_handle(psa_signal_t signal, dp_func_t pfn) +{ + psa_status_t status; + psa_msg_t msg; + + status = psa_get(signal, &msg); + switch (msg.type) { + case PSA_IPC_CONNECT: + psa_reply(msg.handle, PSA_SUCCESS); + break; + case PSA_IPC_CALL: + status = pfn(&msg); + psa_reply(msg.handle, status); + break; + case PSA_IPC_DISCONNECT: + psa_reply(msg.handle, PSA_SUCCESS); + break; + default: + psa_panic(); + } +} +#endif /* !defined(TFM_PSA_API) */ + +psa_status_t tfm_dp_req_mngr_init(void) +{ +#ifdef TFM_PSA_API + psa_signal_t signals = 0; + + while (1) { + signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK); + if (signals & TFM_DP_SECRET_DIGEST_SIGNAL) { + dp_signal_handle(TFM_DP_SECRET_DIGEST_SIGNAL, + tfm_dp_secret_digest_ipc); + } else { + psa_panic(); + } + } + + return PSA_ERROR_SERVICE_FAILURE; +#else + return PSA_SUCCESS; +#endif +} diff --git a/samples/tfm_integration/tfm_secure_partition/dummy_partition/tfm_dummy_partition.yaml b/samples/tfm_integration/tfm_secure_partition/dummy_partition/tfm_dummy_partition.yaml new file mode 100644 index 00000000000..0b84b84d95e --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/dummy_partition/tfm_dummy_partition.yaml @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2018-2020, Arm Limited. All rights reserved. +# Copyright (c) 2021, Nordic Semiconductor ASA. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- + +{ + "psa_framework_version": 1.0, + "name": "TFM_SP_DP", + "type": "APPLICATION-ROT", + "priority": "NORMAL", + "entry_point": "tfm_dp_req_mngr_init", + "stack_size": "0x800", + + # Service definitions for library mode. + "secure_functions": [ + { + "name": "TFM_DP_SECRET_DIGEST", + "signal": "TFM_DP_SECRET_DIGEST_REQ", + "non_secure_clients": true, + "version": 1, + "version_policy": "STRICT" + } + ], + + # Service definitions for IPC mode. + "services" : [{ + "name": "TFM_DP_SECRET_DIGEST", + "sid": "0xFFFFF001", # Bits [31:12] denote the vendor (change this), + # bits [11:0] are arbitrary at the discretion of the + # vendor. + "non_secure_clients": true, + "version": 1, + "version_policy": "STRICT" + } + ], + + "dependencies": [ + "TFM_CRYPTO" + ] +} diff --git a/samples/tfm_integration/tfm_secure_partition/dummy_partition/tfm_manifest_list.yaml.in b/samples/tfm_integration/tfm_secure_partition/dummy_partition/tfm_manifest_list.yaml.in new file mode 100644 index 00000000000..25ee8d5ea61 --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/dummy_partition/tfm_manifest_list.yaml.in @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2018-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- + +{ + "name": "TF-M secure partition manifests", + "type": "manifest_list", + "version_major": 0, + "version_minor": 1, + "manifest_list": [ + { + "name": "Dummy Partition", + "short_name": "TFM_DP", + "manifest": "${APPLICATION_SOURCE_DIR}/dummy_partition/tfm_dummy_partition.yaml", + "output_path": "${TFM_BINARY_DIR}/dummy_partition", + "tfm_partition_ipc": true, + "conditional": "TFM_PARTITION_DUMMY_PARTITION", + "version_major": 0, + "version_minor": 1, + "linker_pattern": { + "library_list": [ + "*tfm_*partition_dp.*" + ], + } + }, + ] +} diff --git a/samples/tfm_integration/tfm_secure_partition/prj.conf b/samples/tfm_integration/tfm_secure_partition/prj.conf new file mode 100644 index 00000000000..811b3048d10 --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/prj.conf @@ -0,0 +1,7 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BUILD_WITH_TFM=y diff --git a/samples/tfm_integration/tfm_secure_partition/sample.yaml b/samples/tfm_integration/tfm_secure_partition/sample.yaml new file mode 100644 index 00000000000..8161d81e5b2 --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/sample.yaml @@ -0,0 +1,23 @@ +common: + tags: tfm + platform_allow: mps2_an521_nonsecure v2m_musca_s1_nonsecure + nrf5340dk_nrf5340_cpuappns nrf9160dk_nrf9160ns + harness: console + harness_config: + type: multi_line + regex: + - "Digest: be45cb2605bf36bebde684841a28f0fd43c69850a3dce5fedba69928ee3a8991" + - "Digest: 1452c8f04245d355722fdbfb03c69bcfd380b7dff911a3e425013397251f6a4e" + - "Digest: d3b4349010abb691b9584b6fd6b41ec54596ef7b98d853fb4f5bfa690f50f222" + - "Digest: 5afbcfede855ca834ff5b4e8a44a32206a51381f3cf52f5001a3241f017ac41a" + - "Digest: 983318380c325099da63de2e7ca57c1630693b28b4754e08817533295dbfcfbb" + - "Status: -135" +sample: + name: "TFM Secure Partition Sample" + +tests: + sample.tfm.secure_partition: + tags: tfm + sample.tfm.secure_partition.ipc: + tags: tfm + extra_args: "CONFIG_TFM_IPC=y" diff --git a/samples/tfm_integration/tfm_secure_partition/src/dummy_partition.c b/samples/tfm_integration/tfm_secure_partition/src/dummy_partition.c new file mode 100644 index 00000000000..d0e4f4f0e58 --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/src/dummy_partition.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "dummy_partition.h" + +#if defined(CONFIG_TFM_IPC) +#include "psa/client.h" +#include "psa_manifest/sid.h" + +psa_status_t dp_secret_digest(uint32_t secret_index, + void *p_digest, + size_t digest_size) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &secret_index, .len = sizeof(secret_index) }, + }; + + psa_outvec out_vec[] = { + { .base = p_digest, .len = digest_size } + }; + + handle = psa_connect(TFM_DP_SECRET_DIGEST_SID, + TFM_DP_SECRET_DIGEST_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), + out_vec, IOVEC_LEN(out_vec)); + + psa_close(handle); + + return status; +} +#else /* defined(CONFIG_TFM_IPC) */ +psa_status_t dp_secret_digest(uint32_t secret_index, + void *p_digest, + size_t digest_size) +{ + psa_status_t status; + psa_invec in_vec[] = { + { .base = &secret_index, .len = sizeof(secret_index) }, + }; + + psa_outvec out_vec[] = { + { .base = p_digest, .len = digest_size } + }; + + status = tfm_ns_interface_dispatch( + (veneer_fn)tfm_dp_secret_digest_req_veneer, + (uint32_t)in_vec, IOVEC_LEN(in_vec), + (uint32_t)out_vec, IOVEC_LEN(out_vec)); + + return status; +} +#endif /* defined(CONFIG_TFM_IPC) */ diff --git a/samples/tfm_integration/tfm_secure_partition/src/dummy_partition.h b/samples/tfm_integration/tfm_secure_partition/src/dummy_partition.h new file mode 100644 index 00000000000..b31ce897d27 --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/src/dummy_partition.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "tfm_api.h" + +psa_status_t dp_secret_digest(uint32_t secret_index, + void *p_digest, + size_t digest_size); diff --git a/samples/tfm_integration/tfm_secure_partition/src/main.c b/samples/tfm_integration/tfm_secure_partition/src/main.c new file mode 100644 index 00000000000..4e81b74e3bd --- /dev/null +++ b/samples/tfm_integration/tfm_secure_partition/src/main.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "dummy_partition.h" + +void main(void) +{ + uint8_t digest[32]; + + for (int key = 0; key < 6; key++) { + psa_status_t status = dp_secret_digest(key, digest, sizeof(digest)); + + if (status != PSA_SUCCESS) { + printk("Status: %d\n", status); + } else { + printk("Digest: "); + for (int i = 0; i < 32; i++) { + printk("%02x", digest[i]); + } + printk("\n"); + } + } +} diff --git a/west.yml b/west.yml index 947f61bafb3..8333daa6f36 100644 --- a/west.yml +++ b/west.yml @@ -218,7 +218,7 @@ manifest: groups: - debug - name: trusted-firmware-m - revision: 400f58ff53eb1dea5234925e96c5279154515cc7 + revision: 7c88781953ce7146878bd8bd724e175fdbc298c5 path: modules/tee/tf-m/trusted-firmware-m groups: - tee