samples: Add TF-M sample for custom secure partitions
The sample implements a dummy ARoT (Application Root of Trust) partition in TF-M and calls it from the app. Signed-off-by: Øyvind Rønningstad <oyvind.ronningstad@nordicsemi.no> Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
parent
3db41349f5
commit
449cb60815
13 changed files with 522 additions and 1 deletions
|
@ -1,3 +1,5 @@
|
|||
.. _tfm_build_system:
|
||||
|
||||
TF-M Build System
|
||||
#################
|
||||
|
||||
|
|
36
samples/tfm_integration/tfm_secure_partition/CMakeLists.txt
Normal file
36
samples/tfm_integration/tfm_secure_partition/CMakeLists.txt
Normal file
|
@ -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
|
||||
)
|
51
samples/tfm_integration/tfm_secure_partition/README.rst
Normal file
51
samples/tfm_integration/tfm_secure_partition/README.rst
Normal file
|
@ -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
|
|
@ -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
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
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
|
||||
$<$<BOOL:${TFM_PSA_API}>:
|
||||
${CMAKE_BINARY_DIR}/dummy_partition/auto_generated/intermedia_tfm_dummy_partition.c>
|
||||
)
|
||||
target_sources(tfm_partitions
|
||||
INTERFACE
|
||||
$<$<BOOL:${TFM_PSA_API}>:
|
||||
${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
|
||||
)
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <psa/crypto.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#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
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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.*"
|
||||
],
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
7
samples/tfm_integration/tfm_secure_partition/prj.conf
Normal file
7
samples/tfm_integration/tfm_secure_partition/prj.conf
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
# Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
CONFIG_BUILD_WITH_TFM=y
|
23
samples/tfm_integration/tfm_secure_partition/sample.yaml
Normal file
23
samples/tfm_integration/tfm_secure_partition/sample.yaml
Normal file
|
@ -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"
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <tfm_veneers.h>
|
||||
#include <tfm_ns_interface.h>
|
||||
|
||||
#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) */
|
|
@ -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);
|
30
samples/tfm_integration/tfm_secure_partition/src/main.c
Normal file
30
samples/tfm_integration/tfm_secure_partition/src/main.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <tfm_veneers.h>
|
||||
#include <tfm_ns_interface.h>
|
||||
|
||||
#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");
|
||||
}
|
||||
}
|
||||
}
|
2
west.yml
2
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue