diff options
author | David Vincze <david.vincze@arm.com> | 2019-11-21 00:19:50 +0100 |
---|---|---|
committer | David Vincze <david.vincze@arm.com> | 2019-11-29 16:35:36 +0100 |
commit | ff6da53ac651101ce38032131a26d46515687b71 (patch) | |
tree | ee6c7ce16dd8b7b84607f456d80a59bc3868c0c8 | |
parent | 20c3e4e2b96c7c43be3f6ea5cc2e1383518e4881 (diff) | |
download | trusted-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>
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 ********/ |