Add attestation SP deployment

Adds a new deployment for running an Attestation service provider
in an SP for the opteesp environment.  Attestation service level
tests have been moved to the common ts-service-test.cmake file
so tests can be run in target and native PC environments.  The
Attestation SP has the following limitations:
- Mocked up event log - integration with TF-A/SPM not yet complete
- Uses mbedcrypto directly rather than teh Crypto service

Signed-off-by: Julian Hall <julian.hall@arm.com>
Signed-off-by: Gyorgy Szing <gyorgy.szing@arm.com>
Change-Id: Ib5efffaab1b23e5c31cbf87aba7ebcf3589aeb3a
diff --git a/components/service/attestation/client/provision/attest_provision_client.c b/components/service/attestation/client/provision/attest_provision_client.c
index 9209cc1..5aca130 100644
--- a/components/service/attestation/client/provision/attest_provision_client.c
+++ b/components/service/attestation/client/provision/attest_provision_client.c
@@ -146,3 +146,31 @@
     return psa_status;
 
 }
+
+psa_status_t attest_provision_iak_exists(void)
+{
+    psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+    rpc_call_handle call_handle;
+    uint8_t *req_buf;
+
+    call_handle = rpc_caller_begin(instance.caller, &req_buf, 0);
+
+    if (call_handle) {
+
+        uint8_t *resp_buf;
+        size_t resp_len;
+        int opstatus;
+
+        instance.rpc_status = rpc_caller_invoke(instance.caller, call_handle,
+            TS_ATTESTATION_OPCODE_IAK_EXISTS, &opstatus, &resp_buf, &resp_len);
+
+        if (instance.rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+            psa_status = opstatus;
+        }
+
+        rpc_caller_end(instance.caller, call_handle);
+    }
+
+    return psa_status;
+}
diff --git a/components/service/attestation/include/provision/attest_provision.h b/components/service/attestation/include/provision/attest_provision.h
index d8355f0..9f42920 100644
--- a/components/service/attestation/include/provision/attest_provision.h
+++ b/components/service/attestation/include/provision/attest_provision.h
@@ -62,6 +62,14 @@
     const uint8_t *data,
     size_t data_length);
 
+/**
+ * \brief Check if IAK exists
+ *
+ * Checks the provisioned state of a device.
+ *
+ * \return Returns PSA_SUCCESS if IAK exists, PSA_ERROR_DOES_NOT_EXIST if not
+ */
+psa_status_t attest_provision_iak_exists(void);
 
 #ifdef __cplusplus
 }
diff --git a/components/service/attestation/key_mngr/attest_key_mngr.c b/components/service/attestation/key_mngr/attest_key_mngr.c
index cff1dcf..3814710 100644
--- a/components/service/attestation/key_mngr/attest_key_mngr.c
+++ b/components/service/attestation/key_mngr/attest_key_mngr.c
@@ -176,3 +176,17 @@
 
     return status;
 }
+
+bool attest_key_mngr_iak_exists(void)
+{
+    if (!instance.is_iak_open && instance.iak_id) {
+
+        /* A persistent key ID is specified so the key might
+         * exist but has not been opened yet.
+         */
+        psa_status_t status = psa_open_key(instance.iak_id, &instance.iak_handle);
+        instance.is_iak_open = (status == PSA_SUCCESS);
+    }
+
+    return instance.is_iak_open;
+}
diff --git a/components/service/attestation/key_mngr/attest_key_mngr.h b/components/service/attestation/key_mngr/attest_key_mngr.h
index 0600be8..341a298 100644
--- a/components/service/attestation/key_mngr/attest_key_mngr.h
+++ b/components/service/attestation/key_mngr/attest_key_mngr.h
@@ -7,6 +7,8 @@
 #ifndef ATTEST_KEY_MNGR_H
 #define ATTEST_KEY_MNGR_H
 
+#include <stdbool.h>
+#include <stddef.h>
 #include <psa/crypto.h>
 
 /* Key ID for a volatile IAK (for test) */
