aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Vincze <david.vincze@arm.com>2019-11-21 00:19:50 +0100
committerDavid Vincze <david.vincze@arm.com>2019-11-29 16:35:36 +0100
commitff6da53ac651101ce38032131a26d46515687b71 (patch)
treeee6c7ce16dd8b7b84607f456d80a59bc3868c0c8
parent20c3e4e2b96c7c43be3f6ea5cc2e1383518e4881 (diff)
downloadtrusted-firmware-m-ff6da53ac651101ce38032131a26d46515687b71.tar.gz
Attest: Implement API to get attestation public key
Implement non-secure interface function for IPC and library models and secure interface function to get the public part of the attestation key pair. Add public key getter secure function / service to Initial Attestation partition manifest. Change-Id: Idae5f5d5d645afa6d3c7e62e9169387e57932137 Signed-off-by: David Vincze <david.vincze@arm.com>
-rw-r--r--interface/include/psa/initial_attestation.h4
-rw-r--r--interface/include/psa_manifest/sid.h2
-rw-r--r--interface/include/tfm_veneers.h1
-rw-r--r--interface/src/tfm_initial_attestation_func_api.c23
-rw-r--r--interface/src/tfm_initial_attestation_ipc_api.c30
-rw-r--r--secure_fw/ns_callable/tfm_veneers.c2
-rw-r--r--secure_fw/services/initial_attestation/attestation_core.c62
-rw-r--r--secure_fw/services/initial_attestation/psa_manifest/tfm_initial_attestation.h1
-rw-r--r--secure_fw/services/initial_attestation/tfm_attestation_req_mngr.c42
-rw-r--r--secure_fw/services/initial_attestation/tfm_attestation_secure_api.c36
-rw-r--r--secure_fw/services/initial_attestation/tfm_initial_attestation.yaml15
-rw-r--r--secure_fw/services/tfm_service_list.inc16
12 files changed, 233 insertions, 1 deletions
diff --git a/interface/include/psa/initial_attestation.h b/interface/include/psa/initial_attestation.h
index 6a7b8d8e17..4dd247bbc2 100644
--- a/interface/include/psa/initial_attestation.h
+++ b/interface/include/psa/initial_attestation.h
@@ -45,7 +45,9 @@ enum psa_attest_err_t {
PSA_ATTEST_ERR_INIT_FAILED,
/** Token buffer is too small to store the created token there */
PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW,
- /** Some of the mandatory claims are unavailable*/
+ /** Attestation key buffer is too small to store the obtained key there */
+ PSA_ATTEST_ERR_KEY_BUFFER_OVERFLOW,
+ /** Some of the mandatory claims are unavailable */
PSA_ATTEST_ERR_CLAIM_UNAVAILABLE,
/** Some parameter or combination of parameters are recognised as invalid:
* - challenge size is not allowed
diff --git a/interface/include/psa_manifest/sid.h b/interface/include/psa_manifest/sid.h
index baa02c2d51..a6a96e7a04 100644
--- a/interface/include/psa_manifest/sid.h
+++ b/interface/include/psa_manifest/sid.h
@@ -45,6 +45,8 @@ extern "C" {
#define TFM_ATTEST_GET_TOKEN_VERSION (1U)
#define TFM_ATTEST_GET_TOKEN_SIZE_SID (0x00000021U)
#define TFM_ATTEST_GET_TOKEN_SIZE_VERSION (1U)
+#define TFM_ATTEST_GET_PUBLIC_KEY_SID (0x00000022U)
+#define TFM_ATTEST_GET_PUBLIC_KEY_VERSION (1U)
/******** TFM_SP_CORE_TEST ********/
#define SPM_CORE_TEST_INIT_SUCCESS_SID (0x0000F020U)
diff --git a/interface/include/tfm_veneers.h b/interface/include/tfm_veneers.h
index b0b486774a..0bcef49abd 100644
--- a/interface/include/tfm_veneers.h
+++ b/interface/include/tfm_veneers.h
@@ -94,6 +94,7 @@ psa_status_t tfm_platform_sp_ioctl_veneer(psa_invec *in_vec, size_t in_len, psa_
/******** TFM_SP_INITIAL_ATTESTATION ********/
psa_status_t tfm_initial_attest_get_token_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
psa_status_t tfm_initial_attest_get_token_size_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_initial_attest_get_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
#ifdef TFM_PARTITION_TEST_CORE
/******** TFM_SP_CORE_TEST ********/
diff --git a/interface/src/tfm_initial_attestation_func_api.c b/interface/src/tfm_initial_attestation_func_api.c
index c391f61172..7292df5f5f 100644
--- a/interface/src/tfm_initial_attestation_func_api.c
+++ b/interface/src/tfm_initial_attestation_func_api.c
@@ -9,6 +9,7 @@
#include "tfm_veneers.h"
#include "tfm_ns_interface.h"
#include "psa/client.h"
+#include "psa/crypto_types.h"
#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
@@ -56,3 +57,25 @@ psa_initial_attest_get_token_size(uint32_t challenge_size,
(uint32_t)in_vec, IOVEC_LEN(in_vec),
(uint32_t)out_vec, IOVEC_LEN(out_vec));
}
+
+enum psa_attest_err_t
+tfm_initial_attest_get_public_key(uint8_t *public_key,
+ size_t public_key_buf_size,
+ size_t *public_key_len,
+ psa_ecc_curve_t *elliptic_curve_type)
+{
+ int32_t res;
+
+ psa_outvec out_vec[] = {
+ {.base = public_key, .len = public_key_buf_size},
+ {.base = elliptic_curve_type, .len = sizeof(*elliptic_curve_type)},
+ {.base = public_key_len, .len = sizeof(*public_key_len)}
+ };
+
+ res = tfm_ns_interface_dispatch(
+ (veneer_fn)tfm_initial_attest_get_public_key_veneer,
+ (uint32_t)NULL, 0,
+ (uint32_t)out_vec, IOVEC_LEN(out_vec));
+
+ return (enum psa_attest_err_t)res;
+}
diff --git a/interface/src/tfm_initial_attestation_ipc_api.c b/interface/src/tfm_initial_attestation_ipc_api.c
index 10b3a59319..ed9264f1db 100644
--- a/interface/src/tfm_initial_attestation_ipc_api.c
+++ b/interface/src/tfm_initial_attestation_ipc_api.c
@@ -9,6 +9,7 @@
#include "tfm_veneers.h"
#include "tfm_ns_interface.h"
#include "psa/client.h"
+#include "psa/crypto_types.h"
#include "psa_manifest/sid.h"
#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
@@ -81,3 +82,32 @@ psa_initial_attest_get_token_size(uint32_t challenge_size,
return (enum psa_attest_err_t)status;
}
+
+enum psa_attest_err_t
+tfm_initial_attest_get_public_key(uint8_t *public_key,
+ size_t public_key_buf_size,
+ size_t *public_key_len,
+ psa_ecc_curve_t *elliptic_curve_type)
+{
+ psa_handle_t handle = PSA_NULL_HANDLE;
+ psa_status_t status;
+
+ psa_outvec out_vec[] = {
+ {.base = public_key, .len = public_key_buf_size},
+ {.base = elliptic_curve_type, .len = sizeof(*elliptic_curve_type)},
+ {.base = public_key_len, .len = sizeof(*public_key_len)}
+ };
+
+ handle = psa_connect(TFM_ATTEST_GET_PUBLIC_KEY_SID,
+ TFM_ATTEST_GET_PUBLIC_KEY_VERSION);
+ if (!PSA_HANDLE_IS_VALID(handle)) {
+ return PSA_ATTEST_ERR_GENERAL;
+ }
+
+ status = psa_call(handle, PSA_IPC_CALL,
+ NULL, 0,
+ out_vec, IOVEC_LEN(out_vec));
+ psa_close(handle);
+
+ return (enum psa_attest_err_t)status;
+}
diff --git a/secure_fw/ns_callable/tfm_veneers.c b/secure_fw/ns_callable/tfm_veneers.c
index bc7ee6fa2c..ade23cf46b 100644
--- a/secure_fw/ns_callable/tfm_veneers.c
+++ b/secure_fw/ns_callable/tfm_veneers.c
@@ -88,6 +88,7 @@ psa_status_t platform_sp_ioctl(psa_invec *, size_t, psa_outvec *, size_t);
/******** TFM_SP_INITIAL_ATTESTATION ********/
psa_status_t initial_attest_get_token(psa_invec *, size_t, psa_outvec *, size_t);
psa_status_t initial_attest_get_token_size(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t initial_attest_get_public_key(psa_invec *, size_t, psa_outvec *, size_t);
#ifdef TFM_PARTITION_TEST_CORE
/******** TFM_SP_CORE_TEST ********/
@@ -221,6 +222,7 @@ TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_ioctl)
/******** TFM_SP_INITIAL_ATTESTATION ********/
TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, initial_attest_get_token)
TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, initial_attest_get_token_size)
+TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, initial_attest_get_public_key)
#ifdef TFM_PARTITION_TEST_CORE
/******** TFM_SP_CORE_TEST ********/
diff --git a/secure_fw/services/initial_attestation/attestation_core.c b/secure_fw/services/initial_attestation/attestation_core.c
index 72459d4fe8..31c53ce027 100644
--- a/secure_fw/services/initial_attestation/attestation_core.c
+++ b/secure_fw/services/initial_attestation/attestation_core.c
@@ -1134,3 +1134,65 @@ initial_attest_get_token_size(const psa_invec *in_vec, uint32_t num_invec,
error:
return attest_err;
}
+
+enum psa_attest_err_t
+initial_attest_get_public_key(const psa_invec *in_vec, uint32_t num_invec,
+ psa_outvec *out_vec, uint32_t num_outvec)
+{
+ enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS;
+ struct q_useful_buf key_buffer;
+ uint8_t *key_source;
+ size_t key_len;
+ psa_ecc_curve_t curve_type;
+
+ (void)in_vec;
+
+ if (num_invec != 0 || num_outvec != 3) {
+ attest_err = PSA_ATTEST_ERR_INVALID_INPUT;
+ goto error;
+ }
+
+ key_buffer.ptr = out_vec[0].base;
+ key_buffer.len = out_vec[0].len;
+
+ if (out_vec[1].len != sizeof(curve_type) ||
+ out_vec[2].len != sizeof(key_len)) {
+ attest_err = PSA_ATTEST_ERR_INVALID_INPUT;
+ goto error;
+ }
+
+ attest_err = attest_check_memory_access(key_buffer.ptr,
+ key_buffer.len,
+ TFM_ATTEST_ACCESS_RW);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ attest_err = attest_check_memory_access(out_vec[1].base,
+ out_vec[1].len,
+ TFM_ATTEST_ACCESS_RW);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ attest_err = attest_get_initial_attestation_public_key(&key_source,
+ &key_len,
+ &curve_type);
+ if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+ goto error;
+ }
+
+ if (key_buffer.len < key_len) {
+ attest_err = PSA_ATTEST_ERR_KEY_BUFFER_OVERFLOW;
+ goto error;
+ }
+
+ (void)tfm_memcpy(key_buffer.ptr, key_source, key_len);
+
+ *(psa_ecc_curve_t *)out_vec[1].base = curve_type;
+
+ *(size_t *)out_vec[2].base = key_len;
+
+error:
+ return attest_err;
+}
diff --git a/secure_fw/services/initial_attestation/psa_manifest/tfm_initial_attestation.h b/secure_fw/services/initial_attestation/psa_manifest/tfm_initial_attestation.h
index 5433654efc..203765df68 100644
--- a/secure_fw/services/initial_attestation/psa_manifest/tfm_initial_attestation.h
+++ b/secure_fw/services/initial_attestation/psa_manifest/tfm_initial_attestation.h
@@ -16,6 +16,7 @@ extern "C" {
#define TFM_ATTEST_GET_TOKEN_SIGNAL (1U << (0 + 4))
#define TFM_ATTEST_GET_TOKEN_SIZE_SIGNAL (1U << (1 + 4))
+#define TFM_ATTEST_GET_PUBLIC_KEY_SIGNAL (1U << (2 + 4))
#ifdef __cplusplus
}
diff --git a/secure_fw/services/initial_attestation/tfm_attestation_req_mngr.c b/secure_fw/services/initial_attestation/tfm_attestation_req_mngr.c
index 46bafc682d..1ee9fdd928 100644
--- a/secure_fw/services/initial_attestation/tfm_attestation_req_mngr.c
+++ b/secure_fw/services/initial_attestation/tfm_attestation_req_mngr.c
@@ -7,6 +7,7 @@
#include <string.h>
#include "psa/initial_attestation.h"
+#include "psa/crypto_types.h"
#include "attestation.h"
#ifdef TFM_PSA_API
@@ -14,6 +15,7 @@
#include "tfm_client.h"
#include "psa/service.h"
#include "region_defs.h"
+#include "tfm_plat_crypto_keys.h"
#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
@@ -97,6 +99,43 @@ static enum psa_attest_err_t psa_attest_get_token_size(const psa_msg_t *msg)
return status;
}
+static enum psa_attest_err_t tfm_attest_get_public_key(const psa_msg_t *msg)
+{
+ enum psa_attest_err_t status = PSA_ATTEST_ERR_SUCCESS;
+ uint8_t key_buf[ECC_P_256_KEY_SIZE];
+ size_t key_len;
+ psa_ecc_curve_t curve_type;
+
+ psa_outvec out_vec[] = {
+ {.base = key_buf, .len = sizeof(key_buf)},
+ {.base = &curve_type, .len = sizeof(curve_type)},
+ {.base = &key_len, .len = sizeof(key_len)}
+ };
+
+ if (msg->out_size[1] != out_vec[1].len ||
+ msg->out_size[2] != out_vec[2].len) {
+ return PSA_ATTEST_ERR_INVALID_INPUT;
+ }
+
+ /* Store the client ID here for later use in service. */
+ g_attest_caller_id = msg->client_id;
+
+ status = initial_attest_get_public_key(NULL, 0,
+ out_vec, IOVEC_LEN(out_vec));
+
+ if (msg->out_size[0] < key_len) {
+ return PSA_ATTEST_ERR_KEY_BUFFER_OVERFLOW;
+ }
+
+ if (status == PSA_ATTEST_ERR_SUCCESS) {
+ psa_write(msg->handle, 0, key_buf, key_len);
+ psa_write(msg->handle, 1, &curve_type, out_vec[1].len);
+ psa_write(msg->handle, 2, &key_len, out_vec[2].len);
+ }
+
+ return status;
+}
+
/*
* Fixme: Temporarily implement abort as infinite loop,
* will replace it later.
@@ -151,6 +190,9 @@ enum psa_attest_err_t attest_partition_init(void)
} else if (signals & TFM_ATTEST_GET_TOKEN_SIZE_SIGNAL) {
attest_signal_handle(TFM_ATTEST_GET_TOKEN_SIZE_SIGNAL,
psa_attest_get_token_size);
+ } else if (signals & TFM_ATTEST_GET_PUBLIC_KEY_SIGNAL) {
+ attest_signal_handle(TFM_ATTEST_GET_PUBLIC_KEY_SIGNAL,
+ tfm_attest_get_public_key);
} else {
tfm_abort();
}
diff --git a/secure_fw/services/initial_attestation/tfm_attestation_secure_api.c b/secure_fw/services/initial_attestation/tfm_attestation_secure_api.c
index c042009040..2f6754f539 100644
--- a/secure_fw/services/initial_attestation/tfm_attestation_secure_api.c
+++ b/secure_fw/services/initial_attestation/tfm_attestation_secure_api.c
@@ -97,3 +97,39 @@ psa_initial_attest_get_token_size(uint32_t challenge_size,
return (enum psa_attest_err_t)status;
}
+
+__attribute__((section("SFN")))
+enum psa_attest_err_t
+tfm_initial_attest_get_public_key(uint8_t *public_key,
+ size_t public_key_buf_size,
+ size_t *public_key_len,
+ psa_ecc_curve_t *elliptic_curve_type)
+{
+ psa_status_t status;
+
+ psa_outvec out_vec[] = {
+ {.base = public_key, .len = public_key_buf_size},
+ {.base = elliptic_curve_type, .len = sizeof(*elliptic_curve_type)},
+ {.base = public_key_len, .len = sizeof(*public_key_len)}
+ };
+
+#ifdef TFM_PSA_API
+ psa_handle_t handle = PSA_NULL_HANDLE;
+
+ handle = psa_connect(TFM_ATTEST_GET_PUBLIC_KEY_SID,
+ TFM_ATTEST_GET_PUBLIC_KEY_VERSION);
+ if (!PSA_HANDLE_IS_VALID(handle)) {
+ return PSA_ATTEST_ERR_GENERAL;
+ }
+
+ status = psa_call(handle, PSA_IPC_CALL,
+ NULL, 0,
+ out_vec, IOVEC_LEN(out_vec));
+ psa_close(handle);
+#else
+ status = tfm_initial_attest_get_public_key_veneer(NULL, 0,
+ out_vec, IOVEC_LEN(out_vec));
+#endif
+
+ return (enum psa_attest_err_t)status;
+}
diff --git a/secure_fw/services/initial_attestation/tfm_initial_attestation.yaml b/secure_fw/services/initial_attestation/tfm_initial_attestation.yaml
index 93b9d3e347..2e790aaf19 100644
--- a/secure_fw/services/initial_attestation/tfm_initial_attestation.yaml
+++ b/secure_fw/services/initial_attestation/tfm_initial_attestation.yaml
@@ -29,6 +29,14 @@
"non_secure_clients": true,
"version": 1,
"version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_ATTEST_GET_PUBLIC_KEY",
+ "signal": "INITIAL_ATTEST_GET_PUBLIC_KEY",
+ "sid": "0x00000022",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
}
],
"linker_pattern": {
@@ -50,6 +58,13 @@
"non_secure_clients": true,
"version": 1,
"version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_ATTEST_GET_PUBLIC_KEY",
+ "sid": "0x00000022",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
}
]
}
diff --git a/secure_fw/services/tfm_service_list.inc b/secure_fw/services/tfm_service_list.inc
index 9767f85215..bc6410cf56 100644
--- a/secure_fw/services/tfm_service_list.inc
+++ b/secure_fw/services/tfm_service_list.inc
@@ -141,6 +141,15 @@ const struct tfm_spm_service_db_t service_db[] =
.version = 1,
.version_policy = TFM_VERSION_POLICY_STRICT
},
+ {
+ .name = "TFM_ATTEST_GET_PUBLIC_KEY",
+ .partition_id = TFM_SP_INITIAL_ATTESTATION,
+ .signal = TFM_ATTEST_GET_PUBLIC_KEY_SIGNAL,
+ .sid = 0x00000022,
+ .non_secure_client = true,
+ .version = 1,
+ .version_policy = TFM_VERSION_POLICY_STRICT
+ },
#ifdef TFM_PARTITION_TEST_CORE
/******** TFM_SP_CORE_TEST ********/
@@ -547,6 +556,13 @@ struct tfm_spm_service_t service[] =
.msg_queue = {0},
.list = {0},
},
+ {
+ .service_db = NULL,
+ .partition = NULL,
+ .handle_list = {0},
+ .msg_queue = {0},
+ .list = {0},
+ },
#ifdef TFM_PARTITION_TEST_CORE
/******** TFM_SP_CORE_TEST ********/