Attest: Add CBOR/COSE encoding to IAT
Replace the temporary TLV encoding of the initial
attestation token (IAT) to the final CBOR/COSE encoding.
Change-Id: I4b6c936e501704fd193757e47ccbde657e85ede6
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
diff --git a/interface/include/psa_initial_attestation_api.h b/interface/include/psa_initial_attestation_api.h
index 5d650f0..bb479f4 100644
--- a/interface/include/psa_initial_attestation_api.h
+++ b/interface/include/psa_initial_attestation_api.h
@@ -26,7 +26,7 @@
* \brief PSA INITIAL ATTESTATION API version
*/
#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (0)
-#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (1)
+#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (9)
/**
* \enum psa_attest_err_t
@@ -181,19 +181,6 @@
*/
/**
- * Calculated based on:
- * - COSE header
- * - Algorithm identifier
- * - Key ID
- * - Claims in initial attestation token
- * - COSE Signature
- *
- * This size (in bytes) is a maximum value, actual token size can be smaller.
- */
-/* FixMe: Just initial value it must be updated if claims are fixed */
-#define PSA_INITIAL_ATTEST_TOKEN_SIZE (512u)
-
-/**
* \brief Get initial attestation token
*
* \param[in] challenge_obj Pointer to buffer where challenge input is
diff --git a/secure_fw/services/initial_attestation/CMakeLists.inc b/secure_fw/services/initial_attestation/CMakeLists.inc
index 5373dcd..9644905 100644
--- a/secure_fw/services/initial_attestation/CMakeLists.inc
+++ b/secure_fw/services/initial_attestation/CMakeLists.inc
@@ -37,6 +37,7 @@
"${INITIAL_ATTESTATION_DIR}/attestation_core.c"
"${INITIAL_ATTESTATION_DIR}/attestation_crypto_stub.c"
"${INITIAL_ATTESTATION_DIR}/attestation_key.c"
+ "${INITIAL_ATTESTATION_DIR}/attest_token.c"
)
#Setting include directories
@@ -47,6 +48,8 @@
embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core ABSOLUTE)
embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm ABSOLUTE)
embedded_include_directories(PATH ${TFM_ROOT_DIR}/lib/ext/qcbor/inc ABSOLUTE)
+ embedded_include_directories(PATH ${TFM_ROOT_DIR}/lib/t_cose/inc ABSOLUTE)
+ embedded_include_directories(PATH ${TFM_ROOT_DIR}/lib/t_cose/src ABSOLUTE)
embedded_include_directories(PATH ${INITIAL_ATTESTATION_DIR} ABSOLUTE)
set(BUILD_CMSIS_CORE Off)
diff --git a/secure_fw/services/initial_attestation/attest_eat_defines.h b/secure_fw/services/initial_attestation/attest_eat_defines.h
new file mode 100644
index 0000000..002e2a1
--- /dev/null
+++ b/secure_fw/services/initial_attestation/attest_eat_defines.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __ATTEST_EAT_DEFINES_H__
+#define __ATTEST_EAT_DEFINES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EAT_CBOR_ARM_RANGE_BASE (-75000)
+#define EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION (EAT_CBOR_ARM_RANGE_BASE - 0)
+#define EAT_CBOR_ARM_LABEL_CLIENT_ID (EAT_CBOR_ARM_RANGE_BASE - 1)
+#define EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE (EAT_CBOR_ARM_RANGE_BASE - 2)
+#define EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID (EAT_CBOR_ARM_RANGE_BASE - 3)
+#define EAT_CBOR_ARM_LABEL_BOOT_SEED (EAT_CBOR_ARM_RANGE_BASE - 4)
+#define EAT_CBOR_ARM_LABEL_HW_VERSION (EAT_CBOR_ARM_RANGE_BASE - 5)
+#define EAT_CBOR_ARM_LABEL_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 6)
+#define EAT_CBOR_ARM_LABEL_NO_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 7)
+#define EAT_CBOR_ARM_LABEL_CHALLENGE (EAT_CBOR_ARM_RANGE_BASE - 8)
+#define EAT_CBOR_ARM_LABEL_UEID (EAT_CBOR_ARM_RANGE_BASE - 9)
+#define EAT_CBOR_ARM_LABEL_ORIGINATION (EAT_CBOR_ARM_RANGE_BASE - 10)
+
+#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_TYPE (1)
+#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_VALUE (2)
+#define EAT_CBOR_SW_COMPONENT_SECURITY_EPOCH (3)
+#define EAT_CBOR_SW_COMPONENT_VERSION (4)
+#define EAT_CBOR_SW_COMPONENT_SIGNER_ID (5)
+#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC (6)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ATTEST_EAT_DEFINES_H__ */
diff --git a/secure_fw/services/initial_attestation/attestation.h b/secure_fw/services/initial_attestation/attestation.h
index 71a3835..356132d 100644
--- a/secure_fw/services/initial_attestation/attestation.h
+++ b/secure_fw/services/initial_attestation/attestation.h
@@ -15,30 +15,6 @@
extern "C" {
#endif
-/* Extension of shared data TLVs, defined in bl2/include/tfm_boot_status.h */
-/* #define GENERAL_BOOT_SEED 0x00 */ /* Defined in tfm_boot_status.h */
-#define GENERAL_INSTANCE_ID 0x01
-#define GENERAL_CHALLENGE 0x02
-#define GENERAL_CALLER_ID 0x03
-#define GENERAL_IMPLEMENTATION_ID 0x04
-#define GENERAL_HW_VERSION 0x05
-#define GENERAL_SECURITY_LIFECYCLE 0x06
-
-#define TLV_MINOR_IAS_INSTANCE_ID \
- ((SW_GENERAL << 6) | GENERAL_INSTANCE_ID)
-#define TLV_MINOR_IAS_CHALLENGE \
- ((SW_GENERAL << 6) | GENERAL_CHALLENGE)
-#define TLV_MINOR_IAS_CALLER_ID \
- ((SW_GENERAL << 6) | GENERAL_CALLER_ID)
-#define TLV_MINOR_IAS_IMPLEMENTATION_ID \
- ((SW_GENERAL << 6) | GENERAL_IMPLEMENTATION_ID)
-#define TLV_MINOR_IAS_HW_VERSION \
- ((SW_GENERAL << 6) | GENERAL_HW_VERSION)
-#define TLV_MINOR_IAS_SECURITY_LIFECYCLE \
- ((SW_GENERAL << 6) | GENERAL_SECURITY_LIFECYCLE)
-#define TLV_MINOR_IAS_IAT_VERSION \
- ((SW_GENERAL << 6) | GENERAL_IAT_VERSION)
-
/*!
* \brief Initialise the initial attestation service during the TF-M boot up
* process.
diff --git a/secure_fw/services/initial_attestation/attestation_core.c b/secure_fw/services/initial_attestation/attestation_core.c
index c167342..a0c396b 100644
--- a/secure_fw/services/initial_attestation/attestation_core.c
+++ b/secure_fw/services/initial_attestation/attestation_core.c
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <string.h>
#include <stddef.h>
-#include "psa_initial_attestation_api.h"
#include "attestation.h"
#include "secure_utilities.h"
#include "tfm_api.h"
@@ -19,9 +18,16 @@
#include "platform/include/tfm_plat_device_id.h"
#include "platform/include/tfm_plat_boot_seed.h"
#include "tfm_attest_hal.h"
+#include "attest_token.h"
+#include "attest_eat_defines.h"
+#include "t_cose_defines.h"
#define MAX_BOOT_STATUS 512
+/* Indicates how to encode SW components' measurements in the CBOR map */
+#define EAT_SW_COMPONENT_NESTED 1 /* Nested map */
+#define EAT_SW_COMPONENT_NOT_NESTED 0 /* Flat structure */
+
/*!
* \var boot_status
*
@@ -53,7 +59,60 @@
}
/*!
- * \brief Static function to look up all entries in the shared data area
+ * \brief Static function to map return values between \ref attest_token_err_t
+ * and \ref psa_attest_err_t
+ *
+ * \param[in] token_err Token encoding return value
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static inline enum psa_attest_err_t
+error_mapping(enum attest_token_err_t token_err)
+{
+ switch (token_err) {
+ case ATTEST_TOKEN_ERR_SUCCESS:
+ return PSA_ATTEST_ERR_SUCCESS;
+ break;
+ case ATTEST_TOKEN_ERR_TOO_SMALL:
+ return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
+ break;
+ default:
+ return PSA_ATTEST_ERR_GENERAL;
+ }
+}
+
+/*!
+ * \brief Static function to convert a pointer and size info to unsigned
+ * integer number. Max 32bits unsigned integers are supported.
+ *
+ * \param[in] int_ptr Pointer to the unsigned integer
+ * \param[in] len Size of the unsigned integers in bytes
+ * \param[in] value Pointer where to store the converted value
+ *
+ * \return Returns 0 on success and -1 on error.
+ */
+static inline int32_t get_uint(const void *int_ptr,
+ size_t len,
+ uint32_t *value)
+{
+ switch (len) {
+ case 1:
+ *value = (uint32_t)(*(uint8_t *)(int_ptr));
+ break;
+ case 2:
+ *value = (uint32_t)(*(uint16_t *)(int_ptr));
+ break;
+ case 4:
+ *value = (uint32_t)(*(uint32_t *)(int_ptr));
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+/*!
+ * \brief Static function to look up all entires in the shared data area
* (boot status) which belong to a specific module.
*
* \param[in] module The identifier of SW module to look up based on this
@@ -96,8 +155,8 @@
tlv_curr = (*tlv_ptr) + tlv_entry->tlv_len;
}
- /* Iterates over the TLV section and copy TLVs with requested module
- * identifier to the provided buffer.
+ /* Iterates over the TLV section and returns the address and size of TLVs
+ * with requested module identifier
*/
for (; tlv_curr < tlv_end; tlv_curr += tlv_entry->tlv_len) {
tlv_entry = (struct shared_data_tlv_entry *)tlv_curr;
@@ -113,126 +172,219 @@
}
/*!
- * \brief Static function to copy a TLV entry from shared data section to the
- * attestation token.
+ * \brief Static function to add SW component related claims to attestation
+ * token in CBOR format.
*
- * \param[in] tlv_len The length of TLV entry in bytes
- * \param[in] tlv_ptr Pointer from where to copy the TLV entry
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * This function translates between TLV and CBOR encoding.
*
- * \return Returns 0 on success. Otherwise, 1.
- */
-static uint32_t attest_copy_tlv(uint16_t tlv_len,
- const uint8_t *tlv_ptr,
- uint32_t token_buf_size,
- uint8_t *token_buf)
-{
- struct shared_data_tlv_header *tlv_header;
- uint8_t *next_tlv = token_buf;
-
- tlv_header = (struct shared_data_tlv_header *)token_buf;
- if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
- return 1;
- }
-
- if (tlv_header->tlv_tot_len + tlv_len > token_buf_size) {
- return 1;
- }
-
- next_tlv += tlv_header->tlv_tot_len;
- tlv_header->tlv_tot_len += tlv_len;
- tfm_memcpy(next_tlv, tlv_ptr, tlv_len);
-
- return 0;
-}
-
-/*!
- * \brief Static function to add a TLV entry to the attestation token.
- *
- * \param[in] minor_type The identifier of the TLV entry
- * \param[in] size Size of the TLV entry in bytes
- * \param[in] data Pointer to the buffer which stores the TLV entry
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
- *
- * \return Returns 0 on success. Otherwise, 1.
- */
-static uint32_t attest_add_tlv(uint16_t minor_type,
- uint32_t size,
- const uint8_t *data,
- uint32_t token_buf_size,
- uint8_t *token_buf)
-{
- struct shared_data_tlv_header *tlv_header;
- struct shared_data_tlv_entry *tlv_entry;
- uint8_t *next_tlv = token_buf;
-
- tlv_header = (struct shared_data_tlv_header *)token_buf;
- if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
- return 1;
- }
-
- if (tlv_header->tlv_tot_len + SHARED_DATA_ENTRY_SIZE(size) >
- token_buf_size) {
- return 1;
- }
-
- next_tlv += tlv_header->tlv_tot_len;
- tlv_header->tlv_tot_len += SHARED_DATA_ENTRY_SIZE(size);
-
- tlv_entry = (struct shared_data_tlv_entry *)next_tlv;
- tlv_entry->tlv_type = SET_TLV_TYPE(TLV_MAJOR_IAS, minor_type);
- tlv_entry->tlv_len = SHARED_DATA_ENTRY_SIZE(size);
-
- next_tlv += SHARED_DATA_ENTRY_HEADER_SIZE;
- tfm_memcpy(next_tlv, data, size);
-
- return 0;
-}
-
-/*!
- * \brief Static function to initalise the token buffer. Add TLV data header to
- * it.
- *
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * \param[in] token_ctx Attestation token encoding context
+ * \param[in] tlv_id The ID of claim
+ * \param[in] claim_value A structure which carries a pointer and size about
+ * the data item to be added to the token
*
* \return Returns error code as specified in \ref psa_attest_err_t
*/
static enum psa_attest_err_t
-attest_init_token(uint32_t token_buf_size, uint8_t *token_buf)
+attest_add_sw_component_claim(struct attest_token_ctx *token_ctx,
+ uint8_t tlv_id,
+ const struct useful_buf_c *claim_value)
{
- struct shared_data_tlv_header *tlv_header;
+ int32_t res;
+ uint32_t value;
- if (SHARED_DATA_HEADER_SIZE > token_buf_size) {
- return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
+ switch (tlv_id) {
+ case SW_MEASURE_VALUE:
+ attest_token_add_bstr(token_ctx,
+ EAT_CBOR_SW_COMPONENT_MEASUREMENT_VALUE,
+ claim_value);
+ break;
+ case SW_MEASURE_TYPE:
+ attest_token_add_tstr(token_ctx,
+ EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC,
+ claim_value);
+ break;
+ case SW_VERSION:
+ attest_token_add_tstr(token_ctx,
+ EAT_CBOR_SW_COMPONENT_VERSION,
+ claim_value);
+ break;
+ case SW_SIGNER_ID:
+ attest_token_add_bstr(token_ctx,
+ EAT_CBOR_SW_COMPONENT_SIGNER_ID,
+ claim_value);
+ break;
+ case SW_EPOCH:
+ res = get_uint(claim_value->ptr, claim_value->len, &value);
+ if (res) {
+ return PSA_ATTEST_ERR_GENERAL;
+ }
+ attest_token_add_integer(token_ctx,
+ EAT_CBOR_SW_COMPONENT_SECURITY_EPOCH,
+ (int64_t)value);
+ break;
+ case SW_TYPE:
+ attest_token_add_tstr(token_ctx,
+ EAT_CBOR_SW_COMPONENT_MEASUREMENT_TYPE,
+ claim_value);
+ break;
+ default:
+ return PSA_ATTEST_ERR_GENERAL;
}
- tlv_header = (struct shared_data_tlv_header *)token_buf;
- tlv_header->tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
- tlv_header->tlv_tot_len = SHARED_DATA_HEADER_SIZE;
-
return PSA_ATTEST_ERR_SUCCESS;
}
/*!
- * \brief Static function to add SW modules related claims to attestation token.
+ * \brief Static function to add the measurement data of a single SW components
+ * to the attestation token.
*
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * \param[in] token_ctx Token encoding context
+ * \param[in] module SW component identifier
+ * \param[in] tlv_address Address of the first TLV entry in the boot status,
+ * which belongs to this SW component.
+ * \param[in] nested_map Flag to indicate that how to encode the SW component
+ * measurement data: nested map or non-nested map.
*
* \return Returns error code as specified in \ref psa_attest_err_t
*/
static enum psa_attest_err_t
-attest_add_sw_module_claims(uint32_t token_buf_size, uint8_t *token_buf)
+attest_add_single_sw_measurment(struct attest_token_ctx *token_ctx,
+ uint32_t module,
+ uint8_t *tlv_address,
+ uint32_t nested_map)
+{
+ struct shared_data_tlv_entry *tlv_entry =
+ (struct shared_data_tlv_entry *) tlv_address;
+ uint16_t tlv_len = tlv_entry->tlv_len;
+ uint8_t tlv_id = GET_IAS_CLAIM(tlv_entry->tlv_type);
+ uint8_t *tlv_ptr = tlv_address;
+ int32_t found = 1;
+ struct useful_buf_c claim_value;
+ enum psa_attest_err_t res;
+ QCBOREncodeContext *cbor_encode_ctx;
+
+ cbor_encode_ctx = attest_token_borrow_cbor_cntxt(token_ctx);
+
+ /* Open nested map for SW component measurement claims */
+ if (nested_map) {
+ QCBOREncode_OpenMapInMapN(cbor_encode_ctx,
+ EAT_CBOR_SW_COMPONENT_MEASUREMENT_VALUE);
+ }
+
+ /* Look up all measurement TLV entry which belongs to the SW component */
+ while (found) {
+ /* Here only measurement claims are added to the token */
+ if (GET_IAS_MEASUREMENT_CLAIM(tlv_id)) {
+ claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE;
+ claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE;
+ res = attest_add_sw_component_claim(token_ctx,
+ tlv_id,
+ &claim_value);
+ if (res != PSA_ATTEST_ERR_SUCCESS) {
+ return res;
+ }
+ }
+
+ /* Look up next entry it can be non-measurement claim*/
+ found = attest_get_tlv_by_module(module, &tlv_id,
+ &tlv_len, &tlv_ptr);
+ if (found == -1) {
+ return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
+ }
+ }
+
+ if (nested_map) {
+ QCBOREncode_CloseMap(cbor_encode_ctx);
+ }
+
+ return PSA_ATTEST_ERR_SUCCESS;
+}
+
+/*!
+ * \brief Static function to add the claims of a single SW components to the
+ * attestation token.
+ *
+ * \param[in] token_ctx Token encoding context
+ * \param[in] module SW component identifier
+ * \param[in] tlv_address Address of the first TLV entry in the boot status,
+ * which belongs to this SW component.
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static enum psa_attest_err_t
+attest_add_single_sw_component(struct attest_token_ctx *token_ctx,
+ uint32_t module,
+ uint8_t *tlv_address)
+{
+ struct shared_data_tlv_entry *tlv_entry =
+ (struct shared_data_tlv_entry *) tlv_address;
+ uint16_t tlv_len = tlv_entry->tlv_len;
+ uint8_t tlv_id = GET_IAS_CLAIM(tlv_entry->tlv_type);
+ uint8_t *tlv_ptr = tlv_address;
+ int32_t found = 1;
+ uint32_t measurement_claim_cnt = 0;
+ struct useful_buf_c claim_value;
+ QCBOREncodeContext *cbor_encode_ctx;
+
+ /* Open map which stores claims belong to a SW component */
+ cbor_encode_ctx = attest_token_borrow_cbor_cntxt(token_ctx);
+ QCBOREncode_OpenMap(cbor_encode_ctx);
+
+ /*Look up all TLV entry which belongs to the same SW component */
+ while (found) {
+ /* Check whether claim is measurement claim */
+ if (GET_IAS_MEASUREMENT_CLAIM(tlv_id)) {
+ if (measurement_claim_cnt == 0) {
+ /* Call only once when first measurement claim found */
+ measurement_claim_cnt++;
+ attest_add_single_sw_measurment(token_ctx,
+ module,
+ tlv_ptr,
+ EAT_SW_COMPONENT_NOT_NESTED);
+ }
+ } else {
+ /* Adding top level claims */
+ claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE;
+ claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE;
+ attest_add_sw_component_claim(token_ctx, tlv_id, &claim_value);
+ }
+
+ /* Look up next entry which belongs to SW component */
+ found = attest_get_tlv_by_module(module, &tlv_id,
+ &tlv_len, &tlv_ptr);
+ if (found == -1) {
+ return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
+ }
+ }
+
+ /* Close map which stores claims belong to a SW component */
+ QCBOREncode_CloseMap(cbor_encode_ctx);
+
+ return PSA_ATTEST_ERR_SUCCESS;
+}
+
+/*!
+ * \brief Static function to add the claims of all SW components to the
+ * attestation token.
+ *
+ * \param[in] token_ctx Token encoding context
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static enum psa_attest_err_t
+attest_add_all_sw_components(struct attest_token_ctx *token_ctx)
{
uint16_t tlv_len;
uint8_t *tlv_ptr;
- uint8_t claim;
- uint32_t found;
- uint32_t res;
- int module;
+ uint8_t tlv_id;
+ int32_t found;
+ uint32_t module;
+ QCBOREncodeContext *cbor_encode_ctx;
+
+ /* Open array which stores SW components claims */
+ cbor_encode_ctx = attest_token_borrow_cbor_cntxt(token_ctx);
+ QCBOREncode_OpenArrayInMapN(cbor_encode_ctx,
+ EAT_CBOR_ARM_LABEL_SW_COMPONENTS);
/* Starting from module 1, because module 0 contains general claims which
* are not related to SW module(i.e: boot_seed)
@@ -243,59 +395,33 @@
*/
tlv_ptr = NULL;
- /*Look up all entry which belongs to the same SW module */
- do {
- found = attest_get_tlv_by_module(module, &claim,
- &tlv_len, &tlv_ptr);
+ /* Look up the first TLV entry which belongs to the SW module */
+ found = attest_get_tlv_by_module(module, &tlv_id,
+ &tlv_len, &tlv_ptr);
+ if (found == -1) {
+ return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
+ }
- if (found == -1) {
- return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
- }
-
- if (found == 1) {
- switch (claim) {
- /* Intentional fall through
- * Claims are handled in the same way with TLV encoding, they
- * are just copied to the token buffer.
- * But later in case of CBOR encoding they must be
- * differentiated in order to apply the corresponding claim
- * label.
- *
- * FixMe: Handle cases individually and apply the proper EAT
- * label
- */
- case SW_MEASURE_VALUE:
- case SW_MEASURE_TYPE:
- case SW_VERSION:
- case SW_SIGNER_ID:
- case SW_EPOCH:
- case SW_TYPE:
- res = attest_copy_tlv(tlv_len, tlv_ptr,
- token_buf_size, token_buf);
- if (res != 0) {
- return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
- }
- break;
- default:
- return PSA_ATTEST_ERR_GENERAL;
- }
- }
- } while (found == 1);
+ if (found == 1) {
+ attest_add_single_sw_component(token_ctx, module, tlv_ptr);
+ }
}
+ /* Close array which stores SW components claims*/
+ QCBOREncode_CloseArray(cbor_encode_ctx);
+
return PSA_ATTEST_ERR_SUCCESS;
}
/*!
* \brief Static function to add boot seed claim to attestation token.
*
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * \param[in] token_ctx Token encoding context
*
* \return Returns error code as specified in \ref psa_attest_err_t
*/
static enum psa_attest_err_t
-attest_add_boot_seed_claim(uint32_t token_buf_size, uint8_t *token_buf)
+attest_add_boot_seed_claim(struct attest_token_ctx *token_ctx)
{
/* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory
* type is configured in the MPU to be normal, instead of device,
@@ -304,20 +430,18 @@
__attribute__ ((aligned(4)))
uint8_t boot_seed[BOOT_SEED_SIZE];
enum tfm_plat_err_t res;
+ struct useful_buf_c claim_value;
res = tfm_plat_get_boot_seed(sizeof(boot_seed), boot_seed);
if (res != TFM_PLAT_ERR_SUCCESS) {
return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
}
- res = attest_add_tlv(TLV_MINOR_IAS_BOOT_SEED,
- BOOT_SEED_SIZE,
- boot_seed,
- token_buf_size,
- token_buf);
- if (res != 0) {
- return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
- }
+ claim_value.ptr = boot_seed;
+ claim_value.len = BOOT_SEED_SIZE;
+ attest_token_add_bstr(token_ctx,
+ EAT_CBOR_ARM_LABEL_BOOT_SEED,
+ &claim_value);
return PSA_ATTEST_ERR_SUCCESS;
}
@@ -330,13 +454,12 @@
/*!
* \brief Static function to add instance id claim to attestation token.
*
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * \param[in] token_ctx Token encoding context
*
* \return Returns error code as specified in \ref psa_attest_err_t
*/
static enum psa_attest_err_t
-attest_add_instance_id_claim(uint32_t token_buf_size, uint8_t *token_buf)
+attest_add_instance_id_claim(struct attest_token_ctx *token_ctx)
{
/* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory
* type is configured in the MPU to be normal, instead of device,
@@ -344,23 +467,20 @@
*/
__attribute__ ((aligned(4)))
uint8_t instance_id[INSTANCE_ID_MAX_SIZE];
- uint32_t res;
enum tfm_plat_err_t res_plat;
uint32_t size = sizeof(instance_id);
+ struct useful_buf_c claim_value;
res_plat = tfm_plat_get_instance_id(&size, instance_id);
if (res_plat != TFM_PLAT_ERR_SUCCESS) {
return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
}
- res = attest_add_tlv(TLV_MINOR_IAS_INSTANCE_ID,
- size,
- instance_id,
- token_buf_size,
- token_buf);
- if (res != 0) {
- return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
- }
+ claim_value.ptr = instance_id;
+ claim_value.len = size;
+ attest_token_add_bstr(token_ctx,
+ EAT_CBOR_ARM_LABEL_UEID,
+ &claim_value);
return PSA_ATTEST_ERR_SUCCESS;
}
@@ -368,13 +488,12 @@
/*!
* \brief Static function to add implementation id claim to attestation token.
*
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * \param[in] token_ctx Token encoding context
*
* \return Returns error code as specified in \ref psa_attest_err_t
*/
static enum psa_attest_err_t
-attest_add_implementation_id_claim(uint32_t token_buf_size, uint8_t *token_buf)
+attest_add_implementation_id_claim(struct attest_token_ctx *token_ctx)
{
/* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory
* type is configured in the MPU to be normal, instead of device,
@@ -382,23 +501,20 @@
*/
__attribute__ ((aligned(4)))
uint8_t implementation_id[IMPLEMENTATION_ID_MAX_SIZE];
- uint32_t res;
enum tfm_plat_err_t res_plat;
uint32_t size = sizeof(implementation_id);
+ struct useful_buf_c claim_value;
res_plat = tfm_plat_get_implementation_id(&size, implementation_id);
if (res_plat != TFM_PLAT_ERR_SUCCESS) {
return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
}
- res = attest_add_tlv(TLV_MINOR_IAS_IMPLEMENTATION_ID,
- size,
- implementation_id,
- token_buf_size,
- token_buf);
- if (res != 0) {
- return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
- }
+ claim_value.ptr = implementation_id;
+ claim_value.len = size;
+ attest_token_add_bstr(token_ctx,
+ EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID,
+ &claim_value);
return PSA_ATTEST_ERR_SUCCESS;
}
@@ -406,13 +522,12 @@
/*!
* \brief Static function to add hardware version claim to attestation token.
*
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * \param[in] token_ctx Token encoding context
*
* \return Returns error code as specified in \ref psa_attest_err_t
*/
static enum psa_attest_err_t
-attest_add_hw_version_claim(uint32_t token_buf_size, uint8_t *token_buf)
+attest_add_hw_version_claim(struct attest_token_ctx *token_ctx)
{
/* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory
* type is configured in the MPU to be normal, instead of device,
@@ -420,23 +535,20 @@
*/
__attribute__ ((aligned(4)))
uint8_t hw_version[HW_VERSION_MAX_SIZE];
- uint32_t res;
enum tfm_plat_err_t res_plat;
uint32_t size = sizeof(hw_version);
+ struct useful_buf_c claim_value;
res_plat = tfm_plat_get_hw_version(&size, hw_version);
if (res_plat != TFM_PLAT_ERR_SUCCESS) {
return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
}
- res = attest_add_tlv(TLV_MINOR_IAS_HW_VERSION,
- size,
- hw_version,
- token_buf_size,
- token_buf);
- if (res != 0) {
- return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
- }
+ claim_value.ptr = hw_version;
+ claim_value.len = size;
+ attest_token_add_tstr(token_ctx,
+ EAT_CBOR_ARM_LABEL_HW_VERSION,
+ &claim_value);
return PSA_ATTEST_ERR_SUCCESS;
}
@@ -445,13 +557,12 @@
/*!
* \brief Static function to add caller id claim to attestation token.
*
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * \param[in] token_ctx Token encoding context
*
* \return Returns error code as specified in \ref psa_attest_err_t
*/
static enum psa_attest_err_t
-attest_add_caller_id_claim(uint32_t token_buf_size, uint8_t *token_buf)
+attest_add_caller_id_claim(struct attest_token_ctx *token_ctx)
{
uint32_t res;
int32_t caller_id;
@@ -461,14 +572,9 @@
return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
}
- res = attest_add_tlv(TLV_MINOR_IAS_CALLER_ID,
- sizeof(int32_t),
- (uint8_t *)&caller_id,
- token_buf_size,
- token_buf);
- if (res != 0) {
- return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
- }
+ attest_token_add_integer(token_ctx,
+ EAT_CBOR_ARM_LABEL_CLIENT_ID,
+ (int64_t)caller_id);
return PSA_ATTEST_ERR_SUCCESS;
}
@@ -476,27 +582,20 @@
/*!
* \brief Static function to add security lifecycle claim to attestation token.
*
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * \param[in] token_ctx Token encoding context
*
* \return Returns error code as specified in \ref psa_attest_err_t
*/
static enum psa_attest_err_t
-attest_add_security_lifecycle_claim(uint32_t token_buf_size, uint8_t *token_buf)
+attest_add_security_lifecycle_claim(struct attest_token_ctx *token_ctx)
{
- uint32_t res;
enum tfm_security_lifecycle_t security_lifecycle;
security_lifecycle = tfm_attest_hal_get_security_lifecycle();
- res = attest_add_tlv(TLV_MINOR_IAS_SECURITY_LIFECYCLE,
- sizeof(enum tfm_security_lifecycle_t),
- (uint8_t *)&security_lifecycle,
- token_buf_size,
- token_buf);
- if (res != 0) {
- return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
- }
+ attest_token_add_integer(token_ctx,
+ EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE,
+ (int64_t)security_lifecycle);
return PSA_ATTEST_ERR_SUCCESS;
}
@@ -504,54 +603,24 @@
/*!
* \brief Static function to add challenge claim to attestation token.
*
- * \param[in] challenge_buf_size Size of challenge object in bytes
- * \param[in] challenge_buf Pointer to buffer which stores the challenge
- * object
- * \param[in] token_buf_size Size of token buffer in bytes
- * \param[out] token_buf Pointer to buffer which stores the token
+ * \param[in] token_ctx Token encoding context
+ * \param[in] challenge Pointer to buffer which stores the challenge
*
* \return Returns error code as specified in \ref psa_attest_err_t
*/
static enum psa_attest_err_t
-attest_add_challenge_claim(uint32_t challenge_buf_size,
- const uint8_t *challenge_buf,
- uint32_t token_buf_size,
- uint8_t *token_buf)
+attest_add_challenge_claim(struct attest_token_ctx *token_ctx,
+ const struct useful_buf_c *challenge)
{
- uint32_t res;
-
- res = attest_add_tlv(TLV_MINOR_IAS_CHALLENGE,
- challenge_buf_size,
- challenge_buf,
- token_buf_size,
- token_buf);
- if (res != 0) {
- return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
- }
+ attest_token_add_bstr(token_ctx, EAT_CBOR_ARM_LABEL_CHALLENGE, challenge);
return PSA_ATTEST_ERR_SUCCESS;
}
/*!
- * \brief Static function to retrieve the constructed attestation token's size.
- *
- * \param[in] token_buf Pointer to buffer which stores the token
- *
- * \return Returns the size of token in bytes
- */
-static uint32_t attest_get_token_size(const uint8_t *token_buf)
-{
- struct shared_data_tlv_header *tlv_header;
-
- tlv_header = (struct shared_data_tlv_header *)token_buf;
-
- return tlv_header->tlv_tot_len;
-}
-
-/*!
* \brief Static function to verify the input challenge size
*
- * Only discrete sizes are accepted.
+ * Only discrete sizes are accepted.
*
* \param[in] challenge_size Size of challenge object in bytes.
*
@@ -572,11 +641,129 @@
return PSA_ATTEST_ERR_INVALID_INPUT;
}
-/* Initial implementation of attestation service:
- * - data is TLV encoded
- * - token is not signed yet
- * - only fixed set of claims are supported
- * - external claims are not handled, expect challenge object
+/*!
+ * \brief Static function to create the initial attestation token
+ *
+ * \param[in] challenge Structure to carry the challenge value:
+ * pointer + challeng's length
+ * \param[in] token Structure to carry the token info, where to
+ * create it: pointer + buffer's length
+ * \param[out] completed_token Structure to carry the info about the created
+ * token: pointer + final token's length
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static enum psa_attest_err_t
+attest_create_token(struct useful_buf_c *challenge,
+ struct useful_buf *token,
+ struct useful_buf_c *completed_token)
+{
+ enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS;
+ enum attest_token_err_t token_err;
+ struct attest_token_ctx attest_token_ctx;
+ int32_t key_select;
+ int32_t alg_select;
+ uint32_t option_flags = 0;
+
+ if (challenge->len == 36) {
+ /* FixMe: Special challenge with option flags appended. This might can
+ * be removed when the public API can take option_flags.
+ */
+ option_flags = *(uint32_t *)(challenge->ptr + 32);
+ challenge->len = 32;
+ }
+
+ /* Lower three bits are the key select */
+ key_select = option_flags & 0x7;
+
+ /* Map the key select to an algorithm. Maybe someday we'll support something
+ * other than ES256
+ */
+ switch (key_select) {
+ default:
+ alg_select = COSE_ALGORITHM_ES256;
+ }
+
+ /* Get started creating the token. This sets up the CBOR and COSE contexts
+ * which causes the COSE headers to be constructed.
+ */
+ token_err = attest_token_start(&attest_token_ctx,
+ option_flags, /* option_flags */
+ key_select, /* key_select */
+ COSE_ALGORITHM_ES256, /* alg_select */
+ token);
+
+ if (token_err != ATTEST_TOKEN_ERR_SUCCESS) {
+ attest_err = error_mapping(token_err);
+ goto error;
+ }
+
+ attest_err = attest_add_challenge_claim(&attest_token_ctx,
+ challenge);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ if (!(option_flags & TOKEN_OPT_OMIT_CLAIMS)) {
+ attest_err = attest_add_boot_seed_claim(&attest_token_ctx);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ /* FixMe: Remove this #if when MPU will be configured properly.
+ * Currently in case of TFM_LVL == 3 unaligned access triggers
+ * a usage fault exception.
+ */
+#if !defined(TFM_LVL) || (TFM_LVL == 1)
+ attest_err = attest_add_instance_id_claim(&attest_token_ctx);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ attest_err = attest_add_hw_version_claim(&attest_token_ctx);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ attest_err = attest_add_implementation_id_claim(&attest_token_ctx);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+#endif
+
+ attest_err = attest_add_caller_id_claim(&attest_token_ctx);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ attest_err = attest_add_security_lifecycle_claim(&attest_token_ctx);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ attest_err = attest_add_all_sw_components(&attest_token_ctx);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+ }
+
+ /* Finish up creating the token. This is where the actual signature
+ * is generated. This finishes up the CBOR encoding too.
+ */
+ token_err = attest_token_finish(&attest_token_ctx, completed_token);
+ if (token_err) {
+ attest_err = error_mapping(token_err);
+ goto error;
+ }
+
+error:
+ return attest_err;
+}
+
+/* Limitations of the current implementation:
+ * - Token is not signed yet properly, just a fake signature is added to the
+ * token due to lack of psa_asymmetric_sign() implementation in crypto
+ * service.
*/
enum psa_attest_err_t
initial_attest_get_token(const psa_invec *in_vec, uint32_t num_invec,
@@ -584,91 +771,43 @@
{
enum tfm_status_e tfm_err;
enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS;
+ struct useful_buf_c challenge;
+ struct useful_buf token;
+ struct useful_buf_c completed_token;
- const uint8_t *challenge_buf = (uint8_t *)in_vec[0].base;
- size_t challenge_buf_size = in_vec[0].len;
- uint8_t *token_buf = (uint8_t *)out_vec[0].base;
- size_t *token_buf_size = &(out_vec[0].len);
+ challenge.ptr = in_vec[0].base;
+ challenge.len = in_vec[0].len;
+ token.ptr = out_vec[0].base;
+ token.len = out_vec[0].len;
- attest_err = attest_verify_challenge_size(challenge_buf_size);
+ attest_err = attest_verify_challenge_size(challenge.len);
if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
goto error;
}
- tfm_err = tfm_core_memory_permission_check((void *)challenge_buf,
- challenge_buf_size,
+ tfm_err = tfm_core_memory_permission_check((void *)challenge.ptr,
+ challenge.len,
TFM_MEMORY_ACCESS_RO);
if (tfm_err != TFM_SUCCESS) {
attest_err = PSA_ATTEST_ERR_INVALID_INPUT;
goto error;
}
- tfm_err = tfm_core_memory_permission_check(token_buf,
- *token_buf_size,
+ tfm_err = tfm_core_memory_permission_check(token.ptr,
+ token.len,
TFM_MEMORY_ACCESS_RW);
if (tfm_err != TFM_SUCCESS) {
attest_err = PSA_ATTEST_ERR_INVALID_INPUT;
goto error;
}
- attest_err = attest_init_token(*token_buf_size, token_buf);
+ attest_err = attest_create_token(&challenge, &token, &completed_token);
if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
goto error;
}
- attest_err = attest_add_sw_module_claims(*token_buf_size, token_buf);
- if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
- goto error;
- }
-
- attest_err = attest_add_boot_seed_claim(*token_buf_size, token_buf);
- if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
- goto error;
- }
-
- /* FixMe: Remove this #if when MPU will be configured properly. Currently
- * in case of TFM_LVL == 3 unaligned access triggers a usage fault
- * exception.
- */
-#if !defined(TFM_LVL) || (TFM_LVL == 1)
- attest_err = attest_add_instance_id_claim(*token_buf_size, token_buf);
- if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
- goto error;
- }
-
- attest_err = attest_add_hw_version_claim(*token_buf_size, token_buf);
- if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
- goto error;
- }
-
- attest_err = attest_add_implementation_id_claim(*token_buf_size, token_buf);
- if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
- goto error;
- }
-#endif
-
- attest_err = attest_add_challenge_claim(challenge_buf_size,
- challenge_buf,
- *token_buf_size,
- token_buf);
- if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
- goto error;
- }
-
- attest_err = attest_add_caller_id_claim(*token_buf_size, token_buf);
- if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
- goto error;
- }
-
- attest_err = attest_add_security_lifecycle_claim(*token_buf_size,
- token_buf);
- if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
- goto error;
- }
-
- /* FixMe: Token should be signed with attestation key */
-
- *token_buf_size = attest_get_token_size(token_buf);
+ out_vec[0].base = (void *)completed_token.ptr;
+ out_vec[0].len = completed_token.len;
error:
return attest_err;
@@ -682,6 +821,17 @@
enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS;
uint32_t challenge_size = *(uint32_t *)in_vec[0].base;
uint32_t *token_buf_size = (uint32_t *)out_vec[0].base;
+ struct useful_buf_c challenge;
+ struct useful_buf token;
+ struct useful_buf_c completed_token;
+
+ /* Only the size of the challenge is needed */
+ challenge.ptr = NULL;
+ challenge.len = challenge_size;
+
+ /* Special value to get the size of the token, but token is not created */
+ token.ptr = NULL;
+ token.len = INT32_MAX;
if (out_vec[0].len < sizeof(uint32_t)) {
attest_err = PSA_ATTEST_ERR_INVALID_INPUT;
@@ -693,7 +843,12 @@
goto error;
}
- *token_buf_size = PSA_INITIAL_ATTEST_TOKEN_SIZE;
+ attest_err = attest_create_token(&challenge, &token, &completed_token);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ *token_buf_size = completed_token.len;
error:
return attest_err;
diff --git a/secure_fw/services/initial_attestation/manifest.yaml b/secure_fw/services/initial_attestation/manifest.yaml
index 4d607af..1de3305 100644
--- a/secure_fw/services/initial_attestation/manifest.yaml
+++ b/secure_fw/services/initial_attestation/manifest.yaml
@@ -38,6 +38,8 @@
"attestation_core.c",
"attestation_crypto_stub.c",
"attestation_key.c",
+ "attest_token.c",
+
],
"tfm_linker_pattern": [
"library_list": [
diff --git a/test/suites/attestation/CMakeLists.inc b/test/suites/attestation/CMakeLists.inc
index c503554..45a0613 100644
--- a/test/suites/attestation/CMakeLists.inc
+++ b/test/suites/attestation/CMakeLists.inc
@@ -1,5 +1,5 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -29,8 +29,13 @@
elseif(ENABLE_ATTESTATION_SERVICE_TESTS)
list(APPEND ALL_SRC_C_S "${ATTESTATION_TEST_DIR}/secure/attestation_s_interface_testsuite.c")
list(APPEND ALL_SRC_C_NS "${ATTESTATION_TEST_DIR}/non_secure/attestation_ns_interface_testsuite.c")
+ list(APPEND ALL_SRC_C_NS "${ATTESTATION_TEST_DIR}/token_test.c")
#Setting include directories
embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
+ embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/services/initial_attestation ABSOLUTE)
+ embedded_include_directories(PATH ${TFM_ROOT_DIR}/lib/ext/qcbor/inc ABSOLUTE)
+ embedded_include_directories(PATH ${TFM_ROOT_DIR}/lib/t_cose/inc ABSOLUTE)
+ embedded_include_directories(PATH ${TFM_ROOT_DIR}/lib/t_cose/src ABSOLUTE)
endif()
diff --git a/test/suites/attestation/attestation_tests_common.h b/test/suites/attestation/attestation_tests_common.h
index be85a69..041f0ac 100644
--- a/test/suites/attestation/attestation_tests_common.h
+++ b/test/suites/attestation/attestation_tests_common.h
@@ -8,8 +8,6 @@
#ifndef __ATTESTATION_TESTS_COMMON_H__
#define __ATTESTATION_TESTS_COMMON_H__
-#include "psa_initial_attestation_api.h"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -19,7 +17,7 @@
*
* \brief Size of token buffer in bytes.
*/
-#define TEST_TOKEN_SIZE PSA_INITIAL_ATTEST_TOKEN_SIZE
+#define TEST_TOKEN_SIZE (0x200)
/*!
* \def TOO_SMALL_TOKEN_BUFFER
diff --git a/test/suites/attestation/non_secure/attestation_ns_interface_testsuite.c b/test/suites/attestation/non_secure/attestation_ns_interface_testsuite.c
index 7135a56..7c2e28f 100644
--- a/test/suites/attestation/non_secure/attestation_ns_interface_testsuite.c
+++ b/test/suites/attestation/non_secure/attestation_ns_interface_testsuite.c
@@ -16,6 +16,7 @@
#include "tfm_api.h"
#include <string.h>
#include <stdlib.h>
+#include "../token_test.h"
static uint8_t token_buffer[TEST_TOKEN_SIZE];
static uint8_t challenge_buffer[TEST_CHALLENGE_OBJ_SIZE];
@@ -24,58 +25,21 @@
/* List of tests */
static void tfm_attest_test_2001(struct test_result_t *ret);
static void tfm_attest_test_2002(struct test_result_t *ret);
+static void tfm_attest_test_2003(struct test_result_t *ret);
+static void tfm_attest_test_2004(struct test_result_t *ret);
static struct test_t attestation_interface_tests[] = {
{&tfm_attest_test_2001, "TFM_ATTEST_TEST_2001",
"Get attestation token and check claims", {0} },
{&tfm_attest_test_2002, "TFM_ATTEST_TEST_2002",
"Negative test cases for initial attestation service", {0} },
+ {&tfm_attest_test_2003, "TFM_ATTEST_TEST_2003",
+ "Minimal token test for CBOR/COSE encoding", {0} },
+ {&tfm_attest_test_2004, "TFM_ATTEST_TEST_2004",
+ "Minimal token size test for CBOR/COSE encoding", {0} },
};
/*!
- * \brief Static function to iterates over the TLV fields in the attestation
- * token and look for the location of the specified TLV type.
- *
- * \param[in] minor_type The identifier of the TLV data entry
- * \param[in] token_buf Pointer to the buffer which stores the token
- * \param[out] tlv_ptr Pointer to the TLV data entry
- *
- * \return Returns 0 on success. Otherwise, 1.
- */
-static uint32_t attest_get_tlv_data(uint16_t minor_type,
- uint8_t *token_buf,
- uint8_t **tlv_data_ptr)
-{
- struct shared_data_tlv_header *tlv_header;
- struct shared_data_tlv_entry *tlv_entry;
- uintptr_t tlv_end;
- uintptr_t tlv_curr;
-
- tlv_header = (struct shared_data_tlv_header *)token_buf;
- if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
- return 1u;
- }
-
- /* Get the boundaries of TLV section */
- tlv_end = (uintptr_t)token_buf + tlv_header->tlv_tot_len;
- tlv_curr = (uintptr_t)token_buf + SHARED_DATA_HEADER_SIZE;
-
- /* Iterates over the TLV section and copy TLVs with requested minor
- * type to the provided buffer.
- */
- for(; tlv_curr < tlv_end; tlv_curr += tlv_entry->tlv_len) {
- tlv_entry = (struct shared_data_tlv_entry *)tlv_curr;
- if (GET_MINOR(tlv_entry->tlv_type) == minor_type) {
- *tlv_data_ptr = (uint8_t *)tlv_entry +
- SHARED_DATA_ENTRY_HEADER_SIZE;
- return 0;
- }
- }
-
- return 1u;
-}
-
-/*!
* \brief Static function to generate a random byte stream. It is used as a
* challenge object to test attestation service.
*
@@ -120,29 +84,11 @@
* \brief Positive tests for initial attestation service
*
* - Calling Initial Attestation service to get token
- * - Check the existence of the fixed set of claims:
- * - Boot status
- * - Boot seed
- * - Instance ID
- * - Challenge object
- * - Caller ID
- * - Implementation ID
- * - Hardware version
- * - Security lifecycle
- * - Comparing value of claims:
- * - Boot seed: Compare boot seed from subsequent calls
- * - Device ID: Currently compare with fix value
- * - Challenge: Compare with input object
- * - Caller ID: Check whether is it in non-secure range
*/
static void tfm_attest_test_2001(struct test_result_t *ret)
{
enum psa_attest_err_t err;
uint32_t token_size;
- uint8_t boot_seed_buffer[BOOT_SEED_SIZE];
- uint8_t *tlv_data_ptr;
- int32_t caller_id;
- uint32_t res;
generate_challenge(TEST_CHALLENGE_OBJ_SIZE, challenge_buffer);
@@ -154,8 +100,8 @@
return;
}
- if (token_size != PSA_INITIAL_ATTEST_TOKEN_SIZE) {
- TEST_FAIL("Token size is faulty");
+ if (token_size > TEST_TOKEN_SIZE) {
+ TEST_FAIL("Allocated buffer is smaller than required");
return;
}
@@ -169,119 +115,6 @@
return;
}
- /* Check IMAGE HASH
- * The image hash cannot be retrieved from image manifest if code runs in
- * NS context, because the image header resides in S memory area.
- */
- res = attest_get_tlv_data(TLV_MINOR_IAS_S_NS_MEASURE_VALUE, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_S_NS_SHA256");
- return;
- }
-
- /* FixMe: Remove this #if when MPU will be configured properly. Currently
- * in case of TFM_LVL == 3 unaligned access triggers a usage fault
- * exception.
- */
-#if !defined(TFM_LVL) || (TFM_LVL == 1)
- /* Check INSTANCE_ID */
- res = attest_get_tlv_data(TLV_MINOR_IAS_INSTANCE_ID, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_INSTANCE_ID");
- return;
- }
-
- /* Check IMPLEMENTATION_ID */
- res = attest_get_tlv_data(TLV_MINOR_IAS_IMPLEMENTATION_ID, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_IMPLEMENTATION_ID");
- return;
- }
-
- /* Check HARDWARE_VERSION, optional claim */
- res = attest_get_tlv_data(TLV_MINOR_IAS_HW_VERSION, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_HW_VERSION");
- return;
- }
-#endif
-
- /* Check SECURITY LIFECYCLE */
- res = attest_get_tlv_data(TLV_MINOR_IAS_SECURITY_LIFECYCLE, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_SECURITY_LIFECYCLE");
- return;
- }
-
- /* Check CHALLENGE */
- res = attest_get_tlv_data(TLV_MINOR_IAS_CHALLENGE, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_CHALLENGE");
- return;
- }
- if (tfm_memcmp(tlv_data_ptr, challenge_buffer,
- TEST_CHALLENGE_OBJ_SIZE) != 0) {
- TEST_FAIL("Faulty claim: TLV_MINOR_IAS_CHALLENGE");
- return;
- }
-
- /* Check CALLER ID */
- res = attest_get_tlv_data(TLV_MINOR_IAS_CALLER_ID, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_CALLER_ID");
- return;
- }
-
- caller_id = *((int32_t *)tlv_data_ptr);
- if (!TFM_CLIENT_ID_IS_NS(caller_id)) {
- TEST_FAIL("Faulty claim: TLV_MINOR_IAS_CALLER_ID");
- return;
- }
-
- /* Check BOOT_SEED */
- res = attest_get_tlv_data(TLV_MINOR_IAS_BOOT_SEED, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_BOOT_SEED");
- return;
- }
-
- /* Store received boot seed. */
- tfm_memcpy(boot_seed_buffer, tlv_data_ptr, BOOT_SEED_SIZE);
-
- /* Call attest API again and compare the value of boot seed on subsequent
- * calls. They must be equal within the same boot cycle.
- */
- err = psa_initial_attest_get_token(challenge_buffer,
- TEST_CHALLENGE_OBJ_SIZE,
- token_buffer,
- &token_size);
- if (err != PSA_ATTEST_ERR_SUCCESS) {
- TEST_FAIL("Get token failed");
- return;
- }
-
- /* Get boot seed again */
- res = attest_get_tlv_data(TLV_MINOR_IAS_BOOT_SEED, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_BOOT_SEED");
- return;
- }
-
- /*Compare the values of boot seed on subsequent calls */
- if (tfm_memcmp(tlv_data_ptr, boot_seed_buffer, BOOT_SEED_SIZE) != 0) {
- TEST_FAIL("Faulty claim: TLV_MINOR_IAS_BOOT_SEED");
- return;
- }
-
ret->val = TEST_PASSED;
}
@@ -316,10 +149,48 @@
token_buffer,
&token_size);
- if (err == PSA_ATTEST_ERR_SUCCESS) {
+ if (err != PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW) {
TEST_FAIL("Attestation should fail with too small token buffer");
return;
}
ret->val = TEST_PASSED;
}
+
+/*!
+ * \brief Get minimal token, only include a hard coded challenge, but omit the
+ * rest of the claims
+ *
+ * Calling the minimal_test, which just retrieves a specific token:
+ * - only hard coded challenge is included
+ * - token signature is the hash of the token concatenated twice
+ */
+static void tfm_attest_test_2003(struct test_result_t *ret)
+{
+ enum psa_attest_err_t err;
+
+ err = minimal_test();
+ if (err != PSA_ATTEST_ERR_SUCCESS) {
+ TEST_FAIL("CBOR/COSE minimal_test has failed");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
+
+/*!
+ * \brief Get the size of the minimal token, only include a hard coded
+ * challenge, but omit the rest of the claims
+ */
+static void tfm_attest_test_2004(struct test_result_t *ret)
+{
+ enum psa_attest_err_t err;
+
+ err = minimal_get_size_test();
+ if (err != PSA_ATTEST_ERR_SUCCESS) {
+ TEST_FAIL("CBOR/COSE minimal_get_size_test has failed");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
diff --git a/test/suites/attestation/secure/attestation_s_interface_testsuite.c b/test/suites/attestation/secure/attestation_s_interface_testsuite.c
index 91852bd..951e0ed 100644
--- a/test/suites/attestation/secure/attestation_s_interface_testsuite.c
+++ b/test/suites/attestation/secure/attestation_s_interface_testsuite.c
@@ -9,13 +9,9 @@
#include "psa_initial_attestation_api.h"
#include "secure_fw/services/initial_attestation/attestation.h"
#include "../attestation_tests_common.h"
-#include "bl2/include/tfm_boot_status.h"
-#include "bl2/ext/mcuboot/bootutil/include/bootutil/image.h"
#include "secure_utilities.h"
#include "platform/include/tfm_plat_device_id.h"
#include "platform/include/tfm_plat_boot_seed.h"
-#include "flash_layout.h"
-#include "spm_partition_defs.h"
#include <string.h>
#include <stdlib.h>
@@ -35,108 +31,6 @@
"Negative test cases for initial attestation service", {0} },
};
-/*!
- * \brief Static function to iterates over the TLV fields in the attestation
- * token and look for the location of the specified TLV type.
- *
- * \param[in] minor_type The identifier of the TLV data entry
- * \param[in] token_buf Pointer to the buffer which stores the token
- * \param[out] tlv_ptr Pointer to the TLV data entry
- *
- * \return Returns 0 on success. Otherwise, 1.
- */
-static uint32_t attest_get_tlv_data(uint16_t minor_type,
- uint8_t *token_buf,
- uint8_t **tlv_data_ptr)
-{
- struct shared_data_tlv_header *tlv_header;
- struct shared_data_tlv_entry *tlv_entry;
- uintptr_t tlv_end;
- uintptr_t tlv_curr;
-
- tlv_header = (struct shared_data_tlv_header *)token_buf;
- if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
- return 1u;
- }
-
- /* Get the boundaries of TLV section */
- tlv_end = (uintptr_t)token_buf + tlv_header->tlv_tot_len;
- tlv_curr = (uintptr_t)token_buf + SHARED_DATA_HEADER_SIZE;
-
- /* Iterates over the TLV section and copy TLVs with requested minor
- * type to the provided buffer.
- */
- for(; tlv_curr < tlv_end; tlv_curr += tlv_entry->tlv_len) {
- tlv_entry = (struct shared_data_tlv_entry *)tlv_curr;
- if (GET_MINOR(tlv_entry->tlv_type) == minor_type) {
- *tlv_data_ptr = (uint8_t *)tlv_entry +
- SHARED_DATA_ENTRY_HEADER_SIZE;
- return 0;
- }
- }
-
- return 1u;
-}
-
-/*!
- * \brief Get image hash from the image manifest.
- *
- * This function iterates over the image manifest section to look for
- * the image's hash value. This manifest section is also TLV encoded.
- * This function can be called if TFM_LVL == 1, to avoid MemMange fault, which
- * is triggered by enabled MPU at level 3 isolation.
- *
- * Note 1: The access of manifest section must be done with NS alias to avoid
- * MPC fault, because manifest section is configured to be NS memory.
- *
- * Note 2: This function assumes that active image resides in slot 0 or in RAM
- * pointing by LOAD_ADDRESS macro. But these assumptions might not be
- * valid if MCUBOOT_NO_SWAP mode is used.
- *
- * \param[out] Pointer to the location of image hash value in the image
- * manifest section.
- *
- * \return Returns 0 on success. Otherwise, 1.
- */
-#if !defined(TFM_LVL) || (TFM_LVL == 1)
-/* FixMe: This offset should be calculated per device */
-#define USUAL_S_NS_ALIAS_OFFSET 0x10000000u
-static uint32_t attest_get_s_ns_sha256(uint8_t **hash)
-{
- struct image_header *image_header;
- struct image_tlv_info *tlv_info;
- struct image_tlv *tlv_entry;
- uint32_t image_header_address;
- uint8_t *off;
- uint8_t *end;
-
-#ifdef LOAD_ADDRESS
- image_header_address = LOAD_ADDRESS;
-#else
- image_header_address = (FLASH_BASE_ADDRESS + FLASH_AREA_IMAGE_0_OFFSET);
-#endif
- image_header = (struct image_header *)image_header_address;
- /* Calculates NS memory alias of manifest section */
- tlv_info = (struct image_tlv_info *)(image_header_address +
- image_header->ih_hdr_size +
- image_header->ih_img_size -
- USUAL_S_NS_ALIAS_OFFSET);
-
- end = (uint8_t *)tlv_info + tlv_info->it_tlv_tot;
- off = (uint8_t *)tlv_info + sizeof(struct image_tlv_info);
-
- for (; off < end; off += sizeof(struct image_tlv) + tlv_entry->it_len) {
- tlv_entry = (struct image_tlv *)(off);
- if (tlv_entry->it_type == IMAGE_TLV_SHA256) {
- *hash = (uint8_t *)tlv_entry + sizeof(struct image_tlv);
- return 0;
- }
- }
-
- return 1u;
-}
-#endif
-
void
register_testsuite_s_attestation_interface(struct test_suite_t *p_test_suite)
{
@@ -154,31 +48,11 @@
* \brief Positive tests for initial attestation service
*
* - Calling Initial Attestation service to get token
- * - Check the existence of the fixed set of claims:
- * - Boot status
- * - Boot seed
- * - Instance ID
- * - Challenge object
- * - Caller ID
- * - Implementation ID
- * - Hardware version
- * - Security lifecycle
- * - Comparing value of claims:
- * - Boot status: Get boot status from token and from image manifest
- * and compare them
- * - Boot seed: Compare boot seed from subsequent calls
- * - Device ID: Currently compare with fix value
- * - Challenge: Compare with input object
- * - Caller ID: Check whether is it in non-secure range
*/
static void tfm_attest_test_1001(struct test_result_t *ret)
{
enum psa_attest_err_t err;
uint32_t token_size;
- uint8_t boot_seed_buffer[BOOT_SEED_SIZE];
- uint8_t *tlv_data_ptr;
- int32_t caller_id;
- uint32_t res;
/* Get attestation token size */
err = psa_initial_attest_get_token_size(TEST_CHALLENGE_OBJ_SIZE,
@@ -188,8 +62,8 @@
return;
}
- if (token_size != PSA_INITIAL_ATTEST_TOKEN_SIZE) {
- TEST_FAIL("Token size is faulty");
+ if (token_size > TEST_TOKEN_SIZE) {
+ TEST_FAIL("Allocated buffer is smaller than required");
return;
}
@@ -206,135 +80,14 @@
return;
}
- /* Check IMAGE HASH */
- res = attest_get_tlv_data(TLV_MINOR_IAS_S_NS_MEASURE_VALUE, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_S_NS_SHA256");
- return;
- }
- /* Extract image hash from manifest data and compare with claim.
- * This can be done only from secure side if S_MPU is not enabled.
- */
-#if !defined(TFM_LVL) || (TFM_LVL == 1)
- uint8_t *hash_from_image;
- res = attest_get_s_ns_sha256(&hash_from_image);
- if (res == 0) {
- if (tfm_memcmp(tlv_data_ptr, hash_from_image, 32) != 0) {
- TEST_FAIL("Faulty claim: TLV_MINOR_IAS_S_NS_SHA256");
- return;
- }
- }
-#endif
-
- /* FixMe: Remove this #if when MPU will be configured properly. Currently
- * in case of TFM_LVL == 3 unaligned access triggers a usage fault
- * exception.
- */
-#if !defined(TFM_LVL) || (TFM_LVL == 1)
- /* Check INSTANCE_ID */
- res = attest_get_tlv_data(TLV_MINOR_IAS_INSTANCE_ID, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_INSTANCE_ID");
- return;
- }
-
- /* Check IMPLEMENTATION_ID */
- res = attest_get_tlv_data(TLV_MINOR_IAS_IMPLEMENTATION_ID, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_IMPLEMENTATION_ID");
- return;
- }
-
- /* Check HARDWARE_VERSION, optional claim */
- res = attest_get_tlv_data(TLV_MINOR_IAS_HW_VERSION, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_HW_VERSION");
- return;
- }
-#endif
-
- /* Check SECURITY LIFECYCLE */
- res = attest_get_tlv_data(TLV_MINOR_IAS_SECURITY_LIFECYCLE, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_SECURITY_LIFECYCLE");
- return;
- }
-
- /* Check CHALLENGE */
- res = attest_get_tlv_data(TLV_MINOR_IAS_CHALLENGE, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_CHALLENGE");
- return;
- }
- if (tfm_memcmp(tlv_data_ptr, challenge_buffer,
- TEST_CHALLENGE_OBJ_SIZE) != 0) {
- TEST_FAIL("Faulty claim: TLV_MINOR_IAS_CHALLENGE");
- return;
- }
-
- /* Check CALLER ID */
- res = attest_get_tlv_data(TLV_MINOR_IAS_CALLER_ID, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_CALLER_ID");
- return;
- }
-
- caller_id = *((int32_t *)tlv_data_ptr);
- if (caller_id < TFM_SP_BASE) {
- TEST_FAIL("Faulty claim: TLV_MINOR_IAS_CALLER_ID");
- return;
- }
-
- /* Check BOOT_SEED */
- res = attest_get_tlv_data(TLV_MINOR_IAS_BOOT_SEED, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_BOOT_SEED");
- return;
- }
-
- /* Store received boot seed. */
- tfm_memcpy(boot_seed_buffer, tlv_data_ptr, BOOT_SEED_SIZE);
-
- /* Call attest API again and compare the value of boot seed on subsequent
- * calls. They must be equal within the same boot cycle.
- */
- err = psa_initial_attest_get_token(challenge_buffer,
- TEST_CHALLENGE_OBJ_SIZE,
- token_buffer,
- &token_size);
- if (err != PSA_ATTEST_ERR_SUCCESS) {
- TEST_FAIL("Get token failed");
- return;
- }
-
- /* Get boot seed again */
- res = attest_get_tlv_data(TLV_MINOR_IAS_BOOT_SEED, token_buffer,
- &tlv_data_ptr);
- if (res != 0) {
- TEST_FAIL("Missing claim: TLV_MINOR_IAS_BOOT_SEED");
- return;
- }
-
- /*Compare the values of boot seed on subsequent calls */
- if (tfm_memcmp(tlv_data_ptr, boot_seed_buffer, BOOT_SEED_SIZE) != 0) {
- TEST_FAIL("Faulty claim: TLV_MINOR_IAS_BOOT_SEED");
- return;
- }
-
ret->val = TEST_PASSED;
}
/*!
* \brief Negative tests for initial attestation service
*
+ * - Calling initial attestation service with bigger challenge object than
+ * allowed.
* - Calling initial attestation service with smaller buffer size than the
* expected size of the token.
*/
@@ -343,6 +96,17 @@
enum psa_attest_err_t err;
uint32_t token_size = TEST_TOKEN_SIZE;
+ /* Call with with bigger challenge object than allowed */
+ err = psa_initial_attest_get_token(challenge_buffer,
+ INVALID_CHALLENGE_OBJECT_SIZE,
+ token_buffer,
+ &token_size);
+
+ if (err != PSA_ATTEST_ERR_INVALID_INPUT) {
+ TEST_FAIL("Attestation should fail with too big challenge object");
+ return;
+ }
+
/* Call with smaller buffer size than size of test token */
token_size = TOO_SMALL_TOKEN_BUFFER;
err = psa_initial_attest_get_token(challenge_buffer,
@@ -351,7 +115,7 @@
&token_size);
if (err != PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW) {
- TEST_FAIL("Attestation should fail with small buffer");
+ TEST_FAIL("Attestation should fail with too small token buffer");
return;
}