@@ -57,6 +59,8 @@
 /**
  * \brief Export the IAK public key
  *
+ *  Like the above method, if no IAK exists, one will be generated.
+ *
  * \param[out] data  Buffer for key data
  * \param[in]  data_size Size of buffer
  * \param[out] data_length  Length in bytes of key
@@ -67,6 +71,23 @@
                                 size_t data_size, size_t *data_length);
 
 /**
+ * \brief Import the IAK key-pair
+ *
+ * \param[in]  data  The key data
+ * \param[out] data_length  Length in bytes of the key-pair
+ *
+ * \return Status
+ */
+psa_status_t attest_key_mngr_import_iak(const uint8_t *data, size_t data_length);
+
+/**
+ * \brief Check if the IAK exists
+ *
+ * \return True if IAK exist
+ */
+bool attest_key_mngr_iak_exists(void);
+
+/**
  * \brief Return maximum size of an exported IAK public key
  *
  * \return Maximum export size
@@ -80,15 +101,6 @@
  */
 size_t attest_key_mngr_max_iak_import_size(void);
 
-/**
- * \brief Import the IAK key-pair
- *
- * \param[in]  data  The key data
-  * \param[out] data_length  Length in bytes of the key-pair
- *
- * \return Status
- */
-psa_status_t attest_key_mngr_import_iak(const uint8_t *data, size_t data_length);
 
 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/components/service/attestation/provider/attest_provider.c b/components/service/attestation/provider/attest_provider.c
index 9669ed6..7ebf833 100644
--- a/components/service/attestation/provider/attest_provider.c
+++ b/components/service/attestation/provider/attest_provider.c
@@ -17,13 +17,15 @@
 static rpc_status_t get_token_size_handler(void *context, struct call_req* req);
 static rpc_status_t export_iak_public_key_handler(void *context, struct call_req* req);
 static rpc_status_t import_iak_handler(void *context, struct call_req* req);
+static rpc_status_t iak_exists_handler(void *context, struct call_req* req);
 
 /* Handler mapping table for service */
 static const struct service_handler handler_table[] = {
     {TS_ATTESTATION_OPCODE_GET_TOKEN,               get_token_handler},
     {TS_ATTESTATION_OPCODE_GET_TOKEN_SIZE,          get_token_size_handler},
     {TS_ATTESTATION_OPCODE_EXPORT_IAK_PUBLIC_KEY,   export_iak_public_key_handler},
-    {TS_ATTESTATION_OPCODE_IMPORT_IAK,              import_iak_handler}
+    {TS_ATTESTATION_OPCODE_IMPORT_IAK,              import_iak_handler},
+    {TS_ATTESTATION_OPCODE_IAK_EXISTS,              iak_exists_handler}
 };
 
 struct rpc_interface *attest_provider_init(struct attest_provider *context, psa_key_id_t iak_id)
@@ -232,3 +234,17 @@
 
     return rpc_status;
 }
+
+static rpc_status_t iak_exists_handler(void *context, struct call_req* req)
+{
+    int opstatus = PSA_ERROR_DOES_NOT_EXIST;
+
+    if (attest_key_mngr_iak_exists()) {
+
+       opstatus = PSA_SUCCESS;
+    }
+
+    call_req_set_opstatus(req, opstatus);
+
+    return TS_RPC_CALL_ACCEPTED;
+}
diff --git a/components/service/attestation/test/service/attestation_provisioning_tests.cpp b/components/service/attestation/test/service/attestation_provisioning_tests.cpp
index de447cf..4237bdf 100644
--- a/components/service/attestation/test/service/attestation_provisioning_tests.cpp
+++ b/components/service/attestation/test/service/attestation_provisioning_tests.cpp
@@ -103,12 +103,16 @@
 TEST(AttestationProvisioningTests, provisionedIak)
 {
     /* Verify that the provisioning flow where an IAK is generated externally
-     * and imported during manufacture.
+     * and imported during manufacture.  Note that the initial import is only
+     * expected to be successful for a fresh device.
      */
-    psa_status_t status;
+    psa_status_t status = attest_provision_iak_exists();
 
-    status = attest_provision_import_iak(ref_iak_priv_key, sizeof(ref_iak_priv_key));
-    LONGS_EQUAL(PSA_SUCCESS, status);
+    if (status == PSA_ERROR_DOES_NOT_EXIST) {
+
+        status = attest_provision_import_iak(ref_iak_priv_key, sizeof(ref_iak_priv_key));
+        LONGS_EQUAL(PSA_SUCCESS, status);
+    }
 
     /* Attempting to import again should be forbidden */
     status = attest_provision_import_iak(ref_iak_priv_key, sizeof(ref_iak_priv_key));
diff --git a/components/service/locator/linux/ffa/linuxffa_location_strategy.c b/components/service/locator/linux/ffa/linuxffa_location_strategy.c
index 2469e86..96e73d7 100644
--- a/components/service/locator/linux/ffa/linuxffa_location_strategy.c
+++ b/components/service/locator/linux/ffa/linuxffa_location_strategy.c
@@ -88,11 +88,12 @@
     }
     partition_lookup[] =
     {
-        {"crypto",                  "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0"},
-        {"internal-trusted-storage",  "dc1eef48-b17a-4ccf-ac8b-dfcff7711b14"},
-        {"protected-storage",         "751bf801-3dde-4768-a514-0f10aeed1790"},
-        {"test-runner",             "33c75baf-ac6a-4fe4-8ac7-e9909bee2d17"},
-        {NULL,                  NULL}
+        {"crypto",                      "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0"},
+        {"internal-trusted-storage",    "dc1eef48-b17a-4ccf-ac8b-dfcff7711b14"},
+        {"protected-storage",           "751bf801-3dde-4768-a514-0f10aeed1790"},
+        {"test-runner",                 "33c75baf-ac6a-4fe4-8ac7-e9909bee2d17"},
+        {"attestation",                 "a1baf155-8876-4695-8f7c-54955e8db974"},
+        {NULL,                          NULL}
     };
 
     const struct service_to_uuid *entry = &partition_lookup[0];
