feat(rmm-eac4): modify RSI_ATTESTATION_TOKEN commands
Modifies RSI_ATTESTATION_TOKEN_INIT and
RSI_ATTESTATION_TOKEN_CONTINUE commands as per
RMM Specification 1.0-eac4.
Number of 4K pages allocated for attestation
buffer is defined by RMM_ATTEST_BUFFER_PAGES
in CommonConfigs.cmake and set to 1 by default.
Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
Change-Id: Icda7f26e291a19b143ae14a291c03cc7bda0e076
diff --git a/cmake/CommonConfigs.cmake b/cmake/CommonConfigs.cmake
index 7e1e9a4..d212c06 100644
--- a/cmake/CommonConfigs.cmake
+++ b/cmake/CommonConfigs.cmake
@@ -53,6 +53,15 @@
ELSE OFF)
#
+# The number of 4K pages allocated for attestation buffer.
+#
+arm_config_option(
+ NAME RMM_CCA_TOKEN_BUFFER
+ HELP "Number of pages to allocate in Aux granules for Realm CCA token"
+ TYPE STRING
+ DEFAULT 1)
+
+#
# Introduce a pseudo-library purely for applying flags to RMM's libraries.
# This is applied to any targets created after this point.
#
@@ -91,6 +100,9 @@
INTERFACE "RMM_FPU_USE_AT_REL2=1")
endif()
+target_compile_definitions(rmm-common
+ INTERFACE "RMM_CCA_TOKEN_BUFFER=U(${RMM_CCA_TOKEN_BUFFER})")
+
#
# Project name and version
#
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index a14200c..af2f797 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -250,6 +250,7 @@
RMM_MAX_SIZE , ,0x0 ,"Maximum size for RMM image"
MAX_CPUS , ,16 ,"Maximum number of CPUs supported by RMM"
GRANULE_SHIFT , ,12 ,"Granule Shift used by RMM"
+ RMM_CCA_TOKEN_BUFFER , ,1 ,"Number of pages to allocate in Aux granules for Realm CCA token"
RMM_DOCS ,ON | OFF ,OFF ,"RMM Documentation build"
CMAKE_BUILD_TYPE ,Debug | Release ,Release ,"CMake Build type"
CMAKE_CONFIGURATION_TYPES ,Debug & Release ,Debug & Release ,"Multi-generator configuration types"
diff --git a/lib/allocator/include/memory_alloc.h b/lib/allocator/include/memory_alloc.h
index 06f381a..eb7da95 100644
--- a/lib/allocator/include/memory_alloc.h
+++ b/lib/allocator/include/memory_alloc.h
@@ -11,12 +11,12 @@
typedef struct memory_header_s memory_header_t;
/* MbedTLS needs 8K of heap for attestation usecases */
-#define REC_HEAP_PAGES 2U
-#define REC_HEAP_SIZE (REC_HEAP_PAGES * SZ_4K)
+#define REC_HEAP_PAGES 2U
+#define REC_HEAP_SIZE (REC_HEAP_PAGES * SZ_4K)
/* Number of pages per REC for PMU state */
-#define REC_PMU_PAGES 1U
-#define REC_PMU_SIZE (REC_PMU_PAGES * SZ_4K)
+#define REC_PMU_PAGES 1U
+#define REC_PMU_SIZE (REC_PMU_PAGES * SZ_4K)
/*
* SIMD context that holds FPU/SVE registers. Space to save max arch supported
@@ -27,18 +27,22 @@
* Size of other status registers : 32 bytes
* Total size is ~3 Pages (rounded up to page size).
*/
-#define REC_SIMD_PAGES 3U
-#define REC_SIMD_SIZE (REC_SIMD_PAGES * SZ_4K)
+#define REC_SIMD_PAGES 3U
+#define REC_SIMD_SIZE (REC_SIMD_PAGES * SZ_4K)
/* Number of pages per REC for 'rec_attest_data' structure */
-#define REC_ATTEST_PAGES 1U
-#define REC_ATTEST_SIZE (REC_ATTEST_PAGES * SZ_4K)
+#define REC_ATTEST_PAGES 1U
+#define REC_ATTEST_SIZE (REC_ATTEST_PAGES * SZ_4K)
+
+/* Number of pages per REC for attestation buffer */
+#define REC_ATTEST_TOKEN_BUF_SIZE (RMM_CCA_TOKEN_BUFFER * SZ_4K)
/* Number of pages per REC to be allocated */
#define REC_NUM_PAGES (REC_HEAP_PAGES + \
REC_PMU_PAGES + \
REC_SIMD_PAGES + \
- REC_ATTEST_PAGES)
+ REC_ATTEST_PAGES + \
+ RMM_CCA_TOKEN_BUFFER)
struct buffer_alloc_ctx {
unsigned char *buf;
diff --git a/lib/attestation/include/attestation_token.h b/lib/attestation/include/attestation_token.h
index 807d0b5..6093e4f 100644
--- a/lib/attestation/include/attestation_token.h
+++ b/lib/attestation/include/attestation_token.h
@@ -44,7 +44,7 @@
enum attest_token_gen_state_t {
ATTEST_SIGN_NOT_STARTED,
ATTEST_SIGN_IN_PROGRESS,
- ATTEST_SIGN_TOKEN_WRITE_IN_PROGRESS,
+ ATTEST_SIGN_TOKEN_WRITE_IN_PROGRESS
};
/*
@@ -84,8 +84,13 @@
*/
enum attest_token_gen_state_t state;
struct attest_token_encode_ctx ctx;
- /* Data saved in the first iteration */
- unsigned long token_ipa;
+
+ /* Number of CCA token bytes left to copy to the Realm */
+ size_t cca_token_len;
+
+ /* Number of CCA token bytes copied to the Realm */
+ size_t copied_len;
+
unsigned char challenge[ATTEST_CHALLENGE_SIZE];
};
diff --git a/lib/realm/include/rec.h b/lib/realm/include/rec.h
index d39819d..49c516d 100644
--- a/lib/realm/include/rec.h
+++ b/lib/realm/include/rec.h
@@ -131,6 +131,9 @@
/* Pointer to attestation-related data */
struct rec_attest_data *attest_data;
+
+ /* Address of the attestation token buffer */
+ uintptr_t cca_token_buf;
};
struct rec {
diff --git a/plat/host/host_build/src/host_setup.c b/plat/host/host_build/src/host_setup.c
index fadc4ee..443592b 100644
--- a/plat/host/host_build/src/host_setup.c
+++ b/plat/host/host_build/src/host_setup.c
@@ -25,6 +25,7 @@
RMM_EL3_IFC_MAKE_VERSION(RMM_EL3_IFC_VERS_MAJOR, RMM_EL3_IFC_VERS_MINOR)
#define RMM_EL3_MAX_CPUS (1U)
#define REALM_BUFFER_IPA 0x1000
+#define ATTEST_TOKEN_BUFFER_SIZE 0x100
#define CHECK_RMI_RESULT() \
({ \
@@ -79,11 +80,16 @@
{
INFO("RSI Version is 0x%lx\n", regs[1]);
+ if (regs[0] != RSI_SUCCESS) {
+ ERROR("RSI_VERSION command failed 0x%lx\n", regs[0]);
+ return 0;
+ }
+
srand((int)time(NULL));
/* Add dummy Realm Attestation RSI calls */
regs[0] = SMC_RSI_ATTEST_TOKEN_INIT;
- regs[1] = REALM_BUFFER_IPA;
+ regs[1] = rand();
regs[2] = rand();
regs[3] = rand();
regs[4] = rand();
@@ -91,7 +97,6 @@
regs[6] = rand();
regs[7] = rand();
regs[8] = rand();
- regs[9] = rand();
return host_util_rsi_helper(realm_continue_1);
}
@@ -109,17 +114,25 @@
/* Continue Realm Attestation RSI calls */
regs[0] = SMC_RSI_ATTEST_TOKEN_CONTINUE;
regs[1] = REALM_BUFFER_IPA;
+ regs[2] = 0;
+ regs[3] = ATTEST_TOKEN_BUFFER_SIZE;
return host_util_rsi_helper(realm_continue_2);
-
}
static int realm_continue_2(unsigned long *regs)
{
+ static unsigned long offset;
+
if (regs[0] == RSI_INCOMPLETE) {
INFO("Realm Token Attestation creation is pre-empted by interrupt.\n");
+
+ offset += regs[1];
+
/* Continue Realm Attestation RSI calls */
regs[0] = SMC_RSI_ATTEST_TOKEN_CONTINUE;
regs[1] = REALM_BUFFER_IPA;
+ regs[2] = offset;
+ regs[3] = ATTEST_TOKEN_BUFFER_SIZE;
return host_util_rsi_helper(realm_continue_2);
}
diff --git a/runtime/rmi/rec.c b/runtime/rmi/rec.c
index c7d2c49..7537fb7 100644
--- a/runtime/rmi/rec.c
+++ b/runtime/rmi/rec.c
@@ -185,12 +185,13 @@
* - REC_PMU_PAGES for PMU state
* - REC_SIMD_PAGES for SIMD state
* - REC_ATTEST_PAGES for 'rec_attest_data' structure
+ * - REC_ATTEST_BUFFER_PAGES for attestation buffer
*/
assert(r->num_rec_aux >= REC_NUM_PAGES);
/*
* Assign base address for attestation heap, PMU, SIMD, attestation
- * data
+ * data and buffer.
*/
aux_data = &r->aux_data;
aux_data->attest_heap_buf = (uint8_t *)rec_aux;
@@ -200,6 +201,8 @@
((uint8_t *)aux_data->pmu + REC_PMU_SIZE);
aux_data->attest_data = (struct rec_attest_data *)
((uint8_t *)aux_data->simd_ctx + REC_SIMD_SIZE);
+ aux_data->cca_token_buf = (uintptr_t)aux_data->attest_data +
+ REC_ATTEST_SIZE;
rec_attestation_heap_init(r);
rec_simd_state_init(r);
diff --git a/runtime/rsi/logger.c b/runtime/rsi/logger.c
index 5db269d..21792a4 100644
--- a/runtime/rsi/logger.c
+++ b/runtime/rsi/logger.c
@@ -41,8 +41,8 @@
RSI_FUNCTION(FEATURES, 1U, 1U), /* 0xC4000191 */
RSI_FUNCTION(MEASUREMENT_READ, 1U, 8U), /* 0xC4000192 */
RSI_FUNCTION(MEASUREMENT_EXTEND, 10U, 0U), /* 0xC4000193 */
- RSI_FUNCTION(ATTEST_TOKEN_INIT, 9U, 0U), /* 0xC4000194 */
- RSI_FUNCTION(ATTEST_TOKEN_CONTINUE, 1U, 1U), /* 0xC4000195 */
+ RSI_FUNCTION(ATTEST_TOKEN_INIT, 8U, 0U), /* 0xC4000194 */
+ RSI_FUNCTION(ATTEST_TOKEN_CONTINUE, 3U, 1U), /* 0xC4000195 */
RSI_FUNCTION(REALM_CONFIG, 1U, 0U), /* 0xC4000196 */
RSI_FUNCTION(IPA_STATE_SET, 4U, 2U), /* 0xC4000197 */
RSI_FUNCTION(IPA_STATE_GET, 1U, 1U), /* 0xC4000198 */
diff --git a/runtime/rsi/realm_attest.c b/runtime/rsi/realm_attest.c
index 485bf71..58e71c1 100644
--- a/runtime/rsi/realm_attest.c
+++ b/runtime/rsi/realm_attest.c
@@ -31,30 +31,6 @@
}
/*
- * Save the input parameters in the context for later iterations to check for
- * consistency.
- */
-static void save_input_parameters(struct rec *rec)
-{
- struct rec_attest_data *attest_data = rec->aux_data.attest_data;
-
- attest_data->token_sign_ctx.token_ipa = rec->regs[1];
- (void)memcpy(attest_data->token_sign_ctx.challenge, &rec->regs[2],
- ATTEST_CHALLENGE_SIZE);
-}
-
-/*
- * Verify that in all the iterations the input parameters are the same
- * as in the initial call.
- */
-static bool verify_input_parameters_consistency(struct rec *rec)
-{
- struct rec_attest_data *attest_data = rec->aux_data.attest_data;
-
- return attest_data->token_sign_ctx.token_ipa == rec->regs[1];
-}
-
-/*
* Function to continue with the sign operation
*/
static void attest_token_continue_sign_state(
@@ -67,7 +43,6 @@
enum attest_token_err_t ret =
attest_realm_token_sign(&(attest_data->token_sign_ctx.ctx),
&(attest_data->rmm_realm_token_len));
-
if ((ret == ATTEST_TOKEN_ERR_COSE_SIGN_IN_PROGRESS) ||
(ret == ATTEST_TOKEN_ERR_SUCCESS)) {
/*
@@ -96,12 +71,15 @@
struct rsi_result *res)
{
struct granule *gr;
- uint8_t *realm_att_token;
+ uintptr_t realm_att_token;
unsigned long realm_att_token_ipa = rec->regs[1];
+ unsigned long offset = rec->regs[2];
+ unsigned long size = rec->regs[3];
enum s2_walk_status walk_status;
struct s2_walk_result walk_res = { 0UL };
- size_t attest_token_len;
+ size_t attest_token_len, length;
struct rec_attest_data *attest_data = rec->aux_data.attest_data;
+ uintptr_t cca_token_buf = rec->aux_data.cca_token_buf;
/*
* Translate realm granule IPA to PA. If returns with
@@ -127,38 +105,72 @@
return;
}
+ if (size == 0UL) {
+ res->smc_res.x[0] = RSI_SUCCESS;
+ return;
+ }
+
/* Map realm data granule to RMM address space */
gr = find_granule(walk_res.pa);
- realm_att_token = granule_map(gr, SLOT_RSI_CALL);
- assert(realm_att_token != NULL);
+ realm_att_token = (uintptr_t)granule_map(gr, SLOT_RSI_CALL);
+ assert(realm_att_token != 0UL);
- attest_token_len = attest_cca_token_create(realm_att_token,
- ATTEST_TOKEN_BUFFER_SIZE,
- &attest_data->rmm_realm_token_buf,
- attest_data->rmm_realm_token_len);
+ if (attest_data->token_sign_ctx.copied_len == 0UL) {
+ attest_token_len = attest_cca_token_create(
+ (void *)cca_token_buf,
+ REC_ATTEST_TOKEN_BUF_SIZE,
+ &attest_data->rmm_realm_token_buf,
+ attest_data->rmm_realm_token_len);
+ if (attest_token_len == 0UL) {
+ res->smc_res.x[0] = RSI_ERROR_INPUT;
+
+ /* The signing has failed. Reset the state. */
+ attest_data->token_sign_ctx.state =
+ ATTEST_SIGN_NOT_STARTED;
+ goto out_unmap;
+ }
+
+ attest_data->token_sign_ctx.cca_token_len = attest_token_len;
+ } else {
+ attest_token_len = attest_data->token_sign_ctx.cca_token_len;
+ }
+
+ length = (size < attest_token_len) ? size : attest_token_len;
+
+ /* Copy attestation token */
+ (void)memcpy((void *)(realm_att_token + offset),
+ (void *)(cca_token_buf +
+ attest_data->token_sign_ctx.copied_len),
+ length);
+
+ attest_token_len -= length;
+
+ if (attest_token_len != 0UL) {
+ attest_data->token_sign_ctx.cca_token_len = attest_token_len;
+ attest_data->token_sign_ctx.copied_len += length;
+
+ res->smc_res.x[0] = RSI_INCOMPLETE;
+ } else {
+
+ /* The signing has succeeded. Reset the state. */
+ attest_data->token_sign_ctx.state = ATTEST_SIGN_NOT_STARTED;
+ res->smc_res.x[0] = RSI_SUCCESS;
+ }
+
+ res->smc_res.x[1] = length;
+
+out_unmap:
/* Unmap realm granule */
- buffer_unmap(realm_att_token);
+ buffer_unmap((void *)realm_att_token);
/* Unlock last level page table (walk_res.g_llt) */
granule_unlock(walk_res.llt);
-
- /* Write output parameters */
- if (attest_token_len == 0UL) {
- res->smc_res.x[0] = RSI_ERROR_INPUT;
- } else {
- res->smc_res.x[0] = RSI_SUCCESS;
- res->smc_res.x[1] = attest_token_len;
- }
-
- /* The signing has either succeeded or failed. Reset the state. */
- attest_data->token_sign_ctx.state = ATTEST_SIGN_NOT_STARTED;
}
void handle_rsi_attest_token_init(struct rec *rec, struct rsi_result *res)
{
- struct rd *rd = NULL;
- unsigned long realm_buf_ipa;
+ struct rd *rd;
struct rec_attest_data *attest_data;
void *rpv_ptr;
size_t rpv_len;
@@ -166,9 +178,7 @@
assert(rec != NULL);
- realm_buf_ipa = rec->regs[1];
attest_data = rec->aux_data.attest_data;
-
res->action = UPDATE_REC_RETURN_TO_REALM;
/*
@@ -188,11 +198,6 @@
}
}
- if (!GRANULE_ALIGNED(realm_buf_ipa)) {
- res->smc_res.x[0] = RSI_ERROR_INPUT;
- return;
- }
-
/*
* rd lock is acquired so that measurement cannot be updated
* simultaneously by another rec
@@ -201,16 +206,10 @@
rd = granule_map(rec->realm_info.g_rd, SLOT_RD);
assert(rd != NULL);
- if (!addr_in_par(rd, realm_buf_ipa)) {
- res->smc_res.x[0] = RSI_ERROR_INPUT;
- goto out_unmap_rd;
- }
-
- /*
- * Save the input parameters in the context for later iterations
- * to check.
- */
- save_input_parameters(rec);
+ /* Save challenge value in the context */
+ (void)memcpy((void *)attest_data->token_sign_ctx.challenge,
+ (const void *)&rec->regs[1],
+ ATTEST_CHALLENGE_SIZE);
get_rpv(rd, &rpv_ptr, &rpv_len);
att_ret = attest_realm_token_create(rd->algorithm, rd->measurement,
@@ -220,17 +219,18 @@
&attest_data->token_sign_ctx,
attest_data->rmm_realm_token_buf,
sizeof(attest_data->rmm_realm_token_buf));
+ buffer_unmap(rd);
+ granule_unlock(rec->realm_info.g_rd);
+
if (att_ret != 0) {
ERROR("FATAL_ERROR: Realm token creation failed\n");
panic();
}
+ attest_data->token_sign_ctx.copied_len = 0UL;
attest_data->token_sign_ctx.state = ATTEST_SIGN_IN_PROGRESS;
- res->smc_res.x[0] = RSI_SUCCESS;
-out_unmap_rd:
- buffer_unmap(rd);
- granule_unlock(rec->realm_info.g_rd);
+ res->smc_res.x[0] = RSI_SUCCESS;
}
/*
@@ -247,6 +247,7 @@
struct rsi_result *res)
{
struct rec_attest_data *attest_data;
+ unsigned long realm_buf_ipa, offset, size;
assert(rec != NULL);
assert(rec_exit != NULL);
@@ -254,47 +255,47 @@
attest_data = rec->aux_data.attest_data;
res->action = UPDATE_REC_RETURN_TO_REALM;
- if (!verify_input_parameters_consistency(rec)) {
+ realm_buf_ipa = rec->regs[1];
+ offset = rec->regs[2];
+ size = rec->regs[3];
+
+ if (!GRANULE_ALIGNED(realm_buf_ipa) ||
+ (offset >= GRANULE_SIZE) ||
+ ((offset + size) > GRANULE_SIZE) ||
+ ((offset + size) < offset)) {
res->smc_res.x[0] = RSI_ERROR_INPUT;
return;
}
- while (true) {
- switch (attest_data->token_sign_ctx.state) {
- case ATTEST_SIGN_NOT_STARTED:
- /*
- * Before this call the initial attestation token call
- * (SMC_RSI_ATTEST_TOKEN_INIT) must have been executed
- * successfully.
- */
- res->smc_res.x[0] = RSI_ERROR_STATE;
- break;
- case ATTEST_SIGN_IN_PROGRESS:
- attest_token_continue_sign_state(attest_data, res);
- break;
- case ATTEST_SIGN_TOKEN_WRITE_IN_PROGRESS:
- attest_token_continue_write_state(rec, res);
- break;
- default:
- /* Any other state is considered an error */
- panic();
- }
+ if (!addr_in_rec_par(rec, realm_buf_ipa)) {
+ res->smc_res.x[0] = RSI_ERROR_INPUT;
+ return;
+ }
- if (res->smc_res.x[0] == RSI_INCOMPLETE) {
- if (check_pending_irq()) {
- res->action = UPDATE_REC_EXIT_TO_HOST;
- res->smc_res.x[0] = RSI_INCOMPLETE;
- rec_exit->exit_reason = RMI_EXIT_IRQ;
- break;
- }
- if (((unsigned int)res->action &
- FLAG_EXIT_TO_HOST) != 0U) {
- break;
- }
- } else {
- break;
+ if (attest_data->token_sign_ctx.state == ATTEST_SIGN_NOT_STARTED) {
+ /*
+ * Before this call the initial attestation token call
+ * (SMC_RSI_ATTEST_TOKEN_INIT) must have been executed
+ * successfully.
+ */
+ res->smc_res.x[0] = RSI_ERROR_STATE;
+ return;
+ }
+
+ while (attest_data->token_sign_ctx.state == ATTEST_SIGN_IN_PROGRESS) {
+ attest_token_continue_sign_state(attest_data, res);
+ if (check_pending_irq()) {
+ res->action = UPDATE_REC_EXIT_TO_HOST;
+ rec_exit->exit_reason = RMI_EXIT_IRQ;
+ return;
}
}
+
+ /* Any other state is considered an error */
+ assert(attest_data->token_sign_ctx.state ==
+ ATTEST_SIGN_TOKEN_WRITE_IN_PROGRESS);
+
+ attest_token_continue_write_state(rec, res);
}
void handle_rsi_measurement_extend(struct rec *rec, struct rsi_result *res)
@@ -391,11 +392,11 @@
cnt = (unsigned int)(measurement_get_size(rd->algorithm) /
sizeof(unsigned long));
- assert(cnt >= SMC_RESULT_REGS - 1U);
+ assert(cnt >= (SMC_RESULT_REGS - 1U));
assert(cnt < ARRAY_LEN(rec->regs));
/* Copy the part of the measurement to res->smc_res.x[] */
- for (i = 0U; i < SMC_RESULT_REGS - 1U; i++) {
+ for (i = 0U; i < (SMC_RESULT_REGS - 1U); i++) {
measurement_value_part = (unsigned long *)
&(rd->measurement[idx][i * sizeof(unsigned long)]);
res->smc_res.x[i + 1U] = *measurement_value_part;