aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Hall <julian.hall@arm.com>2021-05-13 15:30:39 +0100
committerGyorgy Szing <Gyorgy.Szing@arm.com>2021-07-05 12:43:49 +0200
commit700aa36408ceec03311bd7aa097c93d220371304 (patch)
tree8f27789bb08415199825541e94448c3ac83b2f4a
parent70be3f17bd00710dcab9fcba2fea2c23853c7c71 (diff)
downloadtrusted-services-700aa36408ceec03311bd7aa097c93d220371304.tar.gz
Add attestation service provider and client
Adds the attestation service provider with a packed-c serializer. A client that implements the PSA Attestation C API is also added. To allow for service level testing in a PC environment, a standalone service context has beed added for the attestation service. Signed-off-by: Julian Hall <julian.hall@arm.com> Change-Id: I468e8be122472b5cfff4b9a56569a08b193a14e9
-rw-r--r--components/service/attestation/client/psa/component.cmake13
-rw-r--r--components/service/attestation/client/psa/iat_client.c168
-rw-r--r--components/service/attestation/client/psa/iat_client.h51
-rw-r--r--components/service/attestation/include/component.cmake14
-rw-r--r--components/service/attestation/include/psa/initial_attestation.h23
-rw-r--r--components/service/attestation/key_mngr/attest_key_mngr.c36
-rw-r--r--components/service/attestation/key_mngr/attest_key_mngr.h12
-rw-r--r--components/service/attestation/provider/attest_provider.c157
-rw-r--r--components/service/attestation/provider/attest_provider.h66
-rw-r--r--components/service/attestation/provider/component.cmake13
-rw-r--r--components/service/attestation/provider/serializer/attest_provider_serializer.h38
-rw-r--r--components/service/attestation/provider/serializer/packed-c/component.cmake13
-rw-r--r--components/service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.c108
-rw-r--r--components/service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.h25
-rw-r--r--components/service/attestation/reporter/psa/psa_attest_report.c14
-rw-r--r--components/service/attestation/test/common/component.cmake13
-rw-r--r--components/service/attestation/test/common/report_dump.cpp (renamed from components/service/attestation/test/component/report_dump.cpp)0
-rw-r--r--components/service/attestation/test/common/report_dump.h (renamed from components/service/attestation/test/component/report_dump.h)0
-rw-r--r--components/service/attestation/test/component/attestation_reporter_tests.cpp4
-rw-r--r--components/service/attestation/test/component/component.cmake1
-rw-r--r--components/service/attestation/test/service/attestation_service_tests.cpp169
-rw-r--r--components/service/attestation/test/service/component.cmake13
-rw-r--r--components/service/locator/standalone/services/attestation/attestation_service_context.cpp58
-rw-r--r--components/service/locator/standalone/services/attestation/attestation_service_context.h31
-rw-r--r--components/service/locator/standalone/services/attestation/component.cmake13
-rw-r--r--components/service/locator/standalone/standalone_env.cpp4
-rw-r--r--deployments/component-test/component-test.cmake7
-rw-r--r--deployments/libts/linux-pc/CMakeLists.txt19
-rw-r--r--deployments/ts-service-test/linux-pc/CMakeLists.txt3
29 files changed, 1045 insertions, 41 deletions
diff --git a/components/service/attestation/client/psa/component.cmake b/components/service/attestation/client/psa/component.cmake
new file mode 100644
index 0000000..046c0a5
--- /dev/null
+++ b/components/service/attestation/client/psa/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 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}/iat_client.c"
+ )
diff --git a/components/service/attestation/client/psa/iat_client.c b/components/service/attestation/client/psa/iat_client.c
new file mode 100644
index 0000000..5c88018
--- /dev/null
+++ b/components/service/attestation/client/psa/iat_client.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include "iat_client.h"
+#include <common/tlv/tlv.h>
+#include <psa/initial_attestation.h>
+#include <protocols/service/attestation/packed-c/get_token.h>
+#include <protocols/service/attestation/packed-c/get_token_size.h>
+#include <protocols/service/attestation/packed-c/opcodes.h>
+#include <protocols/rpc/common/packed-c/status.h>
+
+/**
+ * @brief The singleton psa_iat_client instance
+ *
+ * The psa attestation C API assumes a single backend service provider. This
+ * structure defines the state used by the psa_iat_client that communicates
+ * with a remote provider using the provided rpc caller.
+ */
+static struct psa_iat_client
+{
+ struct rpc_caller *caller;
+ int rpc_status;
+} instance;
+
+
+psa_status_t psa_iat_client_init(struct rpc_caller *caller)
+{
+ instance.caller = caller;
+ instance.rpc_status = TS_RPC_CALL_ACCEPTED;
+
+ return PSA_SUCCESS;
+}
+
+void psa_iat_client_deinit(void)
+{
+ instance.caller = NULL;
+}
+
+int psa_iat_client_rpc_status(void)
+{
+ return instance.rpc_status;
+}
+
+psa_status_t psa_initial_attest_get_token(
+ const uint8_t *auth_challenge, size_t challenge_size,
+ uint8_t *token_buf, size_t token_buf_size, size_t *token_size)
+{
+ psa_status_t psa_status = PSA_ERROR_INVALID_ARGUMENT;
+ size_t req_len = tlv_required_space(challenge_size);
+
+ struct tlv_record challenge_record;
+ challenge_record.tag = TS_ATTESTATION_GET_TOKEN_IN_TAG_AUTH_CHALLENGE;
+ challenge_record.length = challenge_size;
+ challenge_record.value = auth_challenge;
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ *token_size = 0;
+
+ call_handle = rpc_caller_begin(instance.caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+ struct tlv_iterator req_iter;
+
+ tlv_iterator_begin(&req_iter, req_buf, req_len);
+ tlv_encode(&req_iter, &challenge_record);
+
+ instance.rpc_status = rpc_caller_invoke(instance.caller, call_handle,
+ TS_ATTESTATION_OPCODE_GET_TOKEN, &opstatus, &resp_buf, &resp_len);
+
+ if (instance.rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct tlv_const_iterator resp_iter;
+ struct tlv_record decoded_record;
+ tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
+
+ if (tlv_find_decode(&resp_iter,
+ TS_ATTESTATION_GET_TOKEN_OUT_TAG_TOKEN, &decoded_record)) {
+
+ if (decoded_record.length <= token_buf_size) {
+
+ memcpy(token_buf, decoded_record.value, decoded_record.length);
+ *token_size = decoded_record.length;
+ }
+ else {
+ /* Provided buffer is too small */
+ psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+ }
+ else {
+ /* Mandatory response parameter missing */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+ }
+ }
+
+ rpc_caller_end(instance.caller, call_handle);
+ }
+
+ return psa_status;
+}
+
+psa_status_t psa_initial_attest_get_token_size(
+ size_t challenge_size, size_t *token_size)
+{
+ psa_status_t psa_status = PSA_ERROR_INVALID_ARGUMENT;
+ struct ts_attestation_get_token_size_in req_msg;
+ size_t req_len = sizeof(struct ts_attestation_get_token_size_in);
+
+ *token_size = 0; /* For failure case */
+
+ req_msg.challenge_size = challenge_size;
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(instance.caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+ struct tlv_iterator req_iter;
+
+ memcpy(req_buf, &req_msg, req_len);
+
+ instance.rpc_status = rpc_caller_invoke(instance.caller, call_handle,
+ TS_ATTESTATION_OPCODE_GET_TOKEN_SIZE, &opstatus, &resp_buf, &resp_len);
+
+ if (instance.rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ if (resp_len >= sizeof(struct ts_attestation_get_token_size_out)) {
+
+ struct ts_attestation_get_token_size_out resp_msg;
+ memcpy(&resp_msg, resp_buf, sizeof(struct ts_attestation_get_token_size_out));
+ *token_size = resp_msg.token_size;
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+ }
+ }
+
+ rpc_caller_end(instance.caller, call_handle);
+ }
+
+ return psa_status;
+}
diff --git a/components/service/attestation/client/psa/iat_client.h b/components/service/attestation/client/psa/iat_client.h
new file mode 100644
index 0000000..7daeacf
--- /dev/null
+++ b/components/service/attestation/client/psa/iat_client.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PSA_IAT_CLIENT_H
+#define PSA_IAT_CLIENT_H
+
+#include <psa/error.h>
+#include <rpc_caller.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialises the singleton IAT client
+ *
+ * The IAT client provides an implementation of the PSA Attestation API.
+ * This API may be used by client applications to request attestion
+ * tokens.
+ *
+ * @param[in] rpc_caller RPC caller instance
+ *
+ * @return A status indicating the success/failure of the operation
+ */
+psa_status_t psa_iat_client_init(struct rpc_caller *caller);
+
+/**
+ * @brief De-initialises the singleton IAT client
+ *
+ */
+void psa_iat_client_deinit(void);
+
+/**
+ * @brief Return the most recent RPC status
+ *
+ * May be used to obtain information about an RPC error that resulted
+ * in an API operation failure
+ *
+ * @return Most recent RPC operation status
+ */
+int psa_iat_client_rpc_status(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PSA_IAT_CLIENT_H */
diff --git a/components/service/attestation/include/component.cmake b/components/service/attestation/include/component.cmake
new file mode 100644
index 0000000..00c61bd
--- /dev/null
+++ b/components/service/attestation/include/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 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_include_directories(${TGT}
+ PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}"
+ )
diff --git a/components/service/attestation/include/psa/initial_attestation.h b/components/service/attestation/include/psa/initial_attestation.h
index bc630ee..35a18d0 100644
--- a/components/service/attestation/include/psa/initial_attestation.h
+++ b/components/service/attestation/include/psa/initial_attestation.h
@@ -18,7 +18,6 @@
#include <limits.h>
#include <stdint.h>
#include <stddef.h>
-#include "psa/crypto.h"
#ifdef __cplusplus
extern "C" {
@@ -46,7 +45,7 @@ extern "C" {
* attestation service. Used to configure buffers for services that verify the
* produced tokens.
*/
-#define PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE (0x400)
+#define PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE (4096)
/**
* The list of fixed claims in the initial attestation token is still evolving,
@@ -201,26 +200,6 @@ psa_status_t
psa_initial_attest_get_token_size(size_t challenge_size,
size_t *token_size);
-/**
- * \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 *elliptic_curve_type);
-
#ifdef __cplusplus
}
#endif
diff --git a/components/service/attestation/key_mngr/attest_key_mngr.c b/components/service/attestation/key_mngr/attest_key_mngr.c
index c871c82..a4d8ec0 100644
--- a/components/service/attestation/key_mngr/attest_key_mngr.c
+++ b/components/service/attestation/key_mngr/attest_key_mngr.c
@@ -8,9 +8,6 @@
#include <psa/crypto.h>
#include "attest_key_mngr.h"
-/* todo - need strategy for assigning key IDs */
-#define IAK_KEY_ID 0x2000
-
/**
* The singleton attest_key_mngr instance.
*/
@@ -55,16 +52,20 @@ static psa_status_t generate_iak(psa_key_id_t key_id, psa_key_handle_t *iak_hand
return status;
}
-void attest_key_mngr_init(void)
+void attest_key_mngr_init(psa_key_id_t iak_id)
{
instance.is_iak_open = false;
- instance.iak_id = IAK_KEY_ID;
+ instance.iak_id = iak_id;
instance.iak_handle = -1;
}
void attest_key_mngr_deinit(void)
{
+ if (instance.is_iak_open && !instance.iak_id) {
+ psa_destroy_key(instance.iak_handle);
+ instance.is_iak_open = false;
+ }
}
psa_status_t attest_key_mngr_get_iak_handle(psa_key_handle_t *iak_handle)
@@ -73,20 +74,25 @@ psa_status_t attest_key_mngr_get_iak_handle(psa_key_handle_t *iak_handle)
if (!instance.is_iak_open) {
- status = psa_open_key(instance.iak_id, &instance.iak_handle);
+ if (instance.iak_id) {
- if (status == PSA_ERROR_STORAGE_FAILURE) {
-
- /* Accommodate deployments with no persistent storage
- * to support testing. In this case, a volatile key
- * is generated, indicated by an invalid key id.
+ /* A valid key id has been specified so treat as a persistent key
+ * that will normally already exist.
*/
- instance.iak_id = 0;
- }
+ status = psa_open_key(instance.iak_id, &instance.iak_handle);
- if (status != PSA_SUCCESS) {
+ if (status != PSA_SUCCESS) {
- /* First run and no key has been provisioned */
+ /* First run and no key has been provisioned */
+ status = generate_iak(instance.iak_id, &instance.iak_handle);
+ }
+ }
+ else {
+
+ /* An invalid key id has been specified which indicates that a
+ * volatile key should be generated. This is option is intended
+ * for test purposes only.
+ */
status = generate_iak(instance.iak_id, &instance.iak_handle);
}
diff --git a/components/service/attestation/key_mngr/attest_key_mngr.h b/components/service/attestation/key_mngr/attest_key_mngr.h
index 982c841..eaf46fc 100644
--- a/components/service/attestation/key_mngr/attest_key_mngr.h
+++ b/components/service/attestation/key_mngr/attest_key_mngr.h
@@ -9,6 +9,9 @@
#include <psa/crypto.h>
+/* Key ID for a volatile IAK (for test) */
+#define ATTEST_KEY_MNGR_VOLATILE_IAK (0)
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -25,8 +28,15 @@ extern "C" {
/**
* \brief Initialize the attest_key_mngr
+ *
+ * Initializes the attest_key_mngr. The provided key id should
+ * be used as the identifier for the IAK. If a key ID of zero
+ * is passed, a volatile IAK will be generated. This is useful
+ * for test purposes.
+ *
+ * \param[in] iak_id The key id for the IAK
*/
-void attest_key_mngr_init(void);
+void attest_key_mngr_init(psa_key_id_t iak_id);
/**
* \brief De-initialize the attest_key_mngr
diff --git a/components/service/attestation/provider/attest_provider.c b/components/service/attestation/provider/attest_provider.c
new file mode 100644
index 0000000..1e12717
--- /dev/null
+++ b/components/service/attestation/provider/attest_provider.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <protocols/service/attestation/packed-c/opcodes.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <service/attestation/key_mngr/attest_key_mngr.h>
+#include <service/attestation/reporter/attest_report.h>
+#include <psa/initial_attestation.h>
+#include "attest_provider.h"
+
+/* Service request handlers */
+static rpc_status_t get_token_handler(void *context, struct call_req* req);
+static rpc_status_t get_token_size_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}
+};
+
+struct rpc_interface *attest_provider_init(struct attest_provider *context, psa_key_id_t iak_id)
+{
+ struct rpc_interface *rpc_interface = NULL;
+
+ if (context) {
+
+ for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
+ context->serializers[encoding] = NULL;
+
+ service_provider_init(&context->base_provider, context,
+ handler_table, sizeof(handler_table)/sizeof(struct service_handler));
+
+ attest_key_mngr_init(iak_id);
+
+ rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
+ }
+
+ return rpc_interface;
+}
+
+void attest_provider_deinit(struct attest_provider *context)
+{
+ (void)context;
+ attest_key_mngr_deinit();
+}
+
+void attest_provider_register_serializer(struct attest_provider *context,
+ unsigned int encoding, const struct attest_provider_serializer *serializer)
+{
+ if (encoding < TS_RPC_ENCODING_LIMIT)
+ context->serializers[encoding] = serializer;
+}
+
+static const struct attest_provider_serializer *get_attest_serializer(
+ struct attest_provider *context, const struct call_req *req)
+{
+ const struct attest_provider_serializer *serializer = NULL;
+ unsigned int encoding = call_req_get_encoding(req);
+
+ if (encoding < TS_RPC_ENCODING_LIMIT) serializer = context->serializers[encoding];
+
+ return serializer;
+}
+
+static rpc_status_t get_token_handler(void *context, struct call_req* req)
+{
+ struct attest_provider *this_instance = (struct attest_provider*)context;
+ rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+
+ uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64];
+ size_t challenge_len = sizeof(challenge);
+
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct attest_provider_serializer *serializer = get_attest_serializer(this_instance, req);
+
+ if (serializer)
+ rpc_status = serializer->deserialize_get_token_req(req_buf, challenge, &challenge_len);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_key_handle_t iak_handle;
+ int opstatus = attest_key_mngr_get_iak_handle(&iak_handle);
+
+ if (opstatus == PSA_SUCCESS) {
+
+ const uint8_t *token = NULL;
+ size_t token_size = 0;
+
+ opstatus = attest_report_create(iak_handle,
+ (int32_t)call_req_get_caller_id(req),
+ challenge, challenge_len,
+ &token, &token_size);
+
+ if (opstatus == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_get_token_resp(resp_buf, token, token_size);
+ }
+
+ attest_report_destroy(token);
+ }
+
+ call_req_set_opstatus(req, opstatus);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t get_token_size_handler(void *context, struct call_req* req)
+{
+ struct attest_provider *this_instance = (struct attest_provider*)context;
+ rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+
+ uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64];
+ size_t challenge_len = sizeof(challenge);
+
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct attest_provider_serializer *serializer = get_attest_serializer(this_instance, req);
+
+ memset(challenge, 0, sizeof(challenge));
+
+ if (serializer)
+ rpc_status = serializer->deserialize_get_token_size_req(req_buf, &challenge_len);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_key_handle_t iak_handle;
+ int opstatus = attest_key_mngr_get_iak_handle(&iak_handle);
+
+ if (opstatus == PSA_SUCCESS) {
+
+ const uint8_t *token = NULL;
+ size_t token_size = 0;
+
+ opstatus = attest_report_create(iak_handle,
+ (int32_t)call_req_get_caller_id(req),
+ challenge, challenge_len,
+ &token, &token_size);
+
+ if (opstatus == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_get_token_size_resp(resp_buf, token_size);
+ }
+
+ attest_report_destroy(token);
+ }
+
+ call_req_set_opstatus(req, opstatus);
+ }
+
+ return rpc_status;
+}
diff --git a/components/service/attestation/provider/attest_provider.h b/components/service/attestation/provider/attest_provider.h
new file mode 100644
index 0000000..ed3b59a
--- /dev/null
+++ b/components/service/attestation/provider/attest_provider.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ATTEST_PROVIDER_H
+#define ATTEST_PROVIDER_H
+
+#include <rpc/common/endpoint/rpc_interface.h>
+#include <rpc_caller.h>
+#include <service/common/provider/service_provider.h>
+#include <service/attestation/provider/serializer/attest_provider_serializer.h>
+#include <service/attestation/key_mngr/attest_key_mngr.h>
+#include <protocols/rpc/common/packed-c/encoding.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The attest_provider is a service provider that implements an RPC interface
+ * for an instance of the attestation service.
+ */
+struct attest_provider
+{
+ struct service_provider base_provider;
+ const struct attest_provider_serializer *serializers[TS_RPC_ENCODING_LIMIT];
+};
+
+/**
+ * \brief Initialize an instance of the service provider
+ *
+ * Initializes a an attestation service provider. Returns an rpc_interface
+ * that should be associated with a suitable rpc endpoint.
+ *
+ * \param[in] context The instance to initialize
+ * \param[in] iak_id The key ID for the IAK
+ *
+ * \return An rpc_interface or NULL on failure
+ */
+struct rpc_interface *attest_provider_init(struct attest_provider *context,
+ psa_key_id_t iak_id);
+
+/**
+ * \brief Cleans up when the instance is no longer needed
+ *
+ * \param[in] context The instance to de-initialize
+ */
+void attest_provider_deinit(struct attest_provider *context);
+
+/**
+ * \brief Register a protocol serializer
+ *
+ * \param[in] context The instance
+ * \param[in] encoding Serialization encoding e.g. packed-c
+ * \param[in] serializer A concrete serializer
+ */
+void attest_provider_register_serializer(struct attest_provider *context,
+ unsigned int encoding, const struct attest_provider_serializer *serializer);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ATTEST_PROVIDER_H */
diff --git a/components/service/attestation/provider/component.cmake b/components/service/attestation/provider/component.cmake
new file mode 100644
index 0000000..cd30f53
--- /dev/null
+++ b/components/service/attestation/provider/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 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}/attest_provider.c"
+ )
diff --git a/components/service/attestation/provider/serializer/attest_provider_serializer.h b/components/service/attestation/provider/serializer/attest_provider_serializer.h
new file mode 100644
index 0000000..5334cba
--- /dev/null
+++ b/components/service/attestation/provider/serializer/attest_provider_serializer.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ATTEST_PROVIDER_SERIALIZER_H
+#define ATTEST_PROVIDER_SERIALIZER_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <rpc/common/endpoint/rpc_interface.h>
+
+/* Provides a common interface for parameter serialization operations
+ * for the attestation service provider. Allows alternative serialization
+ * protocols to be used without hard-wiring a particular protocol
+ * into the service provider code. A concrete serializer must
+ * implement this interface.
+ */
+struct attest_provider_serializer {
+
+ /* Operation: get_token */
+ rpc_status_t (*deserialize_get_token_req)(const struct call_param_buf *req_buf,
+ uint8_t *auth_challenge, size_t *auth_challenge_len);
+
+ rpc_status_t (*serialize_get_token_resp)(struct call_param_buf *resp_buf,
+ const uint8_t *token,
+ size_t token_size);
+
+ /* Operation: get_token_size */
+ rpc_status_t (*deserialize_get_token_size_req)(const struct call_param_buf *req_buf,
+ size_t *auth_challenge_len);
+
+ rpc_status_t (*serialize_get_token_size_resp)(struct call_param_buf *resp_buf,
+ size_t token_size);
+};
+
+#endif /* ATTEST_PROVIDER_SERIALIZER_H */
diff --git a/components/service/attestation/provider/serializer/packed-c/component.cmake b/components/service/attestation/provider/serializer/packed-c/component.cmake
new file mode 100644
index 0000000..7231a18
--- /dev/null
+++ b/components/service/attestation/provider/serializer/packed-c/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 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}/packedc_attest_provider_serializer.c"
+ )
diff --git a/components/service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.c b/components/service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.c
new file mode 100644
index 0000000..c2e5d56
--- /dev/null
+++ b/components/service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <string.h>
+#include <common/tlv/tlv.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/attestation/packed-c/get_token.h>
+#include <protocols/service/attestation/packed-c/get_token_size.h>
+#include "packedc_attest_provider_serializer.h"
+
+
+/* Operation: get_token */
+static rpc_status_t deserialize_get_token_req(const struct call_param_buf *req_buf,
+ uint8_t *auth_challenge, size_t *auth_challenge_len)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ struct tlv_const_iterator req_iter;
+ struct tlv_record decoded_record;
+
+ tlv_const_iterator_begin(&req_iter, (uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (tlv_find_decode(&req_iter,
+ TS_ATTESTATION_GET_TOKEN_IN_TAG_AUTH_CHALLENGE, &decoded_record)) {
+
+ if (decoded_record.length <= *auth_challenge_len) {
+
+ memcpy(auth_challenge, decoded_record.value, decoded_record.length);
+ *auth_challenge_len = decoded_record.length;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_get_token_resp(struct call_param_buf *resp_buf,
+ const uint8_t *token, size_t token_size)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ struct tlv_iterator resp_iter;
+
+ struct tlv_record token_record;
+ token_record.tag = TS_ATTESTATION_GET_TOKEN_OUT_TAG_TOKEN;
+ token_record.length = token_size;
+ token_record.value = token;
+
+ tlv_iterator_begin(&resp_iter, resp_buf->data, resp_buf->size);
+
+ if (tlv_encode(&resp_iter, &token_record)) {
+
+ resp_buf->data_len = tlv_required_space(token_size);
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Operation: get_token_size */
+static rpc_status_t deserialize_get_token_size_req(const struct call_param_buf *req_buf,
+ size_t *auth_challenge_len)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ struct ts_attestation_get_token_size_in recv_msg;
+ size_t expected_fixed_len = sizeof(struct ts_attestation_get_token_size_in);
+
+ if (expected_fixed_len <= req_buf->data_len) {
+
+ memcpy(&recv_msg, req_buf->data, expected_fixed_len);
+ *auth_challenge_len = recv_msg.challenge_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_get_token_size_resp(struct call_param_buf *resp_buf,
+ size_t token_size)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ struct ts_attestation_get_token_size_out resp_msg;
+ size_t fixed_len = sizeof(struct ts_attestation_get_token_size_out);
+
+ resp_msg.token_size = token_size;
+
+ if (fixed_len <= resp_buf->size) {
+
+ memcpy(resp_buf->data, &resp_msg, fixed_len);
+ resp_buf->data_len = fixed_len;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Singleton method to provide access to the serializer instance */
+const struct attest_provider_serializer *packedc_attest_provider_serializer_instance(void)
+{
+ static const struct attest_provider_serializer instance = {
+ deserialize_get_token_req,
+ serialize_get_token_resp,
+ deserialize_get_token_size_req,
+ serialize_get_token_size_resp
+ };
+
+ return &instance;
+}
diff --git a/components/service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.h b/components/service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.h
new file mode 100644
index 0000000..b73adf8
--- /dev/null
+++ b/components/service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PACKEDC_ATTEST_PROVIDER_SERIALIZER_H
+#define PACKEDC_ATTEST_PROVIDER_SERIALIZER_H
+
+#include <service/attestation/provider/serializer/attest_provider_serializer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Singleton method to provide access to the packed-c serializer
+ * for the attestation service provider.
+ */
+const struct attest_provider_serializer *packedc_attest_provider_serializer_instance(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* PACKEDC_ATTEST_PROVIDER_SERIALIZER_H */
diff --git a/components/service/attestation/reporter/psa/psa_attest_report.c b/components/service/attestation/reporter/psa/psa_attest_report.c
index 3228f1c..1f4ed0e 100644
--- a/components/service/attestation/reporter/psa/psa_attest_report.c
+++ b/components/service/attestation/reporter/psa/psa_attest_report.c
@@ -12,7 +12,9 @@
*/
#include <stdlib.h>
+#include <stdbool.h>
#include <psa/error.h>
+#include <psa/initial_attestation.h>
#include <service/attestation/reporter/attest_report.h>
#include <service/attestation/claims/claims_register.h>
#include "eat_serializer.h"
@@ -22,6 +24,7 @@
#define MAX_DEVICE_CLAIMS (50)
#define MAX_SW_CLAIMS (50)
+static bool validate_challenge(size_t len);
static void add_auth_challenge_claim(struct claim_vector *v, const uint8_t *data, size_t len);
static void add_client_id_claim(struct claim_vector *v, int32_t client_id);
static void add_no_sw_claim(struct claim_vector *v);
@@ -38,6 +41,8 @@ int attest_report_create(psa_key_handle_t key_handle, int32_t client_id,
*report = NULL;
*report_len = 0;
+ if (!validate_challenge(auth_challenge_len)) return PSA_ERROR_INVALID_ARGUMENT;
+
claim_vector_init(&device_claims, MAX_DEVICE_CLAIMS);
claim_vector_init(&sw_claims, MAX_SW_CLAIMS);
@@ -78,6 +83,15 @@ void attest_report_destroy(const uint8_t *report)
free((void*)report);
}
+static bool validate_challenge(size_t len)
+{
+ /* Only allow specific challenge lengths */
+ return
+ (len == PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32) ||
+ (len == PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48) ||
+ (len == PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64);
+}
+
static void add_auth_challenge_claim(struct claim_vector *v, const uint8_t *data, size_t len)
{
struct claim claim;
diff --git a/components/service/attestation/test/common/component.cmake b/components/service/attestation/test/common/component.cmake
new file mode 100644
index 0000000..5985c76
--- /dev/null
+++ b/components/service/attestation/test/common/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 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}/report_dump.cpp"
+ )
diff --git a/components/service/attestation/test/component/report_dump.cpp b/components/service/attestation/test/common/report_dump.cpp
index 65f4a85..65f4a85 100644
--- a/components/service/attestation/test/component/report_dump.cpp
+++ b/components/service/attestation/test/common/report_dump.cpp
diff --git a/components/service/attestation/test/component/report_dump.h b/components/service/attestation/test/common/report_dump.h
index 81becc5..81becc5 100644
--- a/components/service/attestation/test/component/report_dump.h
+++ b/components/service/attestation/test/common/report_dump.h
diff --git a/components/service/attestation/test/component/attestation_reporter_tests.cpp b/components/service/attestation/test/component/attestation_reporter_tests.cpp
index 02b91ac..c83dc3c 100644
--- a/components/service/attestation/test/component/attestation_reporter_tests.cpp
+++ b/components/service/attestation/test/component/attestation_reporter_tests.cpp
@@ -13,10 +13,10 @@
#include <service/attestation/claims/sources/preloaded/preloaded_claim_source.h>
#include <service/attestation/reporter/attest_report.h>
#include <service/attestation/key_mngr/attest_key_mngr.h>
+#include <service/attestation/test/common/report_dump.h>
#include <protocols/service/attestation/packed-c/eat.h>
#include <CppUTest/TestHarness.h>
#include <psa/crypto.h>
-#include "report_dump.h"
TEST_GROUP(AttestationReporterTests)
{
@@ -28,7 +28,7 @@ TEST_GROUP(AttestationReporterTests)
report_len;
psa_crypto_init();
- attest_key_mngr_init();
+ attest_key_mngr_init(ATTEST_KEY_MNGR_VOLATILE_IAK);
/* The set of registered claim_sources determines the content
* of a generated attestation source. The set and type of
diff --git a/components/service/attestation/test/component/component.cmake b/components/service/attestation/test/component/component.cmake
index 9db9a97..3bd7e56 100644
--- a/components/service/attestation/test/component/component.cmake
+++ b/components/service/attestation/test/component/component.cmake
@@ -10,5 +10,4 @@ endif()
target_sources(${TGT} PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/attestation_reporter_tests.cpp"
- "${CMAKE_CURRENT_LIST_DIR}/report_dump.cpp"
)
diff --git a/components/service/attestation/test/service/attestation_service_tests.cpp b/components/service/attestation/test/service/attestation_service_tests.cpp
new file mode 100644
index 0000000..9fe1f4d
--- /dev/null
+++ b/components/service/attestation/test/service/attestation_service_tests.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <limits.h>
+#include <string.h>
+#include <service/attestation/client/psa/iat_client.h>
+#include <protocols/rpc/common/packed-c/encoding.h>
+#include <service_locator.h>
+#include <psa/initial_attestation.h>
+#include <CppUTest/TestHarness.h>
+
+/*
+ * Service-level tests for the attestation service.
+ */
+TEST_GROUP(AttestationServiceTests)
+{
+ void setup()
+ {
+ struct rpc_caller *caller;
+ int status;
+
+ m_rpc_session_handle = NULL;
+ m_attest_service_context = NULL;
+
+ service_locator_init();
+
+ m_attest_service_context =
+ service_locator_query("sn:trustedfirmware.org:attestation:0", &status);
+ CHECK_TRUE(m_attest_service_context);
+
+ m_rpc_session_handle =
+ service_context_open(m_attest_service_context, TS_RPC_ENCODING_PACKED_C, &caller);
+ CHECK_TRUE(m_rpc_session_handle);
+
+ psa_iat_client_init(caller);
+ }
+
+ void teardown()
+ {
+ psa_iat_client_deinit();
+
+ service_context_close(m_attest_service_context, m_rpc_session_handle);
+ m_rpc_session_handle = NULL;
+
+ service_context_relinquish(m_attest_service_context);
+ m_attest_service_context = NULL;
+ }
+
+ rpc_session_handle m_rpc_session_handle;
+ struct service_context *m_attest_service_context;
+};
+
+TEST(AttestationServiceTests, checkTokenSize)
+{
+ uint8_t token_buf[PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE];
+ uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64];
+
+ memset(challenge, 0x87, sizeof(challenge));
+
+ /* Check that the get_token_size operation returns the same size
+ * as theh get_token operation.
+ */
+ psa_status_t status;
+ size_t reported_token_size = 0;
+ size_t actual_token_size = 0;
+
+ status = psa_initial_attest_get_token_size(
+ sizeof(challenge),
+ &reported_token_size);
+
+ LONGS_EQUAL(PSA_SUCCESS, status);
+ CHECK_TRUE(reported_token_size);
+
+ status = psa_initial_attest_get_token(
+ challenge, sizeof(challenge),
+ token_buf, sizeof(token_buf),
+ &actual_token_size);
+
+ LONGS_EQUAL(PSA_SUCCESS, status);
+ UNSIGNED_LONGS_EQUAL(reported_token_size, actual_token_size);
+}
+
+TEST(AttestationServiceTests, invalidChallengeLen)
+{
+ uint8_t token_buf[PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE];
+ uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64];
+
+ memset(challenge, 0x87, sizeof(challenge));
+
+ /* Check that invalid challenge lengths are rejected cleanly */
+ psa_status_t status;
+ size_t challenge_len;
+ size_t token_size = 0;
+
+ /* Zero length challenge */
+ challenge_len = 0;
+ status = psa_initial_attest_get_token_size(
+ challenge_len,
+ &token_size);
+ LONGS_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status);
+
+ status = psa_initial_attest_get_token(
+ challenge, challenge_len,
+ token_buf, sizeof(token_buf),
+ &token_size);
+ LONGS_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status);
+
+ /* Extra large challenge */
+ challenge_len = UINT32_MAX;
+ status = psa_initial_attest_get_token_size(
+ challenge_len,
+ &token_size);
+ LONGS_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status);
+
+ status = psa_initial_attest_get_token(
+ challenge, challenge_len,
+ token_buf, sizeof(token_buf),
+ &token_size);
+ LONGS_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status);
+
+ /* Slightly large challenge */
+ challenge_len = PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 + 1;
+ status = psa_initial_attest_get_token_size(
+ challenge_len,
+ &token_size);
+ LONGS_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status);
+
+ status = psa_initial_attest_get_token(
+ challenge, challenge_len,
+ token_buf, sizeof(token_buf),
+ &token_size);
+ LONGS_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status);
+}
+
+TEST(AttestationServiceTests, repeatedOperation)
+{
+ uint8_t token_buf[PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE];
+ uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48];
+
+ memset(challenge, 0x61, sizeof(challenge));
+
+ /* Check reports can be requested repeatedly without
+ * resource exhausation due to a memory leak.
+ */
+ for (int i = 0; i < 100; ++i) {
+
+ psa_status_t status;
+ size_t reported_token_size = 0;
+ size_t actual_token_size = 0;
+
+ status = psa_initial_attest_get_token_size(
+ sizeof(challenge),
+ &reported_token_size);
+
+ LONGS_EQUAL(PSA_SUCCESS, status);
+ CHECK_TRUE(reported_token_size);
+
+ status = psa_initial_attest_get_token(
+ challenge, sizeof(challenge),
+ token_buf, sizeof(token_buf),
+ &actual_token_size);
+
+ LONGS_EQUAL(PSA_SUCCESS, status);
+ UNSIGNED_LONGS_EQUAL(reported_token_size, actual_token_size);
+ }
+}
diff --git a/components/service/attestation/test/service/component.cmake b/components/service/attestation/test/service/component.cmake
new file mode 100644
index 0000000..a07e402
--- /dev/null
+++ b/components/service/attestation/test/service/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 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}/attestation_service_tests.cpp"
+ )
diff --git a/components/service/locator/standalone/services/attestation/attestation_service_context.cpp b/components/service/locator/standalone/services/attestation/attestation_service_context.cpp
new file mode 100644
index 0000000..302a536
--- /dev/null
+++ b/components/service/locator/standalone/services/attestation/attestation_service_context.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "attestation_service_context.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/event_log/mock/mock_event_log.h>
+
+attestation_service_context::attestation_service_context(const char *sn) :
+ standalone_service_context(sn),
+ m_attest_provider(),
+ m_event_log_claim_source()
+{
+
+}
+
+attestation_service_context::~attestation_service_context()
+{
+
+}
+
+void attestation_service_context::do_init()
+{
+ struct claim_source *claim_source;
+
+ /**
+ * Initialize and register claims sources to define the view of
+ * the device reflected by the attestation service. On a real
+ * device, the set of claim sources will be deployment specific
+ * to accommodate specific device architecture and product
+ * variations.
+ */
+ claims_register_init();
+
+ /* Boot measurement source - uses mock event log */
+ claim_source = event_log_claim_source_init(&m_event_log_claim_source,
+ mock_event_log_start(), mock_event_log_size());
+ claims_register_add_claim_source(CLAIM_CATEGORY_BOOT_MEASUREMENT, claim_source);
+
+ /* Initialize the attestation service provider */
+ struct rpc_interface *attest_ep =
+ attest_provider_init(&m_attest_provider, ATTEST_KEY_MNGR_VOLATILE_IAK);
+
+ attest_provider_register_serializer(&m_attest_provider,
+ TS_RPC_ENCODING_PACKED_C, packedc_attest_provider_serializer_instance());
+
+ standalone_service_context::set_rpc_interface(attest_ep);
+}
+
+void attestation_service_context::do_deinit()
+{
+ attest_provider_deinit(&m_attest_provider);
+ claims_register_deinit();
+}
diff --git a/components/service/locator/standalone/services/attestation/attestation_service_context.h b/components/service/locator/standalone/services/attestation/attestation_service_context.h
new file mode 100644
index 0000000..ad8d0ee
--- /dev/null
+++ b/components/service/locator/standalone/services/attestation/attestation_service_context.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STANDALONE_ATTESTATION_SERVICE_CONTEXT_H
+#define STANDALONE_ATTESTATION_SERVICE_CONTEXT_H
+
+#include <service/locator/standalone/standalone_service_context.h>
+#include <rpc/direct/direct_caller.h>
+#include <service/attestation/provider/attest_provider.h>
+#include <service/attestation/claims/sources/event_log/event_log_claim_source.h>
+
+
+class attestation_service_context : public standalone_service_context
+{
+public:
+ attestation_service_context(const char *sn);
+ virtual ~attestation_service_context();
+
+private:
+
+ void do_init();
+ void do_deinit();
+
+ struct attest_provider m_attest_provider;
+ struct event_log_claim_source m_event_log_claim_source;
+};
+
+#endif /* STANDALONE_ATTESTATION_SERVICE_CONTEXT_H */
diff --git a/components/service/locator/standalone/services/attestation/component.cmake b/components/service/locator/standalone/services/attestation/component.cmake
new file mode 100644
index 0000000..41fc031
--- /dev/null
+++ b/components/service/locator/standalone/services/attestation/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 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}/attestation_service_context.cpp"
+ )
diff --git a/components/service/locator/standalone/standalone_env.cpp b/components/service/locator/standalone/standalone_env.cpp
index 132b6d5..ab1a1be 100644
--- a/components/service/locator/standalone/standalone_env.cpp
+++ b/components/service/locator/standalone/standalone_env.cpp
@@ -9,6 +9,7 @@
#include <service/locator/standalone/services/internal-trusted-storage/its_service_context.h>
#include <service/locator/standalone/services/protected-storage/ps_service_context.h>
#include <service/locator/standalone/services/test-runner/test_runner_service_context.h>
+#include <service/locator/standalone/services/attestation/attestation_service_context.h>
#include "standalone_location_strategy.h"
#include "standalone_service_registry.h"
@@ -26,5 +27,8 @@ void service_locator_envinit(void)
static test_runner_service_context test_runner_context("sn:trustedfirmware.org:test-runner:0");
standalone_service_registry::instance()->regsiter_service_instance(&test_runner_context);
+ static attestation_service_context attestation_context("sn:trustedfirmware.org:attestation:0");
+ standalone_service_registry::instance()->regsiter_service_instance(&attestation_context);
+
service_locator_register_strategy(standalone_location_strategy());
}
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index 075538d..bb52dd5 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -41,6 +41,8 @@ add_components(
"components/service/locator/standalone/services/internal-trusted-storage"
"components/service/locator/standalone/services/protected-storage"
"components/service/locator/standalone/services/test-runner"
+ "components/service/locator/standalone/services/attestation"
+ "components/service/attestation/include"
"components/service/attestation/claims"
"components/service/attestation/claims/sources/preloaded"
"components/service/attestation/claims/sources/event_log"
@@ -48,7 +50,12 @@ add_components(
"components/service/attestation/claims/sources/event_log/test"
"components/service/attestation/reporter/psa"
"components/service/attestation/key_mngr"
+ "components/service/attestation/provider"
+ "components/service/attestation/provider/serializer/packed-c"
+ "components/service/attestation/client/psa"
+ "components/service/attestation/test/common"
"components/service/attestation/test/component"
+ "components/service/attestation/test/service"
"components/service/crypto/client/cpp"
"components/service/crypto/client/cpp/protobuf"
"components/service/crypto/client/cpp/packed-c"
diff --git a/deployments/libts/linux-pc/CMakeLists.txt b/deployments/libts/linux-pc/CMakeLists.txt
index f6ac33d..d1a96ae 100644
--- a/deployments/libts/linux-pc/CMakeLists.txt
+++ b/deployments/libts/linux-pc/CMakeLists.txt
@@ -31,6 +31,7 @@ add_components(
COMPONENTS
"components/rpc/direct"
"components/common/tlv"
+ "components/common/endian"
"components/service/common/include"
"components/service/common/serializer/protobuf"
"components/service/common/provider"
@@ -39,6 +40,16 @@ add_components(
"components/service/locator/standalone/services/internal-trusted-storage"
"components/service/locator/standalone/services/protected-storage"
"components/service/locator/standalone/services/test-runner"
+ "components/service/locator/standalone/services/attestation"
+ "components/service/attestation/include"
+ "components/service/attestation/claims"
+ "components/service/attestation/claims/sources/preloaded"
+ "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"
"components/service/crypto/provider/mbedcrypto"
"components/service/crypto/provider/mbedcrypto/trng_adapter/linux"
"components/service/crypto/provider/serializer/protobuf"
@@ -80,6 +91,14 @@ protobuf_generate_all(TGT "ts" NAMESPACE "protobuf" BASE_DIR "${TS_ROOT}/protoco
include(${TS_ROOT}/external/MbedTLS/MbedTLS.cmake)
target_link_libraries(ts PRIVATE mbedcrypto)
+# Qcbor
+include(${TS_ROOT}/external/qcbor/qcbor.cmake)
+target_link_libraries(ts PRIVATE qcbor)
+
+# t_cose
+include(${TS_ROOT}/external/t_cose/t_cose.cmake)
+target_link_libraries(ts PRIVATE t_cose)
+
#-------------------------------------------------------------------------------
# Test executable (libts-test) for testing libts static library
#
diff --git a/deployments/ts-service-test/linux-pc/CMakeLists.txt b/deployments/ts-service-test/linux-pc/CMakeLists.txt
index 4a86c87..ac4c237 100644
--- a/deployments/ts-service-test/linux-pc/CMakeLists.txt
+++ b/deployments/ts-service-test/linux-pc/CMakeLists.txt
@@ -80,6 +80,9 @@ add_components(
COMPONENTS
"components/service/test_runner/client/cpp"
"components/service/test_runner/test/service"
+ "components/service/attestation/include"
+ "components/service/attestation/client/psa"
+ "components/service/attestation/test/service"
)
#-------------------------------------------------------------------------------