diff --git a/components/service/locator/standalone/services/attestation/attestation_service_context.cpp b/components/service/locator/standalone/services/attestation/attestation_service_context.cpp
index c23bf5c..b7ec8eb 100644
--- a/components/service/locator/standalone/services/attestation/attestation_service_context.cpp
+++ b/components/service/locator/standalone/services/attestation/attestation_service_context.cpp
@@ -9,6 +9,7 @@
 #include <service/attestation/claims/claims_register.h>
 #include <service/attestation/claims/sources/event_log/event_log_claim_source.h>
 #include <service/attestation/claims/sources/event_log/mock/mock_event_log.h>
+#include <psa/crypto.h>
 
 attestation_service_context::attestation_service_context(const char *sn) :
     standalone_service_context(sn),
@@ -30,6 +31,12 @@
 {
     struct claim_source *claim_source;
 
+    /* For the standalone attestation service deployment, the
+     * mbedcrypto library is used directly.  Note that psa_crypto_init()
+     * is allowed to be called multiple times.
+     */
+    psa_crypto_init();
+
     /**
      * Initialize and register claims sources to define the view of
      * the device reflected by the attestation service.  On a real
diff --git a/deployments/attestation/opteesp/CMakeLists.txt b/deployments/attestation/opteesp/CMakeLists.txt
new file mode 100644
index 0000000..6852950
--- /dev/null
+++ b/deployments/attestation/opteesp/CMakeLists.txt
@@ -0,0 +1,163 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+cmake_minimum_required(VERSION 3.16)
+include(../../deployment.cmake REQUIRED)
+
+#-------------------------------------------------------------------------------
+#  The CMakeLists.txt for building the attestation deployment for opteesp
+#
+#  Builds the attestation service provider for running in an SEL0 secure partition
+#  hosted by OPTEE in the role of SPM.
+#-------------------------------------------------------------------------------
+include(${TS_ROOT}/environments/opteesp/env.cmake)
+project(trusted-services LANGUAGES C ASM)
+add_executable(attestation)
+target_include_directories(attestation PRIVATE "${TOP_LEVEL_INCLUDE_DIRS}")
+set(SP_UUID "a1baf155-8876-4695-8f7c-54955e8db974")
+
+
+# Include SP DEV KIT interface
+set(SP_DEV_KIT_INC_DIR ${CMAKE_CURRENT_LIST_DIR})
+list(APPEND CMAKE_MODULE_PATH "${TS_ROOT}/external/Spdevkit")
+find_package(Spdevkit REQUIRED)
+sp_dev_kit_configure_linking(TARGET attestation DEFINES ARM64=1)
+target_link_libraries(attestation PRIVATE ${SP_DEV_KIT_LIBRARIES})
+
+#-------------------------------------------------------------------------------
+#  Default deployment specific configuration
+#
+#-------------------------------------------------------------------------------
+set(TS_NO_FLOAT_HW ON)
+
+#-------------------------------------------------------------------------------
+#  Components that are specific to deployment in the opteesp environment.
+#
+#-------------------------------------------------------------------------------
+add_components(TARGET "attestation"
+	BASE_DIR ${TS_ROOT}
+	COMPONENTS
+		"components/common/tlv"
+		"components/common/endian"
+		"components/config/ramstore"
+		"components/config/loader/sp"
+		"components/messaging/ffa/libsp"
+		"components/rpc/ffarpc/endpoint"
+		"components/rpc/ffarpc/caller/sp"
+		"components/rpc/common/caller"
+		"components/rpc/common/interface"
+		"components/service/common/include"
+		"components/service/common/provider"
+		"components/service/attestation/include"
+		"components/service/attestation/claims"
+		"components/service/attestation/claims/sources/boot_seed_generator"
+		"components/service/attestation/claims/sources/null_lifecycle"
+		"components/service/attestation/claims/sources/instance_id"
+		"components/service/attestation/claims/sources/event_log"
+		"components/service/attestation/claims/sources/event_log/mock"
+		"components/service/attestation/reporter/psa"
+		"components/service/attestation/key_mngr"
+		"components/service/attestation/provider"
+		"components/service/attestation/provider/serializer/packed-c"
+		"protocols/rpc/common/packed-c"
+		"environments/opteesp"
+)
+
+target_sources(attestation PRIVATE
+	attestation_sp.c
+)
+
+#-------------------------------------------------------------------------------
+#  Use the selected platform to provide drivers needed by the deployment
+#
+#-------------------------------------------------------------------------------
+add_platform(TARGET "attestation")
+
+#-------------------------------------------------------------------------------
+#  Components used from external projects
+#
+#-------------------------------------------------------------------------------
+
+# Temporary dependency on mbedcrypto
+set(MBEDTLS_USER_CONFIG_FILE
+	"${TS_ROOT}/components/service/crypto/client/cpp/config_mbedtls_user.h"
+	CACHE STRING "Configuration file for mbedcrypto")
+
+# Mbed TLS provides libmbedcrypto
+include(../../../external/MbedTLS/MbedTLS.cmake)
+target_link_libraries(attestation PRIVATE mbedcrypto)
+
+# Qcbor
+include(${TS_ROOT}/external/qcbor/qcbor.cmake)
+target_link_libraries(attestation PRIVATE qcbor)
+
+# t_cose
+include(${TS_ROOT}/external/t_cose/t_cose.cmake)
+target_link_libraries(attestation PRIVATE t_cose)
+
+if(CMAKE_CROSSCOMPILING)
+	target_link_libraries(attestation PRIVATE stdc++ gcc m)
+endif()
+
+#################################################################
+
+target_compile_definitions(attestation PRIVATE
+	ARM64=1
+)
+
+target_include_directories(attestation PRIVATE
+	${TS_ROOT}
+	${TS_ROOT}/components
+	${TS_ROOT}/deployments/attestation/opteesp
+)
+
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
+	target_compile_options(attestation PRIVATE
+		-fdiagnostics-show-option
+		-fpic
+		-gdwarf-2
+		-mstrict-align
+		-O0
+		-std=gnu99
+	)
+
+	# Options for GCC that control linking
+	target_link_options(attestation PRIVATE
+		-e __sp_entry
+		-fno-lto
+		-nostdlib
+		-pie
+		-zmax-page-size=4096
+	)
+	# Options directly for LD, these are not understood by GCC
+	target_link_options(attestation PRIVATE
+		-Wl,--as-needed
+		-Wl,--sort-section=alignment
+		# -Wl,--dynamic-list ${CMAKE_CURRENT_LIST_DIR}/dyn_list
+	)
+endif()
+
+compiler_generate_stripped_elf(TARGET attestation NAME "${SP_UUID}.stripped.elf" RES STRIPPED_ELF)
+
+######################################## install
+if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+	set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "location to install build output to." FORCE)
+endif()
+#TODO: api headers
+
+install(TARGETS attestation
+			PUBLIC_HEADER DESTINATION ${TS_ENV}/include
+			RUNTIME DESTINATION ${TS_ENV}/bin
+		)
+install(FILES ${STRIPPED_ELF} DESTINATION ${TS_ENV}/bin)
+
+get_property(_PROTO_FILES TARGET attestation PROPERTY PROTOBUF_FILES)
+install(FILES ${_PROTO_FILES} DESTINATION ${TS_ENV}/lib/protobuf)
+
+
+set(EXPORT_SP_NAME "attestation")
+set(EXPORT_SP_UUID ${SP_UUID})
+include(${TS_ROOT}/environments/opteesp/ExportSp.cmake)
diff --git a/deployments/attestation/opteesp/attestation_sp.c b/deployments/attestation/opteesp/attestation_sp.c
new file mode 100644
index 0000000..ce45516
--- /dev/null
+++ b/deployments/attestation/opteesp/attestation_sp.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <rpc/ffarpc/caller/sp/ffarpc_caller.h>
+#include <rpc/ffarpc/endpoint/ffarpc_call_ep.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <config/ramstore/config_ramstore.h>
+#include <config/loader/sp/sp_config_loader.h>
+#include <service/attestation/provider/attest_provider.h>
+#include <service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.h>
+#include <service/attestation/claims/claims_register.h>
+#include <service/attestation/claims/sources/event_log/event_log_claim_source.h>
+#include <service/attestation/claims/sources/boot_seed_generator/boot_seed_generator.h>
+#include <service/attestation/claims/sources/null_lifecycle/null_lifecycle_claim_source.h>
+#include <service/attestation/claims/sources/instance_id/instance_id_claim_source.h>
+#include <ffa_api.h>
+#include <sp_api.h>
+#include <sp_rxtx.h>
+#include <trace.h>
+
+
+/* Temporary dependencies */
+#include <service/attestation/claims/sources/event_log/mock/mock_event_log.h>
+#include <psa/crypto.h>
+
+
+uint16_t own_id = 0; /* !!Needs refactoring as parameter to ffarpc_caller_init */
+
+
+static int sp_init(uint16_t *own_sp_id);
+
+void __noreturn sp_main(struct ffa_init_info *init_info)
+{
+	/* Service provider objects */
+	struct attest_provider attest_provider;
+	struct rpc_interface *attest_iface;
+	struct ffa_call_ep ffarpc_call_ep;
+	struct ffa_direct_msg req_msg;
+
+	/* Claim source objects */
+	struct claim_source *claim_source;
+	struct event_log_claim_source event_log_claim_source;
+    struct boot_seed_generator boot_seed_claim_source;
+    struct null_lifecycle_claim_source lifecycle_claim_source;
+    struct instance_id_claim_source instance_id_claim_source;
+
+	/*********************************************************
+	 * Boot phase
+	 *********************************************************/
+	if (sp_init(&own_id) != 0) goto fatal_error;
+
+	config_ramstore_init();
+	sp_config_load(init_info);
+
+	/**
+	 * Register claim sources for deployment
+     */
+	claims_register_init();
+
+    /* Boot measurement claim source - uses mock event log */
+    claim_source = event_log_claim_source_init(&event_log_claim_source,
+        mock_event_log_start(), mock_event_log_size());
+    claims_register_add_claim_source(CLAIM_CATEGORY_BOOT_MEASUREMENT, claim_source);
+
+    /* Boot seed claim source */
+    claim_source = boot_seed_generator_init(&boot_seed_claim_source);
+    claims_register_add_claim_source(CLAIM_CATEGORY_DEVICE, claim_source);
+
+    /* Lifecycle state claim source */
+    claim_source = null_lifecycle_claim_source_init(&lifecycle_claim_source);
+    claims_register_add_claim_source(CLAIM_CATEGORY_DEVICE, claim_source);
+
+    /* Instance ID claim source */
+    claim_source = instance_id_claim_source_init(&instance_id_claim_source);
+    claims_register_add_claim_source(CLAIM_CATEGORY_DEVICE, claim_source);
+
+	/**
+	 * Initialize the service provider
+     */
+ 	psa_crypto_init(); /* temporary */
+
+    attest_iface = attest_provider_init(&attest_provider, ATTEST_KEY_MNGR_VOLATILE_IAK);
+
+    attest_provider_register_serializer(&attest_provider,
+        TS_RPC_ENCODING_PACKED_C, packedc_attest_provider_serializer_instance());
+
+	ffa_call_ep_init(&ffarpc_call_ep, attest_iface);
+
+	/*********************************************************
+	 * End of boot phase
+	 *********************************************************/
+	ffa_msg_wait(&req_msg);
+
+	while (1) {
+		if (req_msg.function_id == FFA_MSG_SEND_DIRECT_REQ_32) {
+
+			struct ffa_direct_msg resp_msg;
+
+			ffa_call_ep_receive(&ffarpc_call_ep, &req_msg, &resp_msg);
+
+			ffa_msg_send_direct_resp(req_msg.destination_id,
+					req_msg.source_id, resp_msg.args[0], resp_msg.args[1],
+					resp_msg.args[2], resp_msg.args[3], resp_msg.args[4],
+					&req_msg);
+		}
+	}
+
+fatal_error:
+	/* SP is not viable */
+	EMSG("Attestation SP error");
+	while (1) {}
+}
+
+void sp_interrupt_handler(uint32_t interrupt_id)
+{
+	(void)interrupt_id;
+}
+
+static int sp_init(uint16_t *own_sp_id)
+{
+	int status = -1;
+	ffa_result ffa_res;
+	sp_result sp_res;
+	static uint8_t tx_buffer[4096] __aligned(4096);
+	static uint8_t rx_buffer[4096] __aligned(4096);
+
+	sp_res = sp_rxtx_buffer_map(tx_buffer, rx_buffer, sizeof(rx_buffer));
+	if (sp_res == SP_RESULT_OK) {
+		ffa_res = ffa_id_get(own_sp_id);
+		if (ffa_res == FFA_OK) {
+			status = 0;
+		}
+	}
+
+	return status;
+}
diff --git a/deployments/attestation/opteesp/attestation_sp.h b/deployments/attestation/opteesp/attestation_sp.h
new file mode 100644
index 0000000..7c4af58
--- /dev/null
+++ b/deployments/attestation/opteesp/attestation_sp.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ATTESTATION_SP_H
+#define ATTESTATION_SP_H
+
+#define ATTESTATION_SP_UUID \
+    {0xa1baf155, 0x8876, 0x4695, \
+                {0x8f, 0x7c, 0x54, 0x95, 0x5e, 0x8d, 0xb9, 0x74}}
+
+#define ATTESTATION_SP_UUID_BYTES \
+    {0xa1, 0xba, 0xf1, 0x55, 0x88, 0x76, 0x46, 0x95, \
+     0x8f, 0x7c, 0x54, 0x95, 0x5e, 0x8d, 0xb9, 0x74}
+
+#endif /* ATTESTATION_SP_H */
diff --git a/deployments/attestation/opteesp/default_attestation.dts.in b/deployments/attestation/opteesp/default_attestation.dts.in
new file mode 100644
index 0000000..a184164
--- /dev/null
+++ b/deployments/attestation/opteesp/default_attestation.dts.in
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+@DTS_TAG@
+
+@DTS_NODE@ {
+	compatible = "arm,ffa-manifest-1.0";
+	ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+	uuid = <@EXPORT_SP_UUID_DT@>;
+	description = "Attestation";
+	execution-ctx-count = <1>;
+	exception-level = <1>; /* S-EL0 */
+	execution-state = <0>; /* AArch64 */
+	xlat-granule = <0>; /* 4KiB */
+	messaging-method = <0>; /* Direct messaging only */
+};
diff --git a/deployments/attestation/opteesp/optee_sp_user_defines.h b/deployments/attestation/opteesp/optee_sp_user_defines.h
new file mode 100644
index 0000000..23c67b6
--- /dev/null
+++ b/deployments/attestation/opteesp/optee_sp_user_defines.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SP_HEADER_DEFINES_H
+#define SP_HEADER_DEFINES_H
+
+/* To get UUID definition */
+#include "attestation_sp.h"
+
+#define OPTEE_SP_UUID				ATTESTATION_SP_UUID
+#define OPTEE_SP_FLAGS				0
+
+/* Provisioned stack size */
+#define OPTEE_SP_STACK_SIZE			(64 * 1024)
+
+/* Provisioned heap size */
+#define OPTEE_SP_HEAP_SIZE			(32 * 1024)
+
+#endif /* SP_HEADER_DEFINES_H */
diff --git a/deployments/ts-service-test/linux-pc/CMakeLists.txt b/deployments/ts-service-test/linux-pc/CMakeLists.txt
index 798b8cb..c165fac 100644
--- a/deployments/ts-service-test/linux-pc/CMakeLists.txt
+++ b/deployments/ts-service-test/linux-pc/CMakeLists.txt
@@ -78,12 +78,8 @@
 	TARGET "ts-service-test"
 	BASE_DIR ${TS_ROOT}
     COMPONENTS
-        "components/service/test_runner/client/cpp"
+		"components/service/test_runner/client/cpp"
 		"components/service/test_runner/test/service"
-		"components/service/attestation/include"
-		"components/service/attestation/client/psa"
-		"components/service/attestation/client/provision"
-		"components/service/attestation/test/service"
 )
 
 #-------------------------------------------------------------------------------
