Create libpsa deployments
Currently we have libts to encapsulate the lower layers (RPC, driver
access). libts only provides low level APIs for accessing the
services and the users have to add a lot of code on top of the libts
APIs to actually use e.g. a PSA crypto service. This commit
encapsulates this code into a reusable library called libpsa in order
to make integration easier for users. It should be used on top of
libts and it provides convenient APIs to access PSA services.
Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
Change-Id: Id6a16fbf4fbd8c9c9af036d06cfbd934b9ae95cf
diff --git a/components/common/libpsa/component.cmake b/components/common/libpsa/component.cmake
new file mode 100644
index 0000000..08e4748
--- /dev/null
+++ b/components/common/libpsa/component.cmake
@@ -0,0 +1,16 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/libpsa-attestation.c"
+ "${CMAKE_CURRENT_LIST_DIR}/libpsa-crypto.c"
+ "${CMAKE_CURRENT_LIST_DIR}/libpsa-its.c"
+ "${CMAKE_CURRENT_LIST_DIR}/libpsa-ps.c"
+ )
diff --git a/components/common/libpsa/libpsa-attestation.c b/components/common/libpsa/libpsa-attestation.c
new file mode 100644
index 0000000..9e795a6
--- /dev/null
+++ b/components/common/libpsa/libpsa-attestation.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <protocols/rpc/common/packed-c/encoding.h>
+#include <psa/initial_attestation.h>
+#include <service/attestation/client/provision/attest_provision_client.h>
+#include <service/attestation/client/psa/iat_client.h>
+#include <service_locator.h>
+#include <stdio.h>
+
+#include "libpsa.h"
+#include "trace.h"
+
+static struct rpc_caller_session *rpc_session;
+static struct service_context *attestation_service_context;
+
+LIBPSA_EXPORTED psa_status_t libpsa_init_attestation_context(const char *service_name)
+{
+ psa_status_t result = PSA_ERROR_GENERIC_ERROR;
+ psa_status_t provision_result = PSA_ERROR_GENERIC_ERROR;
+
+ if (rpc_session || attestation_service_context) {
+ EMSG("The client is already initialized\n");
+ return result;
+ }
+
+ service_locator_init();
+
+ attestation_service_context = service_locator_query(service_name);
+
+ if (!attestation_service_context) {
+ EMSG("Failed to discover service\n");
+ return result;
+ }
+
+ rpc_session = service_context_open(attestation_service_context);
+
+ if (!rpc_session) {
+ EMSG("Failed to open rpc session\n");
+ libpsa_deinit_attestation_context();
+ return result;
+ }
+
+ result = psa_iat_client_init(rpc_session);
+
+ if (result) {
+ EMSG("psa_iat_client_init failed\n");
+ return result;
+ }
+
+ provision_result = attest_provision_client_init(rpc_session);
+
+ /* If external IAK is used this call can fail */
+ if (provision_result)
+ EMSG(
+ "attest_provision_client_init failed. Are you using external IAK key?\n");
+
+ return result;
+}
+
+LIBPSA_EXPORTED void libpsa_deinit_attestation_context(void)
+{
+ psa_iat_client_deinit();
+ attest_provision_client_deinit();
+
+ if (attestation_service_context && rpc_session) {
+ service_context_close(attestation_service_context, rpc_session);
+ rpc_session = NULL;
+ }
+
+ if (attestation_service_context) {
+ service_context_relinquish(attestation_service_context);
+ attestation_service_context = NULL;
+ }
+}
diff --git a/components/common/libpsa/libpsa-crypto.c b/components/common/libpsa/libpsa-crypto.c
new file mode 100644
index 0000000..4a3a10e
--- /dev/null
+++ b/components/common/libpsa/libpsa-crypto.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <protocols/rpc/common/packed-c/encoding.h>
+#include <service/crypto/client/psa/psa_crypto_client.h>
+#include <service_locator.h>
+#include <stdio.h>
+
+#include "libpsa.h"
+#include "trace.h"
+
+static struct rpc_caller_session *rpc_session;
+static struct service_context *crypto_service_context;
+
+LIBPSA_EXPORTED psa_status_t libpsa_init_crypto_context(const char *service_name)
+{
+ psa_status_t result = PSA_ERROR_GENERIC_ERROR;
+
+ if (rpc_session || crypto_service_context) {
+ EMSG("The client is already initialized\n");
+ return result;
+ }
+
+ service_locator_init();
+
+ crypto_service_context = service_locator_query(service_name);
+
+ if (!crypto_service_context) {
+ EMSG("Failed to discover service\n");
+ return result;
+ }
+
+ rpc_session = service_context_open(crypto_service_context);
+
+ if (!rpc_session) {
+ EMSG("Failed to open rpc session\n");
+ libpsa_deinit_crypto_context();
+ return result;
+ }
+
+ result = psa_crypto_client_init(rpc_session);
+
+ if (result)
+ EMSG("psa_crypto_client_init failed\n");
+
+ return result;
+}
+
+LIBPSA_EXPORTED void libpsa_deinit_crypto_context(void)
+{
+ psa_crypto_client_deinit();
+
+ if (crypto_service_context && rpc_session) {
+ service_context_close(crypto_service_context, rpc_session);
+ rpc_session = NULL;
+ }
+
+ if (crypto_service_context) {
+ service_context_relinquish(crypto_service_context);
+ crypto_service_context = NULL;
+ }
+}
diff --git a/components/common/libpsa/libpsa-its.c b/components/common/libpsa/libpsa-its.c
new file mode 100644
index 0000000..3915bfc
--- /dev/null
+++ b/components/common/libpsa/libpsa-its.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <protocols/rpc/common/packed-c/encoding.h>
+#include <service/secure_storage/backend/secure_storage_client/secure_storage_client.h>
+#include <service/secure_storage/frontend/psa/its/its_frontend.h>
+#include <service_locator.h>
+#include <stdio.h>
+
+#include "libpsa.h"
+#include "trace.h"
+
+static struct rpc_caller_session *rpc_session;
+static struct service_context *its_service_context;
+static struct secure_storage_client its_storage_client;
+
+LIBPSA_EXPORTED psa_status_t libpsa_init_its_context(const char *service_name)
+{
+ psa_status_t result = PSA_ERROR_GENERIC_ERROR;
+
+ if (rpc_session || its_service_context) {
+ EMSG("The client is already initialized\n");
+ return result;
+ }
+
+ service_locator_init();
+
+ its_service_context = service_locator_query(service_name);
+
+ if (!its_service_context) {
+ EMSG("Failed to discover service\n");
+ return result;
+ }
+
+ rpc_session = service_context_open(its_service_context);
+
+ if (!rpc_session) {
+ EMSG("Failed to open rpc session\n");
+ libpsa_deinit_its_context();
+ return result;
+ }
+
+ struct storage_backend *its_storage_backend =
+ secure_storage_client_init(&its_storage_client, rpc_session);
+
+ if (!its_storage_backend) {
+ EMSG("Failed to initialize storage backend\n");
+ libpsa_deinit_its_context();
+ return result;
+ }
+
+ result = psa_its_frontend_init(its_storage_backend);
+
+ return result;
+}
+
+LIBPSA_EXPORTED void libpsa_deinit_its_context(void)
+{
+ psa_its_frontend_init(NULL);
+ secure_storage_client_deinit(&its_storage_client);
+
+ if (its_service_context && rpc_session) {
+ service_context_close(its_service_context, rpc_session);
+ rpc_session = NULL;
+ }
+
+ if (its_service_context) {
+ service_context_relinquish(its_service_context);
+ its_service_context = NULL;
+ }
+}
diff --git a/components/common/libpsa/libpsa-ps.c b/components/common/libpsa/libpsa-ps.c
new file mode 100644
index 0000000..01d41d1
--- /dev/null
+++ b/components/common/libpsa/libpsa-ps.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <protocols/rpc/common/packed-c/encoding.h>
+#include <service/secure_storage/backend/secure_storage_client/secure_storage_client.h>
+#include <service/secure_storage/frontend/psa/ps/ps_frontend.h>
+#include <service_locator.h>
+#include <stdio.h>
+
+#include "libpsa.h"
+#include "trace.h"
+
+static struct rpc_caller_session *rpc_session;
+static struct service_context *ps_service_context;
+static struct secure_storage_client ps_storage_client;
+
+LIBPSA_EXPORTED psa_status_t libpsa_init_ps_context(const char *service_name)
+{
+ psa_status_t result = PSA_ERROR_GENERIC_ERROR;
+
+ if (rpc_session || ps_service_context) {
+ EMSG("The client is already initialized\n");
+ return result;
+ }
+
+ service_locator_init();
+
+ ps_service_context = service_locator_query(service_name);
+
+ if (!ps_service_context) {
+ EMSG("Failed to discover service\n");
+ return result;
+ }
+
+ rpc_session = service_context_open(ps_service_context);
+
+ if (!rpc_session) {
+ EMSG("Failed to open rpc session\n");
+ libpsa_deinit_ps_context();
+ return result;
+ }
+
+ struct storage_backend *ps_storage_backend =
+ secure_storage_client_init(&ps_storage_client, rpc_session);
+
+ if (!ps_storage_backend) {
+ EMSG("Failed to initialize storage backend\n");
+ libpsa_deinit_ps_context();
+ return result;
+ }
+
+ result = psa_ps_frontend_init(ps_storage_backend);
+
+ return result;
+}
+
+LIBPSA_EXPORTED void libpsa_deinit_ps_context(void)
+{
+ psa_ps_frontend_init(NULL);
+ secure_storage_client_deinit(&ps_storage_client);
+
+ if (ps_service_context && rpc_session) {
+ service_context_close(ps_service_context, rpc_session);
+ rpc_session = NULL;
+ }
+
+ if (ps_service_context) {
+ service_context_relinquish(ps_service_context);
+ ps_service_context = NULL;
+ }
+}
diff --git a/components/common/libpsa/libpsa.h b/components/common/libpsa/libpsa.h
new file mode 100644
index 0000000..e5a6fa0
--- /dev/null
+++ b/components/common/libpsa/libpsa.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "psa/crypto_types.h"
+#include "psa/initial_attestation.h"
+#include "psa/internal_trusted_storage.h"
+#include "psa/protected_storage.h"
+
+#ifndef LIBPSA_H
+#define LIBPSA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The functions may be exported as a public interface to
+ * a shared library.
+ */
+#ifdef EXPORT_PUBLIC_INTERFACE_LIBPSA
+#define LIBPSA_EXPORTED __attribute__((__visibility__("default")))
+#else
+#define LIBPSA_EXPORTED
+#endif
+
+LIBPSA_EXPORTED psa_status_t libpsa_init_crypto_context(const char *service_name);
+LIBPSA_EXPORTED void libpsa_deinit_crypto_context(void);
+
+LIBPSA_EXPORTED psa_status_t libpsa_init_attestation_context(const char *service_name);
+LIBPSA_EXPORTED void libpsa_deinit_attestation_context(void);
+
+LIBPSA_EXPORTED psa_status_t libpsa_init_its_context(const char *service_name);
+LIBPSA_EXPORTED void libpsa_deinit_its_context(void);
+
+LIBPSA_EXPORTED psa_status_t libpsa_init_ps_context(const char *service_name);
+LIBPSA_EXPORTED void libpsa_deinit_ps_context(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBPSA_H */
diff --git a/deployments/libpsa/arm-linux/CMakeLists.txt b/deployments/libpsa/arm-linux/CMakeLists.txt
new file mode 100644
index 0000000..5fb9f4a
--- /dev/null
+++ b/deployments/libpsa/arm-linux/CMakeLists.txt
@@ -0,0 +1,44 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
+include(../../deployment.cmake REQUIRED)
+
+#-------------------------------------------------------------------------------
+# Options and variables
+#-------------------------------------------------------------------------------
+set(BUILD_SHARED_LIBS On CACHE BOOL "Determine if a shared library is being built.")
+if(NOT BUILD_SHARED_LIBS)
+ message(FATAL_ERROR "Building static library is not yet supported. Call cmake with -DBUILD_SHARED_LIBS=1")
+endif()
+
+#-------------------------------------------------------------------------------
+# The CMakeLists.txt for building the libpsa deployment for arm-linux
+#
+# Used for building the libpsa library for the arm-linux environment. Used for
+# locating and accessing services from a Linux userspace client. Service
+# instances can be located in any supported secure processing environment.
+#-------------------------------------------------------------------------------
+include(${TS_ROOT}/environments/arm-linux/env_shared_lib.cmake)
+project(psa LANGUAGES CXX C)
+
+add_library(psa)
+
+target_include_directories(psa PRIVATE "${TOP_LEVEL_INCLUDE_DIRS}")
+
+#-------------------------------------------------------------------------------
+# For user-specific tracing set to TRACE_LEVEL_NONE and implement:
+# void trace_puts(const char *str)
+#-------------------------------------------------------------------------------
+
+set(TRACE_PREFIX "LIBPSA" CACHE STRING "Trace prefix")
+set(TRACE_LEVEL "TRACE_LEVEL_DEBUG" CACHE STRING "Trace level")
+#-------------------------------------------------------------------------------
+# Extend with components that are common across all deployments of
+# libpsa
+#
+#-------------------------------------------------------------------------------
+include(../libpsa.cmake REQUIRED)
diff --git a/deployments/libpsa/libpsa-import.cmake b/deployments/libpsa/libpsa-import.cmake
new file mode 100644
index 0000000..661b40d
--- /dev/null
+++ b/deployments/libpsa/libpsa-import.cmake
@@ -0,0 +1,114 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------------
+# Import libpsa into a dependent in-tree deployment build. Where another
+# deployment uses libpsa, including this file in the dependent deployment
+# CMake build file allows libpsa to be built and installed into the binary
+# directory of the dependent.
+#-------------------------------------------------------------------------------
+option(CFG_FORCE_PREBUILT_LIBPSA Off)
+# Try to find a pre-build package.
+version_semver_read(FILE "${CMAKE_CURRENT_LIST_DIR}/version.txt" MAJOR _major MINOR _minor PATCH _patch)
+set(_verstring "${_major}.${_minor}.${_patch}")
+
+if (COVERAGE)
+ set(LIBPSA_BUILD_TYPE "DebugCoverage" CACHE STRING "Build type." FORCE)
+endif()
+
+find_package(libpsa "${_verstring}" QUIET PATHS ${CMAKE_CURRENT_BINARY_DIR}/libpsa_install/${TS_ENV}/lib/cmake/libpsa)
+if(NOT libpsa_FOUND)
+ if (CFG_FORCE_PREBUILT_LIBPSA)
+ string(CONCAT _msg "find_package() failed to find the \"libpsa\" package. Please pass -Dlibpsa_ROOT=<full path>"
+ " to cmake, where <full path> is the directory of the libpsaConfig.cmake file, or "
+ " pass -DCMAKE_FIND_ROOT_PATH=<path>, where <path> is the INSTALL_PREFIX used"
+ " when building libpsa. libpsa_ROOT can be set in the environment too."
+ "If you wish to debug the search process pass -DCMAKE_FIND_DEBUG_MODE=ON to cmake.")
+ message(FATAL_ERROR ${_msg})
+ endif()
+ # Set build type, if a specific value is required. This leaves the default value in the hands of the
+ # libpsa deployment being built.
+ if (DEFINED LIBPSA_BUILD_TYPE)
+ set(_libpsa_build_type_arg "-DCMAKE_BUILD_TYPE=${LIBPSA_BUILD_TYPE}")
+ endif()
+
+ # If not successful, build libpsa as a sub-project.
+ execute_process(COMMAND
+ ${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
+ ${CMAKE_COMMAND}
+ ${_libpsa_build_type_arg}
+ -S ${TS_ROOT}/deployments/libpsa/${TS_ENV}
+ -B ${CMAKE_CURRENT_BINARY_DIR}/libpsa
+ RESULT_VARIABLE
+ _exec_error
+ )
+ unset(_libpsa_build_type_arg)
+ if (NOT _exec_error EQUAL 0)
+ message(FATAL_ERROR "Configuring libpsa failed. ${_exec_error}")
+ endif()
+ execute_process(COMMAND
+ ${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
+ ${CMAKE_COMMAND}
+ --build ${CMAKE_CURRENT_BINARY_DIR}/libpsa
+ --parallel ${PROCESSOR_COUNT}
+ RESULT_VARIABLE
+ _exec_error
+ )
+ if (NOT _exec_error EQUAL 0)
+ message(FATAL_ERROR "Installing libpsa failed. ${_exec_error}")
+ endif()
+ execute_process(COMMAND
+ ${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
+ ${CMAKE_COMMAND}
+ --install ${CMAKE_CURRENT_BINARY_DIR}/libpsa
+ --prefix ${CMAKE_CURRENT_BINARY_DIR}/libpsa_install
+ RESULT_VARIABLE
+ _exec_error
+ )
+ if (NOT _exec_error EQUAL 0)
+ message(FATAL_ERROR "Installing libpsa failed. ${_exec_error}")
+ endif()
+
+ install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/libpsa/cmake_install.cmake)
+
+ find_package(libpsa "${_verstring}" QUIET REQUIRED PATHS ${CMAKE_CURRENT_BINARY_DIR}/libpsa_install/${TS_ENV}/lib/cmake/libpsa)
+else()
+ message(STATUS "Using prebuilt libpsa from ${libpsa_DIR}")
+endif()
+
+# Cmake will use the same build type of the imported target as used by the main project. If no mapping is configured and
+# the matching build type is not found, cmake will fall back to any build type. Details of the fall back mechanism are not
+# documented.
+# If a mapping is defined, and the imported target does not define the mapped build type, cmake will treat the library
+# as not found.
+#
+# If LIBPSA_BUILD_TYPE is set and the main project wants to use a specific build type, configure build type mapping to
+# only allow using the requested build type.
+if (DEFINED LIBPSA_BUILD_TYPE)
+ set_target_properties(libpsa::psa PROPERTIES
+ MAP_IMPORTED_CONFIG_DEBUG ${LIBPSA_BUILD_TYPE}
+ MAP_IMPORTED_CONFIG_MINSIZEREL ${LIBPSA_BUILD_TYPE}
+ MAP_IMPORTED_CONFIG_MINSIZWITHDEBINFO ${LIBPSA_BUILD_TYPE}
+ MAP_IMPORTED_CONFIG_RELEASE ${LIBPSA_BUILD_TYPE}
+ MAP_IMPORTED_CONFIG_RELWITHDEBINFO ${LIBPSA_BUILD_TYPE}
+ MAP_IMPORTED_CONFIG_DEBUGCOVERAGE ${LIBPSA_BUILD_TYPE}
+ )
+
+ # Do a manual check and issue a better message than the default one.
+ get_property(_libpsa_build_type TARGET libpsa::psa PROPERTY IMPORTED_CONFIGURATIONS)
+ string(TOUPPER ${LIBPSA_BUILD_TYPE} _uc_libpsa_build_type)
+ if(${_uc_libpsa_build_type} IN_LIST _libpsa_build_type)
+ else()
+ message(FATAL_ERROR "Installed libpsa package does not supports required build type ${LIBPSA_BUILD_TYPE}.")
+ endif()
+ unset(_libpsa_build_type)
+ unset(_uc_libpsa_build_type)
+endif()
+
+# libpsa can not be used without libts, so add the needed dependency.
+include(${TS_ROOT}/deployments/libts/libts-import.cmake)
+target_link_libraries(libpsa::psa INTERFACE libts::ts)
diff --git a/deployments/libpsa/libpsa.cmake b/deployments/libpsa/libpsa.cmake
new file mode 100644
index 0000000..d5ca8e5
--- /dev/null
+++ b/deployments/libpsa/libpsa.cmake
@@ -0,0 +1,107 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------------
+# The base build file shared between deployments of 'libpsa' for different
+# environments. libpsa provides an interface for accessing PSA API-s.
+# Building with each build type results in different postfix for the library.
+# For details, please refer to deployment.cmake.
+#-------------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------------
+# Common API version implemented by all libpsa deployments
+#-------------------------------------------------------------------------------
+version_semver_read(FILE "${CMAKE_CURRENT_LIST_DIR}/version.txt"
+ MAJOR _major MINOR _minor PATCH _patch)
+set_target_properties(psa PROPERTIES VERSION "${_major}.${_minor}.${_patch}")
+set_target_properties(psa PROPERTIES SOVERSION "${_major}")
+unset(_major)
+unset(_minor)
+unset(_patch)
+
+add_library(libpsa::psa ALIAS psa)
+
+if (COVERAGE)
+ set(LIBPSA_BUILD_TYPE "DebugCoverage" CACHE STRING "Build type." FORCE)
+endif()
+
+#-------------------------------------------------------------------------------
+# Use libts for locating and accessing services. An appropriate version of
+# libts will be imported for the environment in which service tests are
+# deployed.
+#-------------------------------------------------------------------------------
+include(${TS_ROOT}/deployments/libts/libts-import.cmake)
+target_link_libraries(psa PUBLIC libts::ts)
+
+#-------------------------------------------------------------------------------
+# Components that are common across all deployments
+#
+#-------------------------------------------------------------------------------
+
+add_components(
+ TARGET "psa"
+ BASE_DIR ${TS_ROOT}
+ COMPONENTS
+ "environments/${TS_ENV}"
+ "components/common/utils"
+ "components/common/trace"
+ "components/common/libpsa"
+ "components/common/tlv"
+ "components/service/common/include"
+ "components/service/common/client"
+ "components/service/crypto/include"
+ "components/service/crypto/client/psa"
+ "components/service/attestation/include"
+ "components/service/attestation/client/psa"
+ "components/service/attestation/client/provision"
+ "components/service/secure_storage/include"
+ "components/service/secure_storage/frontend/psa/its"
+ "components/service/secure_storage/frontend/psa/ps"
+ "components/service/secure_storage/backend/secure_storage_client"
+)
+
+#-------------------------------------------------------------------------------
+# Define public interfaces for library
+#
+#-------------------------------------------------------------------------------
+
+# Enable exporting interface symbols for library public interface
+target_compile_definitions(psa PRIVATE
+ EXPORT_PUBLIC_INTERFACE_LIBPSA
+ EXPORT_PUBLIC_INTERFACE_PSA_CRYPTO
+ EXPORT_PUBLIC_INTERFACE_PSA_ATTEST
+ EXPORT_PUBLIC_INTERFACE_PSA_ITS
+ EXPORT_PUBLIC_INTERFACE_PSA_PS
+)
+
+#-------------------------------------------------------------------------------
+# Export the library and the corresponding public interface header files
+#
+#-------------------------------------------------------------------------------
+include(${TS_ROOT}/tools/cmake/common/ExportLibrary.cmake REQUIRED)
+
+# Exports library information in preparation for install
+export_library(
+ TARGET "psa"
+ LIB_NAME "libpsa"
+ PKG_CONFIG_FILE "${CMAKE_CURRENT_LIST_DIR}/libpsaConfig.cmake.in"
+)
+
+install(DIRECTORY "${TS_ROOT}/components/service/crypto/include"
+ DIRECTORY "${TS_ROOT}/components/service/attestation/include"
+ DIRECTORY "${TS_ROOT}/components/service/secure_storage/include"
+ DESTINATION "${TS_ENV}"
+ FILES_MATCHING PATTERN "*.h"
+)
+
+install(FILES "${TS_ROOT}/components/service/common/include/psa/error.h"
+ DESTINATION ${TS_ENV}/include/psa
+)
+
+install(FILES "${TS_ROOT}/components/common/libpsa/libpsa.h"
+ DESTINATION ${TS_ENV}/include
+)
diff --git a/deployments/libpsa/libpsaConfig.cmake.in b/deployments/libpsa/libpsaConfig.cmake.in
new file mode 100644
index 0000000..710411b
--- /dev/null
+++ b/deployments/libpsa/libpsaConfig.cmake.in
@@ -0,0 +1,9 @@
+#
+# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+@PACKAGE_INIT@
+
+include("${CMAKE_CURRENT_LIST_DIR}/libpsaTargets.cmake")
diff --git a/deployments/libpsa/linux-pc/CMakeLists.txt b/deployments/libpsa/linux-pc/CMakeLists.txt
new file mode 100644
index 0000000..7d45a36
--- /dev/null
+++ b/deployments/libpsa/linux-pc/CMakeLists.txt
@@ -0,0 +1,44 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
+include(../../deployment.cmake REQUIRED)
+
+#-------------------------------------------------------------------------------
+# Options and variables
+#-------------------------------------------------------------------------------
+set(BUILD_SHARED_LIBS On CACHE BOOL "Determine if a shared library is being built.")
+if(NOT BUILD_SHARED_LIBS)
+ message(FATAL_ERROR "Building static library is not yet supported. Call cmake with -DBUILD_SHARED_LIBS=1")
+endif()
+
+#-------------------------------------------------------------------------------
+# The CMakeLists.txt for building the libpsa deployment for arm-linux
+#
+# Used for building the libpsa library for the arm-linux environment. Used for
+# locating and accessing services from a Linux userspace client. Service
+# instances can be located in any supported secure processing environment.
+#-------------------------------------------------------------------------------
+include(${TS_ROOT}/environments/linux-pc/env_shared_lib.cmake)
+project(psa LANGUAGES CXX C)
+
+add_library(psa)
+
+target_include_directories(psa PRIVATE "${TOP_LEVEL_INCLUDE_DIRS}")
+
+#-------------------------------------------------------------------------------
+# For user-specific tracing set to TRACE_LEVEL_NONE and implement:
+# void trace_puts(const char *str)
+#-------------------------------------------------------------------------------
+
+set(TRACE_PREFIX "LIBPSA" CACHE STRING "Trace prefix")
+set(TRACE_LEVEL "TRACE_LEVEL_DEBUG" CACHE STRING "Trace level")
+#-------------------------------------------------------------------------------
+# Extend with components that are common across all deployments of
+# libpsa
+#
+#-------------------------------------------------------------------------------
+include(../libpsa.cmake REQUIRED)
diff --git a/deployments/libpsa/version.txt b/deployments/libpsa/version.txt
new file mode 100644
index 0000000..afaf360
--- /dev/null
+++ b/deployments/libpsa/version.txt
@@ -0,0 +1 @@
+1.0.0
\ No newline at end of file
diff --git a/tools/b-test/test_data.yaml b/tools/b-test/test_data.yaml
index 1fd72ed..d9764ed 100644
--- a/tools/b-test/test_data.yaml
+++ b/tools/b-test/test_data.yaml
@@ -85,6 +85,16 @@
src: "$TS_ROOT/deployments/internal-trusted-storage/config/shared-flash-opteesp"
params:
- "-GUnix Makefiles"
+ - name: "libpsa-arm-linux"
+ src: "$TS_ROOT/deployments/libpsa/arm-linux"
+ os_id : "GNU/Linux"
+ params:
+ - "-GUnix Makefiles"
+ - name: "libpsa-linux-pc"
+ src: "$TS_ROOT/deployments/libpsa/linux-pc"
+ os_id : "GNU/Linux"
+ params:
+ - "-GUnix Makefiles"
- name: "libsp-linux-pc"
src: "$TS_ROOT/deployments/libsp/linux-pc"
os_id : "GNU/Linux"