DPE: Support host build
If `-DHOST_BUILD=ON` is added to the CMake command line
then the DPE library will be built as a stand-alone
Linux program. Not tested on Windows.
It allows the rapid development, build and test cycles
of the DPE library in a native environment without
the need to execute the code on FVP.
Change-Id: I4923c2aba9636d96bfe1aca4e7d5b731270382fa
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
diff --git a/partitions/dice_protection_environment/test/host/CMakeLists.txt b/partitions/dice_protection_environment/test/host/CMakeLists.txt
new file mode 100644
index 0000000..4576d71
--- /dev/null
+++ b/partitions/dice_protection_environment/test/host/CMakeLists.txt
@@ -0,0 +1,132 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_minimum_required(VERSION 3.15)
+
+Project("DPE Host Build" LANGUAGES C)
+
+set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
+set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
+set(ENABLE_TESTING OFF)
+set(ENABLE_PROGRAMS OFF)
+set(MBEDTLS_FATAL_WARNINGS OFF)
+set(ENABLE_DOCS OFF)
+set(INSTALL_MBEDTLS_HEADERS OFF)
+
+############################### Crypto Library #################################
+
+add_subdirectory(${MBEDCRYPTO_PATH} mbedtls)
+
+############################### QCBOR Library ##################################
+
+add_subdirectory(${QCBOR_PATH} qcbor)
+
+# Entirely disable the floating-point support
+target_compile_definitions(qcbor
+ PRIVATE
+ QCBOR_DISABLE_FLOAT_HW_USE
+ QCBOR_OPT_DISABLE_FLOAT_PREFERRED
+ QCBOR_OPT_DISABLE_FLOAT_ALL
+)
+
+############################### T_COSE Library #################################
+
+set(T_COSE_PATH ${TFM_PATH}/lib/ext/t_cose)
+
+# Empty target just to make build working
+add_library(tfm_config INTERFACE)
+
+# Empty target just to make build working
+add_library(psa_crypto_config INTERFACE)
+
+include(${T_COSE_PATH}/tfm_t_cose.cmake)
+
+add_library(t_cose STATIC EXCLUDE_FROM_ALL)
+
+target_link_libraries(t_cose
+ PUBLIC
+ tfm_t_cose_defs
+ PRIVATE
+ tfm_t_cose_common
+ qcbor
+ mbedtls
+)
+
+############################### DPE Library ####################################
+
+add_library(dpe_lib STATIC EXCLUDE_FROM_ALL)
+
+target_sources(dpe_lib
+ PUBLIC
+ ../../interface/src/dpe_cmd_encode.c
+ PRIVATE
+ ../../dpe_certificate.c
+ ../../dpe_cmd_decode.c
+ ../../dpe_context_mngr.c
+ ../../dpe_crypto_interface.c
+ ../../dpe_log.c
+)
+
+target_include_directories(dpe_lib
+ PUBLIC
+ ../../interface/include
+ ../..
+ ${TFM_PATH}/platform/ext/target/arm/rse/common # platform_locality.h
+ ${TFM_PATH}/platform/ext/target/arm/rse/common/dpe # dpe_plat.h
+ ${TFM_PATH}/secure_fw/partitions/lib/runtime/include # tfm_sp_log.h
+ PRIVATE
+ ${TFM_PATH}/secure_fw/include # array.h
+
+)
+
+# Linked due to the headers
+target_link_libraries(dpe_lib
+ PUBLIC
+ t_cose
+ mbedtls
+ qcbor
+)
+
+target_compile_definitions(dpe_lib
+ PUBLIC
+ TFM_PARTITION_LOG_LEVEL=${TFM_PARTITION_LOG_LEVEL}
+ PRIVATE
+ DPE_TEST_MODE
+)
+
+############################### DPE Host App ###################################
+
+add_executable(dpe_host)
+
+target_sources(dpe_host
+ PRIVATE
+ ./cmd.c
+ ./main.c
+ ./plat.c
+ ./root_keys.c
+ ./client.c
+)
+
+target_link_libraries(dpe_host
+ PUBLIC
+ dpe_lib
+)
+
+target_include_directories(dpe_host
+ PRIVATE
+ .
+)
+
+target_compile_definitions(dpe_host
+ PRIVATE
+)
+
+target_compile_options(dpe_host
+ PRIVATE
+ -Og
+ -g
+)
diff --git a/partitions/dice_protection_environment/test/host/DeriveContext.cbor b/partitions/dice_protection_environment/test/host/DeriveContext.cbor
new file mode 100644
index 0000000..64de303
--- /dev/null
+++ b/partitions/dice_protection_environment/test/host/DeriveContext.cbor
Binary files differ
diff --git a/partitions/dice_protection_environment/test/host/client.c b/partitions/dice_protection_environment/test/host/client.c
new file mode 100644
index 0000000..ec96c70
--- /dev/null
+++ b/partitions/dice_protection_environment/test/host/client.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "dpe_client.h"
+#include "dpe_cmd_decode.h"
+
+#define CLIENT_ID_NS -1
+
+int32_t dpe_client_call(const char *cmd_input, size_t cmd_input_size,
+ char *cmd_output, size_t *cmd_output_size)
+{
+ int32_t err;
+
+ err = dpe_command_decode(CLIENT_ID_NS,
+ cmd_input, cmd_input_size,
+ cmd_output, cmd_output_size);
+
+ return err;
+}
diff --git a/partitions/dice_protection_environment/test/host/cmd.c b/partitions/dice_protection_environment/test/host/cmd.c
new file mode 100644
index 0000000..2256749
--- /dev/null
+++ b/partitions/dice_protection_environment/test/host/cmd.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dice_protection_environment.h"
+#include "dpe_client.h"
+#include "dpe_context_mngr.h"
+#include "dpe_cmd_decode.h"
+#include "dpe_cmd_encode.h"
+
+#include "cmd.h"
+#include "root_keys.h"
+
+#include "tfm_sp_log.h"
+
+#define CLIENT_ID_NS -1
+
+static void print_buf(const unsigned char *buf, size_t size)
+{
+ size_t i;
+
+ if (buf != NULL) {
+ for (i = 0; i < size; ++i) {
+ if ((i & 0xF) == 0) {
+ LOG_DBGFMT("\r\n");
+ }
+ if (buf[i] < 0x10) {
+ LOG_DBGFMT(" 0%x", buf[i]);
+ } else {
+ LOG_DBGFMT(" %x", buf[i]);
+ }
+ }
+ }
+ LOG_DBGFMT("\r\n");
+ LOG_DBGFMT("\r\n");
+}
+
+static dpe_error_t
+cbor_cmd(const char *cmd_in_buf, size_t cmd_in_size, int *context_handle)
+{
+ char cmd_out_buf[2 * 4096];
+ size_t cmd_out_size = sizeof(cmd_out_buf);
+ dpe_error_t err;
+
+ (void)context_handle;
+
+ LOG_DBGFMT("DPE request (%ld):\n", cmd_in_size);
+ print_buf(cmd_in_buf, cmd_in_size);
+
+ err = dpe_command_decode(CLIENT_ID_NS,
+ cmd_in_buf, cmd_in_size,
+ cmd_out_buf, &cmd_out_size);
+
+ LOG_DBGFMT("DPE response (%ld):\n", cmd_out_size);
+ print_buf(cmd_out_buf, cmd_out_size);
+
+ return err;
+}
+
+/*
+ * DPE Library Init:
+ * - crypto_lib
+ * - platform
+ * - context manager
+ */
+void dpe_lib_init(int *context_handle)
+{
+ int ret;
+ dpe_error_t err;
+
+ ret = psa_crypto_init();
+ if (ret != 0) {
+ printf("ERROR: Crypto init failed! (%d)\n", ret);
+ exit(1);
+ }
+
+ ret = register_rot_cdi();
+ if (ret != 0) {
+ printf("ERROR: RoT CDI registration failed! (%d)\n", ret);
+ exit(1);
+ }
+
+ ret = register_root_attest_key();
+ if (ret != 0) {
+ printf("ERROR: Root attest key registration failed! (%d)\n", ret);
+ exit(1);
+ }
+
+ err = initialise_context_mngr(context_handle);
+ if (err != DPE_NO_ERROR) {
+ printf("ERROR: Context manager init failed (%d)\n", err);
+ exit(1);
+ }
+}
+
+dpe_error_t exec_dpe_cmd(enum cmd cmd, const char *cmd_in_buf,
+ size_t cmd_in_size, int *context_handle)
+{
+ switch(cmd) {
+ case CBOR:
+ return cbor_cmd(cmd_in_buf, cmd_in_size, context_handle);
+ default:
+ printf("ERROR: Unknown command\n");
+ exit(1);
+ }
+}
diff --git a/partitions/dice_protection_environment/test/host/cmd.h b/partitions/dice_protection_environment/test/host/cmd.h
new file mode 100644
index 0000000..0c6ad86
--- /dev/null
+++ b/partitions/dice_protection_environment/test/host/cmd.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _CMD_H_
+#define _CMD_H_
+
+enum cmd {
+ CBOR, /* CBOR encoded */
+ MAX_CMD_VAL
+};
+
+int exec_dpe_cmd(enum cmd cmd, const char *cmd_in_buf, size_t cmd_in_size, int *context_handle);
+
+void dpe_lib_init(int *context_handle);
+
+#endif /* _CMD_H_ */
diff --git a/partitions/dice_protection_environment/test/host/main.c b/partitions/dice_protection_environment/test/host/main.c
new file mode 100644
index 0000000..9a72951
--- /dev/null
+++ b/partitions/dice_protection_environment/test/host/main.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dice_protection_environment.h"
+#include "tfm_sp_log.h"
+
+#include "cmd.h"
+
+static int read_cmd(const char path[], char *cmd_buf, size_t *cmd_buf_size)
+{
+ FILE *fd;
+ size_t cmd_size;
+
+ if ((fd = fopen(path, "r")) == NULL) {
+ printf("ERROR: File (%s) cannot be opened.\n", path);
+ return -1;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ cmd_size = ftell(fd);
+ rewind(fd);
+
+ if (*cmd_buf_size < cmd_size) {
+ printf("ERROR: cmd_buf is too small\n");
+ return -1;
+ }
+
+ for (size_t i = 0; i < cmd_size; ++i) {
+ cmd_buf[i] = fgetc(fd);
+ }
+ *cmd_buf_size = cmd_size;
+
+ fclose(fd);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int context_handle;
+ int ret;
+ char cmd_in_buf[4096] = {0};
+ size_t cmd_in_size = sizeof(cmd_in_buf);
+ dpe_error_t err;
+
+ dpe_lib_init(&context_handle);
+
+ if (argc == 2) {
+ ret = read_cmd(argv[1], cmd_in_buf, &cmd_in_size);
+ if (ret < 0) {
+ exit(1);
+ }
+
+ err = exec_dpe_cmd(CBOR, cmd_in_buf, cmd_in_size, &context_handle);
+ if (err != DPE_NO_ERROR) {
+ printf("DPE command decode/execution failed (%d)\n", ret);
+ exit(1);
+ }
+ } else {
+ printf("Wrong number of input params! It must be 1!\n");
+ exit(1);
+ }
+
+ exit(0);
+}
diff --git a/partitions/dice_protection_environment/test/host/plat.c b/partitions/dice_protection_environment/test/host/plat.c
new file mode 100644
index 0000000..3be08bd
--- /dev/null
+++ b/partitions/dice_protection_environment/test/host/plat.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+
+#include "dpe_plat.h"
+#include "tfm_sp_log.h"
+
+extern psa_key_id_t rot_cdi_id;
+extern psa_key_id_t root_attest_key_id;
+
+psa_key_id_t dpe_plat_get_rot_cdi_key_id(void)
+{
+ return rot_cdi_id;
+}
+
+psa_key_id_t dpe_plat_get_root_attest_key_id(void)
+{
+ return root_attest_key_id;
+}
+
+
+int dpe_plat_share_context_with_ap(int ctx_handle)
+{
+ return 0;
+}
+
+
+int32_t dpe_plat_get_client_locality(int32_t client_id)
+{
+ return 0;
+}
diff --git a/partitions/dice_protection_environment/test/host/root_keys.c b/partitions/dice_protection_environment/test/host/root_keys.c
new file mode 100644
index 0000000..83e09c1
--- /dev/null
+++ b/partitions/dice_protection_environment/test/host/root_keys.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa/crypto.h"
+
+/*
+ * The DPE implementation assumes that the runtime has no access to the UDS and
+ * a previous boot stage already done the RoT CDI derivation from the UDS.
+ * Therefore when the RoT certificate is created the RoT CDI derivation step is
+ * skipped. The RoT CDI is assumed to be already known by the Crypto service.
+ * It can be referenced by a handle: rot_cdi_id.
+ */
+psa_key_id_t rot_cdi_id = PSA_KEY_ID_NULL;
+
+/*
+ * Use this hard coded data as the RoT CDI. In normal operation this value is
+ * derived by BL1_1.
+ */
+static const char rot_cdi[] = {
+ 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+ 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+ 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+ 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+};
+
+/* In normal operation this is done by Crypto service init */
+int register_rot_cdi(void)
+{
+ psa_status_t status;
+ psa_key_attributes_t attr = psa_key_attributes_init();
+ psa_algorithm_t algorithm = PSA_ALG_HKDF(PSA_ALG_SHA_256);
+
+ /* Setup the key policy */
+ psa_set_key_bits(&attr, 256);
+ psa_set_key_algorithm(&attr, algorithm);
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
+ psa_set_key_type(&attr, PSA_KEY_TYPE_DERIVE);
+
+ status = psa_import_key(&attr, rot_cdi, sizeof(rot_cdi), &rot_cdi_id);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ return PSA_SUCCESS;
+}
+
+psa_key_id_t root_attest_key_id = PSA_KEY_ID_NULL;
+
+/* The RoT certificate is signed by the root attestation key. */
+static const char root_attest_key[] = {
+ 0xA9, 0xB4, 0x54, 0xB2, 0x6D, 0x6F, 0x90, 0xA4,
+ 0xEA, 0x31, 0x19, 0x35, 0x64, 0xCB, 0xA9, 0x1F,
+ 0xEC, 0x6F, 0x9A, 0x00, 0x2A, 0x7D, 0xC0, 0x50,
+ 0x4B, 0x92, 0xA1, 0x93, 0x71, 0x34, 0x58, 0x5F,
+};
+
+/* In normal operation this is done by Crypto service init */
+int register_root_attest_key(void)
+{
+ psa_status_t status;
+ psa_key_attributes_t attr = psa_key_attributes_init();
+ psa_algorithm_t algorithm = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
+ psa_key_type_t type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
+
+ /* Setup the key policy */
+ psa_set_key_type(&attr, type);
+ psa_set_key_algorithm(&attr, algorithm);
+ psa_set_key_bits(&attr, 256);
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT);
+
+ status = psa_import_key(&attr, root_attest_key, sizeof(root_attest_key),
+ &root_attest_key_id);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ return PSA_SUCCESS;
+}
diff --git a/partitions/dice_protection_environment/test/host/root_keys.h b/partitions/dice_protection_environment/test/host/root_keys.h
new file mode 100644
index 0000000..6e6171e
--- /dev/null
+++ b/partitions/dice_protection_environment/test/host/root_keys.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _ROOT_KEYS_H_
+#define _ROOT_KEYS_H_
+
+int register_rot_cdi(void);
+int register_root_attest_key(void);
+
+#endif /* _ROOT_KEYS_H_ */