diff --git a/deployments/ts-service-test/ts-service-test.cmake b/deployments/ts-service-test/ts-service-test.cmake
index 28ff49d..f56ac01 100644
--- a/deployments/ts-service-test/ts-service-test.cmake
+++ b/deployments/ts-service-test/ts-service-test.cmake
@@ -39,6 +39,10 @@
 		"components/service/crypto/client/cpp/protobuf"
 		"components/service/crypto/client/cpp/packed-c"
 		"components/service/common/serializer/protobuf"
+		"components/service/attestation/include"
+		"components/service/attestation/client/psa"
+		"components/service/attestation/client/provision"
+		"components/service/attestation/test/service"
 		"protocols/service/crypto/protobuf"
 		"protocols/service/crypto/packed-c"
 		"components/service/secure_storage/include"
diff --git a/external/qcbor/0001-Add-3rd-party-settings.patch b/external/qcbor/0001-Add-3rd-party-settings.patch
new file mode 100644
index 0000000..d909e10
--- /dev/null
+++ b/external/qcbor/0001-Add-3rd-party-settings.patch
@@ -0,0 +1,28 @@
+From daaecfc924678cfd1000c87827bb5b8d4653c8e9 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Mon, 5 Jul 2021 05:21:00 +0000
+Subject: [PATCH 1/2] Add 3rd party settings
+
+Introduce a way to allow defining include paths and macro
+definitions externally.
+---
+ CMakeLists.txt | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 8a5bcd0..4e4756d 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -8,6 +8,9 @@ set(CMAKE_C_FLAGS "-pedantic -Wall -O3 -ffunction-sections")
+ 
+ include_directories(inc)
+ 
++include_directories(${thirdparty_inc})
++add_definitions(${thirdparty_def})
++
+ set(SOURCE
+ 	src/ieee754.c
+ 	src/qcbor_decode.c
+-- 
+2.17.1
+
diff --git a/external/qcbor/0002-Add-install-definition.patch b/external/qcbor/0002-Add-install-definition.patch
new file mode 100644
index 0000000..f6f0033
--- /dev/null
+++ b/external/qcbor/0002-Add-install-definition.patch
@@ -0,0 +1,38 @@
+From cb011e7c8ad650bb0dd24930bf19da4a4620e30b Mon Sep 17 00:00:00 2001
+From: Gyorgy Szing <Gyorgy.Szing@arm.com>
+Date: Mon, 5 Jul 2021 06:45:47 +0000
+Subject: [PATCH 2/2] Add install definition
+
+Add install() calls to define stable way to access build artifacts.
+---
+ CMakeLists.txt | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 4e4756d..b26edce 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -20,3 +20,20 @@ set(SOURCE
+ ) 
+ 
+ add_library(qcbor ${SOURCE})
++
++install(
++       TARGETS
++               qcbor
++       ARCHIVE DESTINATION
++               lib
++       PUBLIC_HEADER DESTINATION
++               include/qcbor
++       COMPONENT
++               qcbor
++)
++
++install(
++       DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/inc/
++               DESTINATION include
++               COMPONENT qcbor
++)
+-- 
+2.17.1
+
diff --git a/external/qcbor/qcbor.cmake b/external/qcbor/qcbor.cmake
index 233c16b..7e001be 100644
--- a/external/qcbor/qcbor.cmake
+++ b/external/qcbor/qcbor.cmake
@@ -26,6 +26,11 @@
 	GIT_REPOSITORY ${QCBOR_URL}
 	GIT_TAG ${QCBOR_REFSPEC}
 	GIT_SHALLOW TRUE
+
+	PATCH_COMMAND git stash
+		COMMAND git branch -f bf-patch
+		COMMAND git am ${CMAKE_CURRENT_LIST_DIR}/0001-Add-3rd-party-settings.patch ${CMAKE_CURRENT_LIST_DIR}/0002-Add-install-definition.patch
+		COMMAND git reset bf-patch
 )
 
 # FetchContent_GetProperties exports qcbor_SOURCE_DIR and qcbor_BINARY_DIR variables
