Attest: Add a SP to support test to get IAK public key
Add a test service to support tests to get Initial Attestation public
key.
In some cases, Initial Attestation public key can only be read in
runtime. This test service provides an interface for tests to read the
public key to verify the IAT in tests.
Signed-off-by: David Hu <david.hu@arm.com>
Change-Id: I6f910f9f05becbf1e2e56d1fd421ea013fc885e2
diff --git a/test/suites/attestation/CMakeLists.txt b/test/suites/attestation/CMakeLists.txt
index 8c1076d..7b375a1 100644
--- a/test/suites/attestation/CMakeLists.txt
+++ b/test/suites/attestation/CMakeLists.txt
@@ -38,6 +38,7 @@
DOMAIN_NS=1
$<$<CONFIG:Debug>:INCLUDE_TEST_CODE>
$<$<BOOL:${SYMMETRIC_INITIAL_ATTESTATION}>:SYMMETRIC_INITIAL_ATTESTATION>
+ $<$<AND:$<BOOL:${ATTEST_TEST_GET_PUBLIC_KEY}>,$<NOT:$<BOOL:${SYMMETRIC_INITIAL_ATTESTATION}>>>:ATTEST_TEST_GET_PUBLIC_KEY>
)
target_link_libraries(tfm_test_suite_attestation_ns
@@ -49,6 +50,7 @@
tfm_attestation_defs
tfm_boot_status
platform_ns
+ $<$<AND:$<BOOL:${ATTEST_TEST_GET_PUBLIC_KEY}>,$<NOT:$<BOOL:${SYMMETRIC_INITIAL_ATTESTATION}>>>:tfm_psa_rot_partition_attest_test_service_defs>
)
target_link_libraries(tfm_ns_tests
@@ -81,6 +83,7 @@
PRIVATE
$<$<CONFIG:Debug>:INCLUDE_TEST_CODE>
$<$<BOOL:${SYMMETRIC_INITIAL_ATTESTATION}>:SYMMETRIC_INITIAL_ATTESTATION>
+ $<$<AND:$<BOOL:${ATTEST_TEST_GET_PUBLIC_KEY}>,$<NOT:$<BOOL:${SYMMETRIC_INITIAL_ATTESTATION}>>>:ATTEST_TEST_GET_PUBLIC_KEY>
)
target_link_libraries(tfm_test_suite_attestation_s
@@ -92,6 +95,7 @@
tfm_boot_status
$<$<NOT:$<BOOL:${FORWARD_PROT_MSG}>>:tfm_psa_rot_partition_crypto>
platform_s
+ $<$<AND:$<BOOL:${ATTEST_TEST_GET_PUBLIC_KEY}>,$<NOT:$<BOOL:${SYMMETRIC_INITIAL_ATTESTATION}>>>:tfm_psa_rot_partition_attest_test_service_defs>
)
target_link_libraries(tfm_s_tests
diff --git a/test/suites/attestation/attest_public_key.c b/test/suites/attestation/attest_public_key.c
index f942308..ed65d83 100644
--- a/test/suites/attestation/attest_public_key.c
+++ b/test/suites/attestation/attest_public_key.c
@@ -9,6 +9,9 @@
#include "psa/crypto.h"
#include <stdint.h>
#include "attest.h"
+#ifdef ATTEST_TEST_GET_PUBLIC_KEY
+#include "tfm_attest_test_service_api.h"
+#endif
/*!
* \def ECC_CURVE_SECP256R1_PUBLIC_KEY_LENGTH
@@ -18,10 +21,6 @@
*/
#define ECC_CURVE_SECP256R1_PUBLIC_KEY_LENGTH (1 + 2 * PSA_BITS_TO_BYTES(256))
-extern const psa_ecc_family_t initial_attest_curve_type;
-extern const uint8_t initial_attest_pub_key[];
-extern const uint32_t initial_attest_pub_key_size;
-
/*!
* \var public_key_registered
*
@@ -30,11 +29,64 @@
*/
static uint32_t public_key_registered = 0;
+static psa_status_t attest_import_public_key(psa_key_handle_t *public_key,
+ const uint8_t *key_buf,
+ size_t ken_len,
+ psa_ecc_family_t curve_type)
+{
+ psa_key_attributes_t key_attributes = psa_key_attributes_init();
+
+ /* Setup the key usage flags, algorithm and key type for public key */
+ psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY);
+ psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve_type));
+
+ /* Register public key to Crypto service */
+ return psa_import_key(&key_attributes, key_buf, ken_len, public_key);
+}
+
+#ifdef ATTEST_TEST_GET_PUBLIC_KEY
enum psa_attest_err_t
attest_register_initial_attestation_public_key(psa_key_handle_t *public_key)
{
psa_status_t res;
- psa_key_attributes_t key_attributes = psa_key_attributes_init();
+ uint8_t public_key_buff[ECC_CURVE_SECP256R1_PUBLIC_KEY_LENGTH] = {0};
+ size_t public_key_len;
+ psa_ecc_family_t ecc_curve;
+
+ /* Public key should be unregistered at this point */
+ if (public_key_registered != 0) {
+ return PSA_ATTEST_ERR_GENERAL;
+ }
+
+ res = tfm_initial_attest_get_public_key(public_key_buff,
+ sizeof(public_key_buff),
+ &public_key_len,
+ &ecc_curve);
+ if (res != PSA_SUCCESS) {
+ return PSA_ATTEST_ERR_GENERAL;
+ }
+
+ res = attest_import_public_key(public_key, public_key_buff, public_key_len,
+ ecc_curve);
+ if (res != PSA_SUCCESS) {
+ return PSA_ATTEST_ERR_GENERAL;
+ }
+
+ public_key_registered = 1;
+
+ return PSA_ATTEST_ERR_SUCCESS;
+}
+
+#else /* ATTEST_TEST_GET_PUBLIC_KEY */
+extern const psa_ecc_family_t initial_attest_curve_type;
+extern const uint8_t initial_attest_pub_key[];
+extern const uint32_t initial_attest_pub_key_size;
+
+enum psa_attest_err_t
+attest_register_initial_attestation_public_key(psa_key_handle_t *public_key)
+{
+ psa_status_t res;
/* Public key should be unregistered at this point */
if (public_key_registered != 0) {
@@ -49,18 +101,9 @@
return PSA_ATTEST_ERR_GENERAL;
}
- /* Setup the key usage flags, algorithm and key type for public key */
- psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY);
- psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
- psa_set_key_type(&key_attributes,
- PSA_KEY_TYPE_ECC_PUBLIC_KEY(initial_attest_curve_type));
-
- /* Register public key to Crypto service */
- res = psa_import_key(&key_attributes,
- (const uint8_t *)initial_attest_pub_key,
- initial_attest_pub_key_size,
- public_key);
-
+ res = attest_import_public_key(public_key, initial_attest_pub_key,
+ initial_attest_pub_key_size,
+ initial_attest_curve_type);
if (res != PSA_SUCCESS) {
return PSA_ATTEST_ERR_GENERAL;
}
@@ -69,6 +112,7 @@
return PSA_ATTEST_ERR_SUCCESS;
}
+#endif /* ATTEST_TEST_GET_PUBLIC_KEY */
enum psa_attest_err_t
attest_unregister_initial_attestation_public_key(psa_key_handle_t public_key)
diff --git a/test/test_services/CMakeLists.txt b/test/test_services/CMakeLists.txt
index 4d905ee..0e2740c 100644
--- a/test/test_services/CMakeLists.txt
+++ b/test/test_services/CMakeLists.txt
@@ -56,3 +56,4 @@
add_subdirectory(tfm_ipc_service)
add_subdirectory(tfm_ipc_client)
endif()
+add_subdirectory(tfm_attest_test_service)
diff --git a/test/test_services/tfm_attest_test_service/CMakeLists.txt b/test/test_services/tfm_attest_test_service/CMakeLists.txt
new file mode 100644
index 0000000..0674e78
--- /dev/null
+++ b/test/test_services/tfm_attest_test_service/CMakeLists.txt
@@ -0,0 +1,120 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_policy(SET CMP0079 NEW)
+
+if (NOT TFM_PARTITION_INITIAL_ATTESTATION AND NOT FORWARD_PROT_MSG)
+ return()
+endif()
+
+# This initial attestation test service provide a secure API to enable tests to
+# fetch Initial Attestation public key.
+# This test service shall be only enabled when the public key can only be
+# fetched in runtime.
+if (NOT ATTEST_TEST_GET_PUBLIC_KEY OR SYMMETRIC_INITIAL_ATTESTATION)
+ return()
+endif()
+
+add_library(tfm_psa_rot_partition_attest_test_service STATIC)
+
+target_sources(tfm_psa_rot_partition_attest_test_service
+ PRIVATE
+ ./tfm_attest_test_service.c
+)
+
+# The generated sources
+target_sources(tfm_psa_rot_partition_attest_test_service
+ PRIVATE
+ $<$<BOOL:${TFM_PSA_API}>:
+ ${CMAKE_BINARY_DIR}/generated/test_services/tfm_attest_test_service/auto_generated/intermedia_tfm_attest_test_service.c>
+)
+
+target_sources(tfm_partitions
+ INTERFACE
+ $<$<BOOL:${TFM_PSA_API}>:
+ ${CMAKE_BINARY_DIR}/generated/test_services/tfm_attest_test_service/auto_generated/load_info_tfm_attest_test_service.c>
+)
+
+# Set include directory
+target_include_directories(tfm_psa_rot_partition_attest_test_service
+ PUBLIC
+ .
+ PRIVATE
+ ${CMAKE_BINARY_DIR}/generated/test_services/tfm_attest_test_service
+)
+
+target_include_directories(tfm_partitions
+ INTERFACE
+ ${CMAKE_BINARY_DIR}/generated/test_services/tfm_attest_test_service
+)
+
+target_link_libraries(tfm_psa_rot_partition_attest_test_service
+ PRIVATE
+ tfm_secure_api
+ psa_interface
+ platform_s
+ tfm_test_framework_s
+)
+
+target_link_libraries(tfm_spm
+ PRIVATE
+ tfm_psa_rot_partition_attest_test_service
+)
+
+
+# header files included by other libraries
+add_library(tfm_psa_rot_partition_attest_test_service_defs INTERFACE)
+
+target_include_directories(tfm_psa_rot_partition_attest_test_service_defs
+ INTERFACE
+ .
+)
+
+############################ NS API ############################################
+
+target_sources(tfm_api_ns
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/tfm_attest_test_service_api.c
+)
+
+# The veneers give warnings about not being properly declared so they get hidden
+# to not overshadow _real_ warnings.
+set_source_files_properties(tfm_attest_test_service_api.c
+ PROPERTIES
+ COMPILE_FLAGS -Wno-implicit-function-declaration
+)
+
+target_include_directories(tfm_api_ns
+ PUBLIC
+ .
+)
+
+############################ Secure API ########################################
+
+target_sources(tfm_secure_api
+ INTERFACE
+ ${CMAKE_CURRENT_SOURCE_DIR}/tfm_attest_test_service_api.c
+)
+
+# The veneers give warnings about not being properly declared so they get hidden
+# to not overshadow _real_ warnings.
+set_source_files_properties(tfm_attest_test_service_api.c
+ PROPERTIES
+ COMPILE_FLAGS -Wno-implicit-function-declaration
+)
+
+############################ Partition Defs ####################################
+
+target_link_libraries(tfm_partitions
+ INTERFACE
+ tfm_psa_rot_partition_attest_test_service
+)
+
+target_compile_definitions(tfm_partition_defs
+ INTERFACE
+ ATTEST_TEST_GET_PUBLIC_KEY
+)
diff --git a/test/test_services/tfm_attest_test_service/tfm_attest_test_service.c b/test/test_services/tfm_attest_test_service/tfm_attest_test_service.c
new file mode 100644
index 0000000..b8e1170
--- /dev/null
+++ b/test/test_services/tfm_attest_test_service/tfm_attest_test_service.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "psa/crypto.h"
+#include "psa/error.h"
+#include "psa/service.h"
+#include "tfm_plat_defs.h"
+#include "tfm_plat_crypto_keys.h"
+#include "tfm_memory_utils.h"
+#ifdef TFM_PSA_API
+#include "psa/client.h"
+#include "tfm_api.h"
+#include "psa_manifest/tfm_attest_test_service.h"
+#else /* TFM_PSA_API */
+#include "tfm_veneers.h"
+#endif /* TFM_PSA_API */
+
+/*
+ * NOTE
+ *
+ * This Initial Attestation test service partition provide a secure API to
+ * enable tests to fetch Initial Attestation public key.
+ *
+ * This test service partition shall be only selected when flag
+ * ATTEST_TEST_GET_PUBLIC_KEY is enabled. ATTEST_TEST_GET_PUBLIC_KEY is enabled
+ * when Initial Attestation public key can only be fetched by test case in
+ * runtime.
+ *
+ * For example, some develop boards are provisioned in runtime with a random
+ * Initial Attestation key pair, whose public key is not pre-defined. The public
+ * key is unkown to the attestation verifier. Therefore the public key data can
+ * only be read for IAT verification in runtime.
+ *
+ * Integrating this test service will add the following into system
+ * - A PRoT service to read Initial Attestation key and export the public part.
+ * - Static data and stack belonging to the PRoT service.
+ * - An interface for non-secure test and secure test to read the public key
+ * out.
+ */
+
+/*
+ * NOTE
+ *
+ * This partition is for TF-M test purpose. Do NOT integrate it into any
+ * production or actual usage scenario.
+ */
+
+#define ECC_P256_PUBLIC_KEY_SIZE PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)
+
+/**
+ * The size of X and Y coordinate in 2 parameter style EC public
+ * key. Format is as defined in [COSE (RFC 8152)]
+ * (https://tools.ietf.org/html/rfc8152) and [SEC 1: Elliptic Curve
+ * Cryptography](http://www.secg.org/sec1-v2.pdf).
+ *
+ * This size is well-known and documented in public standards.
+ */
+#define ECC_P256_COORD_SIZE PSA_BITS_TO_BYTES(256) /* 256 bits -> 32 bytes */
+
+static uint8_t attestation_public_key[ECC_P256_PUBLIC_KEY_SIZE];
+static size_t attestation_public_key_len = 0;
+static psa_ecc_family_t attestation_key_curve;
+
+static psa_status_t attest_export_public_key(void)
+{
+
+ enum tfm_plat_err_t plat_res;
+ psa_ecc_family_t psa_curve;
+ struct ecc_key_t attest_key = {0};
+ uint8_t key_buf[3 * ECC_P256_COORD_SIZE]; /* priv + x_coord + y_coord */
+ psa_key_handle_t key_handle;
+ psa_key_attributes_t key_attributes = psa_key_attributes_init();
+ psa_status_t res;
+
+ /* Get the initial attestation key */
+ plat_res = tfm_plat_get_initial_attest_key(key_buf, sizeof(key_buf),
+ &attest_key, &psa_curve);
+
+ /* Check the availability of the private key */
+ if (plat_res != TFM_PLAT_ERR_SUCCESS || attest_key.priv_key == NULL) {
+ return PSA_ERROR_DOES_NOT_EXIST;
+ }
+
+ /* Setup the key policy for private key */
+ psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN);
+ psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(psa_curve));
+
+ /* Register private key to Crypto service */
+ res = psa_import_key(&key_attributes, attest_key.priv_key,
+ attest_key.priv_key_size, &key_handle);
+ if (res != PSA_SUCCESS) {
+ return res;
+ }
+
+ res = psa_export_public_key(key_handle, attestation_public_key,
+ ECC_P256_PUBLIC_KEY_SIZE,
+ &attestation_public_key_len);
+ if (res != PSA_SUCCESS) {
+ goto done;
+ }
+
+ attestation_key_curve = psa_curve;
+
+done:
+ res = psa_destroy_key(key_handle);
+ return res;
+}
+
+#ifdef TFM_PSA_API
+static psa_status_t attest_test_get_public_key(const psa_msg_t *msg)
+{
+ if (msg->out_size[0] < attestation_public_key_len) {
+ return PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+
+ if ((msg->out_size[1] != sizeof(attestation_key_curve)) ||
+ (msg->out_size[2] != sizeof(attestation_public_key_len))) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
+ psa_write(msg->handle, 0, attestation_public_key,
+ attestation_public_key_len);
+ psa_write(msg->handle, 1, &attestation_key_curve,
+ sizeof(attestation_key_curve));
+ psa_write(msg->handle, 2, &attestation_public_key_len,
+ sizeof(attestation_public_key_len));
+
+ return PSA_SUCCESS;
+}
+
+static void attest_signal_handle(psa_signal_t signal)
+{
+ psa_msg_t msg;
+ psa_status_t status;
+
+ status = psa_get(signal, &msg);
+ switch (msg.type) {
+ case PSA_IPC_CONNECT:
+ psa_reply(msg.handle, PSA_SUCCESS);
+ break;
+ case PSA_IPC_CALL:
+ status = attest_test_get_public_key(&msg);
+ psa_reply(msg.handle, status);
+ break;
+ case PSA_IPC_DISCONNECT:
+ psa_reply(msg.handle, PSA_SUCCESS);
+ break;
+ default:
+ psa_panic();
+ }
+}
+
+psa_status_t tfm_attest_test_service_init(void)
+{
+ psa_signal_t signals;
+ psa_status_t err;
+
+ err = attest_export_public_key();
+ if (err != PSA_SUCCESS) {
+ psa_panic();
+ }
+
+ while (1) {
+ signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+ if (signals & TFM_ATTEST_TEST_GET_PUBLIC_KEY_SIGNAL) {
+ attest_signal_handle(TFM_ATTEST_TEST_GET_PUBLIC_KEY_SIGNAL);
+ } else {
+ psa_panic();
+ }
+ }
+
+ return PSA_ERROR_SERVICE_FAILURE;
+}
+#else /* TFM_PSA_API */
+static bool is_public_key_exported = false;
+
+psa_status_t tfm_attest_test_get_public_key(const psa_invec *in_vec,
+ uint32_t num_invec,
+ psa_outvec *out_vec,
+ uint32_t num_outvec)
+{
+ uint8_t *key_buf;
+ size_t key_len;
+ psa_status_t res;
+
+ (void)in_vec;
+
+ if (num_invec != 0 || num_outvec != 3) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
+ /* Skip the export operation if the public key has been already exported. */
+ if (!is_public_key_exported) {
+ res = attest_export_public_key();
+ if (res != PSA_SUCCESS) {
+ return res;
+ }
+
+ is_public_key_exported = true;
+ }
+
+ key_buf = out_vec[0].base;
+ key_len = out_vec[0].len;
+
+ if (out_vec[1].len != sizeof(attestation_key_curve) ||
+ out_vec[2].len != sizeof(attestation_public_key_len)) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (key_len < attestation_public_key_len) {
+ return PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+
+ (void)tfm_memcpy(key_buf, attestation_public_key,
+ attestation_public_key_len);
+
+ *(psa_ecc_family_t *)out_vec[1].base = attestation_key_curve;
+
+ *(size_t *)out_vec[2].base = attestation_public_key_len;
+
+ return PSA_SUCCESS;
+}
+
+psa_status_t tfm_attest_test_service_init(void)
+{
+ return PSA_SUCCESS;
+}
+#endif /* TFM_PSA_API */
diff --git a/test/test_services/tfm_attest_test_service/tfm_attest_test_service.yaml b/test/test_services/tfm_attest_test_service/tfm_attest_test_service.yaml
new file mode 100644
index 0000000..fef37e3
--- /dev/null
+++ b/test/test_services/tfm_attest_test_service/tfm_attest_test_service.yaml
@@ -0,0 +1,36 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+ "psa_framework_version": 1.0,
+ "name": "TFM_SP_ATTEST_TEST",
+ "type": "PSA-ROT",
+ "priority": "NORMAL",
+ "entry_point": "tfm_attest_test_service_init",
+ "stack_size": "0x0400",
+ "secure_functions": [
+ {
+ "name": "TFM_ATTEST_TEST_GET_PUBLIC_KEY",
+ "signal": "TFM_ATTEST_TEST_GET_PUBLIC_KEY",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ }
+ ],
+ "services": [
+ {
+ "name": "TFM_ATTEST_TEST_GET_PUBLIC_KEY",
+ "sid": "0x0000F140",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ }
+ ],
+ "dependencies": [
+ "TFM_CRYPTO"
+ ]
+}
diff --git a/test/test_services/tfm_attest_test_service/tfm_attest_test_service_api.c b/test/test_services/tfm_attest_test_service/tfm_attest_test_service_api.c
new file mode 100644
index 0000000..5946fbf
--- /dev/null
+++ b/test/test_services/tfm_attest_test_service/tfm_attest_test_service_api.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa/crypto.h"
+#include "tfm_attest_test_service_api.h"
+#ifdef TFM_PSA_API
+#include "psa/client.h"
+#include "tfm_api.h"
+#include "psa_manifest/sid.h"
+#else /* TFM_PSA_API */
+#include "tfm_veneers.h"
+#endif /* TFM_PSA_API */
+
+psa_status_t tfm_initial_attest_get_public_key(uint8_t *public_key,
+ size_t public_key_buf_size,
+ size_t *public_key_len,
+ psa_ecc_family_t *curve_type)
+{
+ psa_status_t status;
+
+ psa_outvec out_vec[] = {
+ {.base = public_key, .len = public_key_buf_size},
+ {.base = curve_type, .len = sizeof(*curve_type)},
+ {.base = public_key_len, .len = sizeof(*public_key_len)}
+ };
+
+#ifdef TFM_PSA_API
+ psa_handle_t handle = PSA_NULL_HANDLE;
+
+ handle = psa_connect(TFM_ATTEST_TEST_GET_PUBLIC_KEY_SID,
+ TFM_ATTEST_TEST_GET_PUBLIC_KEY_VERSION);
+ if (!PSA_HANDLE_IS_VALID(handle)) {
+ return PSA_HANDLE_TO_ERROR(handle);
+ }
+
+ status = psa_call(handle, PSA_IPC_CALL, NULL, 0,
+ out_vec, IOVEC_LEN(out_vec));
+ psa_close(handle);
+#else
+ status = tfm_attest_test_get_public_key_veneer(NULL, 0,
+ out_vec, IOVEC_LEN(out_vec));
+#endif
+
+ return status;
+}
diff --git a/test/test_services/tfm_attest_test_service/tfm_attest_test_service_api.h b/test/test_services/tfm_attest_test_service/tfm_attest_test_service_api.h
new file mode 100644
index 0000000..2edcedb
--- /dev/null
+++ b/test/test_services/tfm_attest_test_service/tfm_attest_test_service_api.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_ATTEST_TEST_SERVICE_API_H__
+#define __TFM_ATTEST_TEST_SERVICE_API_H__
+
+#include <stdint.h>
+#include "psa/crypto.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Get the initial attestation public key.
+ *
+ * \param[out] public_key Pointer to the buffer where the public key
+ * will be stored.
+ * \param[in] key_buf_size Size of allocated buffer for key, in bytes.
+ * \param[out] public_key_len Size of public key in bytes.
+ * \param[out] public_key_curve Type of the elliptic curve which the key
+ * belongs to.
+ *
+ * \note Currently only the ECDSA P-256 over SHA-256 algorithm is supported.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t tfm_initial_attest_get_public_key(uint8_t *public_key,
+ size_t public_key_buf_size,
+ size_t *public_key_len,
+ psa_ecc_family_t *curve_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_ATTEST_TEST_SERVICE_API_H__ */
diff --git a/test/test_services/tfm_secure_client_service/tfm_secure_client_service.yaml b/test/test_services/tfm_secure_client_service/tfm_secure_client_service.yaml
index 3749ff4..6f35544 100644
--- a/test/test_services/tfm_secure_client_service/tfm_secure_client_service.yaml
+++ b/test/test_services/tfm_secure_client_service/tfm_secure_client_service.yaml
@@ -59,6 +59,7 @@
"TFM_FWU_QUERY",
"TFM_FWU_REQUEST_REBOOT",
"TFM_FWU_ACCEPT",
- "TFM_FFM11_SERVICE1"
+ "TFM_FFM11_SERVICE1",
+ "TFM_ATTEST_TEST_GET_PUBLIC_KEY"
]
}