@@ -35,11 +40,18 @@
 	FetchContent_Populate(qcbor)
 endif()
 
+# Determine floating point configuration
+if (TS_NO_FLOAT_HW)
+	set(_thirdparty_def -DQCBOR_DISABLE_FLOAT_HW_USE)
+endif()
+
 # Configure the qcbor library
 execute_process(COMMAND
 ${CMAKE_COMMAND}
 	-DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE}
 	-GUnix\ Makefiles
+	-Dthirdparty_def=${_thirdparty_def}
+	-DCMAKE_INSTALL_PREFIX=${QCBOR_INSTALL_PATH}
 	${qcbor_SOURCE_DIR}
 WORKING_DIRECTORY
 	${qcbor_BINARY_DIR}
@@ -54,7 +66,15 @@
 	message(FATAL_ERROR "Build step of qcbor failed with ${_exec_error}.")
 endif()
 
+execute_process(COMMAND
+		${CMAKE_COMMAND} --install ${qcbor_BINARY_DIR}
+		RESULT_VARIABLE _exec_error
+	)
+if (_exec_error)
+	message(FATAL_ERROR "Build step of qcbor failed with ${_exec_error}.")
+endif()
+
 # Create an imported target to have clean abstraction in the build-system.
 add_library(qcbor STATIC IMPORTED)
-set_property(TARGET qcbor PROPERTY IMPORTED_LOCATION "${qcbor_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}qcbor${CMAKE_STATIC_LIBRARY_SUFFIX}")
-set_property(TARGET qcbor PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${qcbor_SOURCE_DIR}/inc")
+set_property(TARGET qcbor PROPERTY IMPORTED_LOCATION "${QCBOR_INSTALL_PATH}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}qcbor${CMAKE_STATIC_LIBRARY_SUFFIX}")
+set_property(TARGET qcbor PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${QCBOR_INSTALL_PATH}/include")
diff --git a/protocols/service/attestation/packed-c/opcodes.h b/protocols/service/attestation/packed-c/opcodes.h
index 3484e1b..7bdc6f7 100644
--- a/protocols/service/attestation/packed-c/opcodes.h
+++ b/protocols/service/attestation/packed-c/opcodes.h
@@ -10,9 +10,13 @@
 /* C/C++ definition of attestation service opcodes
  */
 
+/* Report generation and retrieval operations */
 #define TS_ATTESTATION_OPCODE_GET_TOKEN             (0x0001)
 #define TS_ATTESTATION_OPCODE_GET_TOKEN_SIZE        (0x0002)
+
+/* Provisioning operations */
 #define TS_ATTESTATION_OPCODE_EXPORT_IAK_PUBLIC_KEY (0x0003)
 #define TS_ATTESTATION_OPCODE_IMPORT_IAK            (0x0004)
+#define TS_ATTESTATION_OPCODE_IAK_EXISTS            (0x0005)
 
 #endif /* TS_ATTESTATION_OPCODES_H */
diff --git a/tools/b-test/test_data.yaml b/tools/b-test/test_data.yaml
index 06afe89..32c6337 100644
--- a/tools/b-test/test_data.yaml
+++ b/tools/b-test/test_data.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -78,3 +78,8 @@
             - "-GUnix Makefiles"
             - "-DSP_DEV_KIT_DIR=$SP_DEV_KIT_DIR"
             - "-DCMAKE_VERBOSE_MAKEFILE=y"
+    - name: "attestation-optee-arm"
+      src: "$TS_ROOT/deployments/attestation/opteesp"
+      params:
+            - "-GUnix Makefiles"
+            - "-DSP_DEV_KIT_DIR=$SP_DEV_KIT_DIR"