diff --git a/CMakeLists.txt b/CMakeLists.txt index b3a84b35e9..a7f92f5683 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -410,6 +410,7 @@ if(ENABLE_TESTING OR ENABLE_PROGRAMS) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/include PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/drivers/builtin/include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/drivers/everest/include PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/core PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tf-psa-crypto/drivers/builtin/src) diff --git a/ChangeLog.d/add-psa-iop-key-agreement.txt b/ChangeLog.d/add-psa-iop-key-agreement.txt new file mode 100644 index 0000000000..92dfde1843 --- /dev/null +++ b/ChangeLog.d/add-psa-iop-key-agreement.txt @@ -0,0 +1,4 @@ +Features + * Add an interruptible version of key agreement to the PSA interface. + See psa_key_agreement_iop_setup() and related functions. + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8318e8bf3b..eba6c51787 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,6 @@ set(libs ${mbedtls_target} + ${everest_target} ${CMAKE_THREAD_LIBS_INIT} ) diff --git a/tests/include/test/psa_test_wrappers.h b/tests/include/test/psa_test_wrappers.h index 7ab2bea6b9..4d674e74e0 100644 --- a/tests/include/test/psa_test_wrappers.h +++ b/tests/include/test/psa_test_wrappers.h @@ -475,13 +475,13 @@ psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_abort( psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_complete( psa_key_agreement_iop_t *arg0_operation, - psa_key_id_t *arg1_key); + mbedtls_svc_key_id_t *arg1_key); #define psa_key_agreement_iop_complete(arg0_operation, arg1_key) \ mbedtls_test_wrap_psa_key_agreement_iop_complete(arg0_operation, arg1_key) psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_setup( psa_key_agreement_iop_t *arg0_operation, - psa_key_id_t arg1_private_key, + mbedtls_svc_key_id_t arg1_private_key, const uint8_t *arg2_peer_key, size_t arg3_peer_key_length, psa_algorithm_t arg4_alg, diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.c b/tests/psa-client-server/psasim/src/psa_sim_serialise.c index e5c7225c84..44d87d60f1 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c @@ -1624,6 +1624,42 @@ int psasim_deserialise_mbedtls_svc_key_id_t(uint8_t **pos, return 1; } +size_t psasim_serialise_psa_key_agreement_iop_t_needs( + psa_key_agreement_iop_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_key_agreement_iop_t(uint8_t **pos, + size_t *remaining, + psa_key_agreement_iop_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_key_agreement_iop_t(uint8_t **pos, + size_t *remaining, + psa_key_agreement_iop_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + void psa_sim_serialize_reset(void) { memset(hash_operation_handles, 0, diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.h b/tests/psa-client-server/psasim/src/psa_sim_serialise.h index 523ce8028b..02f6bcbe32 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h @@ -1301,3 +1301,46 @@ int psasim_serialise_mbedtls_svc_key_id_t(uint8_t **pos, int psasim_deserialise_mbedtls_svc_key_id_t(uint8_t **pos, size_t *remaining, mbedtls_svc_key_id_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_key_agreement_iop_t() + * to serialise a `psa_key_agreement_iop_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_key_agreement_iop_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_key_agreement_iop_t_needs( + psa_key_agreement_iop_t value); + +/** Serialise a `psa_key_agreement_iop_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_key_agreement_iop_t(uint8_t **pos, + size_t *remaining, + psa_key_agreement_iop_t value); + +/** Deserialise a `psa_key_agreement_iop_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_key_agreement_iop_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_key_agreement_iop_t(uint8_t **pos, + size_t *remaining, + psa_key_agreement_iop_t *value); diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl index 31c93aeb20..054841ea3a 100755 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl @@ -48,7 +48,8 @@ my @types = qw(unsigned-int int size_t psa_key_derivation_operation_t psa_sign_hash_interruptible_operation_t psa_verify_hash_interruptible_operation_t - mbedtls_svc_key_id_t); + mbedtls_svc_key_id_t + psa_key_agreement_iop_t); grep(s/-/ /g, @types); diff --git a/tests/scripts/test_psa_constant_names.py b/tests/scripts/test_psa_constant_names.py index 6c402dcf20..8ed0fee4b6 100755 --- a/tests/scripts/test_psa_constant_names.py +++ b/tests/scripts/test_psa_constant_names.py @@ -163,6 +163,7 @@ def main(): parser.add_argument('--include', '-I', action='append', default=['tf-psa-crypto/include', 'tf-psa-crypto/drivers/builtin/include', + 'tf-psa-crypto/drivers/everest/include', 'include'], help='Directory for header files') parser.add_argument('--keep-c', diff --git a/tests/src/psa_test_wrappers.c b/tests/src/psa_test_wrappers.c index 6e42a8bba6..1277df0925 100644 --- a/tests/src/psa_test_wrappers.c +++ b/tests/src/psa_test_wrappers.c @@ -835,7 +835,7 @@ psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_abort( /* Wrapper for psa_key_agreement_iop_complete */ psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_complete( psa_key_agreement_iop_t *arg0_operation, - psa_key_id_t *arg1_key) + mbedtls_svc_key_id_t *arg1_key) { psa_status_t status = (psa_key_agreement_iop_complete)(arg0_operation, arg1_key); return status; @@ -844,7 +844,7 @@ psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_complete( /* Wrapper for psa_key_agreement_iop_setup */ psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_setup( psa_key_agreement_iop_t *arg0_operation, - psa_key_id_t arg1_private_key, + mbedtls_svc_key_id_t arg1_private_key, const uint8_t *arg2_peer_key, size_t arg3_peer_key_length, psa_algorithm_t arg4_alg, diff --git a/tf-psa-crypto/core/psa_crypto.c b/tf-psa-crypto/core/psa_crypto.c index e1e0eab69f..ceaa243d1c 100644 --- a/tf-psa-crypto/core/psa_crypto.c +++ b/tf-psa-crypto/core/psa_crypto.c @@ -7731,6 +7731,24 @@ exit: return (status == PSA_SUCCESS) ? unlock_status : status; } +static psa_status_t validate_key_agreement_params(const psa_key_attributes_t *attributes, + psa_algorithm_t alg) +{ + psa_key_type_t key_type; + + if (!PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + key_type = psa_get_key_type(attributes); + if (key_type != PSA_KEY_TYPE_DERIVE && key_type != PSA_KEY_TYPE_RAW_DATA + && key_type != PSA_KEY_TYPE_HMAC && key_type != PSA_KEY_TYPE_PASSWORD) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return PSA_SUCCESS; +} + psa_status_t psa_key_agreement(mbedtls_svc_key_id_t private_key, const uint8_t *peer_key, size_t peer_key_length, @@ -7741,14 +7759,12 @@ psa_status_t psa_key_agreement(mbedtls_svc_key_id_t private_key, psa_status_t status; uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE]; size_t shared_secret_len; - psa_key_type_t key_type; *key = MBEDTLS_SVC_KEY_ID_INIT; - key_type = psa_get_key_type(attributes); - if (key_type != PSA_KEY_TYPE_DERIVE && key_type != PSA_KEY_TYPE_RAW_DATA - && key_type != PSA_KEY_TYPE_HMAC && key_type != PSA_KEY_TYPE_PASSWORD) { - return PSA_ERROR_INVALID_ARGUMENT; + status = validate_key_agreement_params(attributes, alg); + if (status != PSA_SUCCESS) { + return status; } status = psa_raw_key_agreement(alg, private_key, peer_key, peer_key_length, shared_secret, @@ -7763,6 +7779,161 @@ psa_status_t psa_key_agreement(mbedtls_svc_key_id_t private_key, return status; } +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) + +static psa_status_t psa_key_agreement_iop_abort_internal(psa_key_agreement_iop_t *operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->id == 0) { + return PSA_SUCCESS; + } + + status = mbedtls_psa_key_agreement_iop_abort(&operation->mbedtls_ctx); + + operation->id = 0; + + return status; +} +#endif + +uint32_t psa_key_agreement_iop_get_num_ops( + psa_key_agreement_iop_t *operation) +{ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) + return operation->num_ops; +#else + (void) operation; + return 0; +#endif +} + +psa_status_t psa_key_agreement_iop_setup( + psa_key_agreement_iop_t *operation, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + psa_algorithm_t alg, + const psa_key_attributes_t *attributes) +{ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + + if (operation->id != 0 || operation->error_occurred) { + return PSA_ERROR_BAD_STATE; + } + + status = validate_key_agreement_params(attributes, alg); + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + return status; + } + + status = psa_get_and_lock_transparent_key_slot_with_policy( + private_key, &slot, PSA_KEY_USAGE_DERIVE, alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + operation->attributes = *attributes; + + operation->num_ops = 0; + + /* To be removed later when driver dispatch is added. */ + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + status = mbedtls_psa_key_agreement_iop_setup(&operation->mbedtls_ctx, + &slot->attr, slot->key.data, + slot->key.bytes, peer_key, + peer_key_length); + + operation->num_ops = mbedtls_psa_key_agreement_iop_get_num_ops(&operation->mbedtls_ctx); + +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + psa_key_agreement_iop_abort_internal(operation); + return status; + } + if (unlock_status != PSA_SUCCESS) { + operation->error_occurred = 1; + } + return unlock_status; +#else + (void) operation; + (void) private_key; + (void) peer_key; + (void) peer_key_length; + (void) alg; + (void) attributes; + return PSA_ERROR_NOT_SUPPORTED; +#endif +} + +psa_status_t psa_key_agreement_iop_complete( + psa_key_agreement_iop_t *operation, + mbedtls_svc_key_id_t *key) +{ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) + + if (operation->id == 0 || operation->error_occurred) { + return PSA_ERROR_BAD_STATE; + } + + psa_status_t status; + uint8_t intermediate_key[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE]; + size_t key_len = 0; + + status = mbedtls_psa_key_agreement_iop_complete(&operation->mbedtls_ctx, intermediate_key, + sizeof(intermediate_key), + &key_len); + + operation->num_ops = mbedtls_psa_key_agreement_iop_get_num_ops(&operation->mbedtls_ctx); + + if (status == PSA_SUCCESS) { + status = psa_import_key(&operation->attributes, intermediate_key, + key_len, key); + } + + if (status != PSA_SUCCESS && status != PSA_OPERATION_INCOMPLETE) { + operation->error_occurred = 1; + psa_key_agreement_iop_abort_internal(operation); + } + mbedtls_platform_zeroize(intermediate_key, sizeof(intermediate_key)); + return status; +#else + (void) operation; + (void) key; + return PSA_ERROR_BAD_STATE; +#endif +} + +psa_status_t psa_key_agreement_iop_abort( + psa_key_agreement_iop_t *operation) +{ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) + psa_status_t status; + + status = psa_key_agreement_iop_abort_internal(operation); + + operation->num_ops = 0; + operation->error_occurred = 0; + + return status; +#else + (void) operation; + return PSA_SUCCESS; +#endif +} + /****************************************************************/ /* Random generation */ /****************************************************************/ diff --git a/tf-psa-crypto/core/psa_crypto_core.h b/tf-psa-crypto/core/psa_crypto_core.h index 1753554830..d775761efa 100644 --- a/tf-psa-crypto/core/psa_crypto_core.h +++ b/tf-psa-crypto/core/psa_crypto_core.h @@ -700,6 +700,110 @@ psa_status_t psa_key_agreement_raw_builtin( size_t shared_secret_size, size_t *shared_secret_length); +/** + * \brief Get the total number of ops that a key agreement operation has taken + * since its start. + * + * \note The signature of this function is that of a PSA driver + * key_agreement_get_num_ops entry point. This function behaves as an + * key_agreement_get_num_ops entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in] operation The \c mbedtls_psa_key_agreement_interruptible_operation_t to use. + * This must be initialized first. + * + * \return Total number of operations. + */ +uint32_t mbedtls_psa_key_agreement_iop_get_num_ops( + mbedtls_psa_key_agreement_interruptible_operation_t *operation); + +/** + * \brief Set up a new interruptible key agreement operation. + * + * \note The signature of this function is that of a PSA driver + * key_agreement_setup entry point. This function behaves as a + * key_agreement_setup entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * \param[in] operation The \c psa_key_agreement_iop_t to use. + * This must be initialized first. + * \param[in] private_key_attributes The attributes of the private key to use for the + * operation. + * \param[in] private_key_buffer The buffer containing the private key + * context. + * \param[in] private_key_buffer_len Size of the \p private_key_buffer buffer in + * bytes. + * \param[in] peer_key The buffer containing the key context + * of the peer's public key. + * \param[in] peer_key_length Size of the \p peer_key buffer in + * bytes. + * \retval #PSA_SUCCESS + * The operation started successfully - call \c psa_key_agreement_complete() + * with the same context to complete the operation + * \retval #PSA_ERROR_INVALID_ARGUMENT + * An unsupported, incorrectly formatted or incorrect type of key was + * used. + * \retval #PSA_ERROR_NOT_SUPPORTED Either no internal interruptible operations + * are currently supported, or the key type is currently unsupported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * There was insufficient memory to load the key representation. + */ +psa_status_t mbedtls_psa_key_agreement_iop_setup( + mbedtls_psa_key_agreement_interruptible_operation_t *operation, + const psa_key_attributes_t *private_key_attributes, + const uint8_t *private_key_buffer, + size_t private_key_buffer_len, + const uint8_t *peer_key, + size_t peer_key_length); + +/** + * \brief Continue and eventually complete a key agreement operation. + * + * \note The signature of this function is that of a PSA driver + * key_agreement_complete entry point. This function behaves as a + * key_agreement_complete entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in] operation The \c mbedtls_psa_key_agreement_interruptible_operation_t to use. + * This must be initialized first. + * \param[out] shared_secret The buffer to which the shared secret + * is to be written. + * \param[in] shared_secret_size Size of the \p shared_secret buffer in + * bytes. + * \param[out] shared_secret_length On success, the number of bytes that make + * up the returned shared secret. + * \retval #PSA_SUCCESS + * The shared secret was calculated successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * Internal interruptible operations are currently not supported. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p shared_secret_size is too small + */ +psa_status_t mbedtls_psa_key_agreement_iop_complete( + mbedtls_psa_key_agreement_interruptible_operation_t *operation, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length); + +/** + * \brief Abort a key agreement operation. + * + * \note The signature of this function is that of a PSA driver + * key_agreement_abort entry point. This function behaves as a + * key_agreement_abort entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in] operation The \c mbedtls_psa_key_agreement_interruptible_operation_t to abort. + * This must be initialized first. + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + */ +psa_status_t mbedtls_psa_key_agreement_iop_abort( + mbedtls_psa_key_agreement_interruptible_operation_t *operation); + + /** * \brief Set the maximum number of ops allowed to be executed by an * interruptible function in a single call. diff --git a/tf-psa-crypto/drivers/builtin/include/mbedtls/bignum.h b/tf-psa-crypto/drivers/builtin/include/mbedtls/bignum.h index 22d5d84840..40b7277d1b 100644 --- a/tf-psa-crypto/drivers/builtin/include/mbedtls/bignum.h +++ b/tf-psa-crypto/drivers/builtin/include/mbedtls/bignum.h @@ -238,7 +238,7 @@ typedef struct mbedtls_mpi { } mbedtls_mpi; -#define MBEDTLS_MPI_INIT { 0, 0, 0 } +#define MBEDTLS_MPI_INIT { 0, 1, 0 } /** * \brief Initialize an MPI context. diff --git a/tf-psa-crypto/drivers/builtin/include/mbedtls/ecdh.h b/tf-psa-crypto/drivers/builtin/include/mbedtls/ecdh.h index a6a5069337..3d3e479fea 100644 --- a/tf-psa-crypto/drivers/builtin/include/mbedtls/ecdh.h +++ b/tf-psa-crypto/drivers/builtin/include/mbedtls/ecdh.h @@ -95,6 +95,17 @@ typedef struct mbedtls_ecdh_context_mbed { } mbedtls_ecdh_context_mbed; #endif +#if defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_ECDH_CONTEXT_MBED_INIT { MBEDTLS_ECP_GROUP_INIT, MBEDTLS_MPI_INIT, \ + MBEDTLS_ECP_POINT_INIT, \ + MBEDTLS_ECP_POINT_INIT, MBEDTLS_MPI_INIT, \ + MBEDTLS_ECP_RESTART_INIT } +#else +#define MBEDTLS_ECDH_CONTEXT_MBED_INIT { MBEDTLS_ECP_GROUP_INIT, MBEDTLS_MPI_INIT, \ + MBEDTLS_ECP_POINT_INIT, \ + MBEDTLS_ECP_POINT_INIT, MBEDTLS_MPI_INIT } +#endif + /** * * \warning Performing multiple operations concurrently on the same @@ -141,6 +152,35 @@ typedef struct mbedtls_ecdh_context { } mbedtls_ecdh_context; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +#if defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_ECDH_CONTEXT_INIT { MBEDTLS_ECP_GROUP_INIT, MBEDTLS_MPI_INIT, \ + MBEDTLS_ECP_POINT_INIT, \ + MBEDTLS_ECP_POINT_INIT, MBEDTLS_MPI_INIT, \ + MBEDTLS_ECP_PF_UNCOMPRESSED, \ + MBEDTLS_ECP_POINT_INIT, MBEDTLS_ECP_POINT_INIT, \ + MBEDTLS_MPI_INIT, 0, \ + MBEDTLS_ECP_RESTART_INIT } +#else +#define MBEDTLS_ECDH_CONTEXT_INIT { MBEDTLS_ECP_GROUP_INIT, MBEDTLS_MPI_INIT, \ + MBEDTLS_ECP_POINT_INIT, \ + MBEDTLS_ECP_POINT_INIT, MBEDTLS_MPI_INIT, \ + MBEDTLS_ECP_PF_UNCOMPRESSED, \ + MBEDTLS_ECP_POINT_INIT, MBEDTLS_ECP_POINT_INIT, \ + MBEDTLS_MPI_INIT } +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else +#if defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_ECDH_CONTEXT_INIT { MBEDTLS_ECP_PF_UNCOMPRESSED, MBEDTLS_ECP_DP_NONE, \ + MBEDTLS_ECDH_VARIANT_NONE, \ + { MBEDTLS_ECDH_CONTEXT_MBED_INIT }, 0 } +#else +#define MBEDTLS_ECDH_CONTEXT_INIT { MBEDTLS_ECP_PF_UNCOMPRESSED, MBEDTLS_ECP_DP_NONE, \ + MBEDTLS_ECDH_VARIANT_NONE, \ + { MBEDTLS_ECDH_CONTEXT_MBED_INIT } } +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ + /** * \brief Return the ECP group for provided context. * diff --git a/tf-psa-crypto/drivers/builtin/include/mbedtls/ecp.h b/tf-psa-crypto/drivers/builtin/include/mbedtls/ecp.h index b3406142fe..87d63ed13f 100644 --- a/tf-psa-crypto/drivers/builtin/include/mbedtls/ecp.h +++ b/tf-psa-crypto/drivers/builtin/include/mbedtls/ecp.h @@ -255,6 +255,7 @@ mbedtls_ecp_group; #define MBEDTLS_ECP_GROUP_INIT { MBEDTLS_ECP_DP_NONE, MBEDTLS_MPI_INIT, MBEDTLS_MPI_INIT, \ MBEDTLS_MPI_INIT, MBEDTLS_ECP_POINT_INIT, MBEDTLS_MPI_INIT, \ 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0 } + /** * \name SECTION: Module settings * @@ -372,6 +373,8 @@ typedef struct { mbedtls_ecp_restart_muladd_ctx *MBEDTLS_PRIVATE(ma); /*!< ecp_muladd() sub-context */ } mbedtls_ecp_restart_ctx; +#define MBEDTLS_ECP_RESTART_INIT { 0, 0, NULL, NULL } + /* * Operation counts for restartable functions */ diff --git a/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.c b/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.c index acb248293a..57b10c9f50 100644 --- a/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.c +++ b/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.c @@ -630,47 +630,110 @@ psa_status_t mbedtls_psa_generate_key_iop_abort( /* Interruptible ECC Key Agreement */ /****************************************************************/ -uint32_t psa_key_agreement_iop_get_num_ops( - psa_key_agreement_iop_t *operation) +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) && defined(MBEDTLS_ECP_RESTARTABLE) + +uint32_t mbedtls_psa_key_agreement_iop_get_num_ops( + mbedtls_psa_key_agreement_interruptible_operation_t *operation) { - (void) operation; - return 0; + return operation->num_ops; } -psa_status_t psa_key_agreement_iop_setup( - psa_key_agreement_iop_t *operation, - psa_key_id_t private_key, +psa_status_t mbedtls_psa_key_agreement_iop_setup( + mbedtls_psa_key_agreement_interruptible_operation_t *operation, + const psa_key_attributes_t *private_key_attributes, + const uint8_t *private_key_buffer, + size_t private_key_buffer_len, const uint8_t *peer_key, - size_t peer_key_length, - psa_algorithm_t alg, - const psa_key_attributes_t *attributes) + size_t peer_key_length) { - (void) operation; - (void) private_key; - (void) peer_key; - (void) peer_key_length; - (void) alg; - (void) attributes; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *our_key = NULL; + mbedtls_ecp_keypair *their_key = NULL; + mbedtls_ecdh_init(&operation->ctx); + mbedtls_ecdh_enable_restart(&operation->ctx); + + /* We need to clear number of ops here in case there was a previous + complete operation which doesn't reset it after finsishing. */ + operation->num_ops = 0; + + status = mbedtls_psa_ecp_load_representation( + psa_get_key_type(private_key_attributes), + psa_get_key_bits(private_key_attributes), + private_key_buffer, + private_key_buffer_len, + &our_key); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params(&operation->ctx, our_key, MBEDTLS_ECDH_OURS)); + if (status != PSA_SUCCESS) { + goto exit; + } + + mbedtls_ecp_keypair_free(our_key); + mbedtls_free(our_key); + our_key = NULL; + + status = mbedtls_psa_ecp_load_representation( + PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(psa_get_key_type(private_key_attributes)), + psa_get_key_bits(private_key_attributes), + peer_key, + peer_key_length, + &their_key); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* mbedtls_psa_ecp_load_representation() calls mbedtls_ecp_check_pubkey() which + takes MBEDTLS_ECP_OPS_CHK amount of ops. */ + operation->num_ops += MBEDTLS_ECP_OPS_CHK; + + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params(&operation->ctx, their_key, MBEDTLS_ECDH_THEIRS)); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + mbedtls_ecp_keypair_free(our_key); + mbedtls_free(our_key); + mbedtls_ecp_keypair_free(their_key); + mbedtls_free(their_key); + return status; +} + +psa_status_t mbedtls_psa_key_agreement_iop_complete( + mbedtls_psa_key_agreement_interruptible_operation_t *operation, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops()); + + status = mbedtls_to_psa_error(mbedtls_ecdh_calc_secret(&operation->ctx, shared_secret_length, + shared_secret, + shared_secret_size, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE)); + + operation->num_ops += operation->ctx.rs.ops_done; + + return status; +} + +psa_status_t mbedtls_psa_key_agreement_iop_abort( + mbedtls_psa_key_agreement_interruptible_operation_t *operation) +{ + operation->num_ops = 0; + mbedtls_ecdh_free(&operation->ctx); return PSA_SUCCESS; } -psa_status_t psa_key_agreement_iop_complete( - psa_key_agreement_iop_t *operation, - psa_key_id_t *key) -{ - (void) operation; - (void) key; - - return PSA_SUCCESS; -} - -psa_status_t psa_key_agreement_iop_abort( - psa_key_agreement_iop_t *operation) -{ - (void) operation; - - return PSA_SUCCESS; -} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/tf-psa-crypto/drivers/everest/include/everest/everest.h b/tf-psa-crypto/drivers/everest/include/everest/everest.h index 392e7924a9..f83413e024 100644 --- a/tf-psa-crypto/drivers/everest/include/everest/everest.h +++ b/tf-psa-crypto/drivers/everest/include/everest/everest.h @@ -41,6 +41,7 @@ typedef struct { mbedtls_x25519_context ctx; } mbedtls_ecdh_context_everest; +#define MBEDTLS_ECDH_CONTEXT_EVEREST_INIT {MBEDTLS_X25519_CONTEXT_INIT} /** * \brief This function sets up the ECDH context with the information diff --git a/tf-psa-crypto/drivers/everest/include/everest/x25519.h b/tf-psa-crypto/drivers/everest/include/everest/x25519.h index ef314d2f3b..39d01dee0d 100644 --- a/tf-psa-crypto/drivers/everest/include/everest/x25519.h +++ b/tf-psa-crypto/drivers/everest/include/everest/x25519.h @@ -47,6 +47,8 @@ typedef struct unsigned char peer_point[MBEDTLS_X25519_KEY_SIZE_BYTES]; } mbedtls_x25519_context; +#define MBEDTLS_X25519_CONTEXT_INIT {{0}, {0}} + /** * \brief This function initializes an x25519 context. * diff --git a/tf-psa-crypto/drivers/p256-m/CMakeLists.txt b/tf-psa-crypto/drivers/p256-m/CMakeLists.txt index af046da7be..ae44123ca9 100644 --- a/tf-psa-crypto/drivers/p256-m/CMakeLists.txt +++ b/tf-psa-crypto/drivers/p256-m/CMakeLists.txt @@ -12,6 +12,7 @@ target_include_directories(${p256m_target} $ $ $ + $ $ PRIVATE ${MBEDTLS_DIR}/library/ ${TF_PSA_CRYPTO_DIR}/core) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 58b68870f5..62f1dcad75 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -5123,7 +5123,7 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); psa_status_t psa_key_agreement_iop_setup( psa_key_agreement_iop_t *operation, - psa_key_id_t private_key, + mbedtls_svc_key_id_t private_key, const uint8_t *peer_key, size_t peer_key_length, psa_algorithm_t alg, @@ -5208,7 +5208,7 @@ psa_status_t psa_key_agreement_iop_setup( */ psa_status_t psa_key_agreement_iop_complete( psa_key_agreement_iop_t *operation, - psa_key_id_t *key); + mbedtls_svc_key_id_t *key); /** * \brief Abort a key agreement operation. diff --git a/tf-psa-crypto/include/psa/crypto_builtin_composites.h b/tf-psa-crypto/include/psa/crypto_builtin_composites.h index c9c0c6b870..14e759b13d 100644 --- a/tf-psa-crypto/include/psa/crypto_builtin_composites.h +++ b/tf-psa-crypto/include/psa/crypto_builtin_composites.h @@ -33,6 +33,10 @@ #endif #include "mbedtls/chachapoly.h" +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) +#include "mbedtls/ecdh.h" +#endif + /* * MAC multi-part operation definitions. */ @@ -227,4 +231,21 @@ typedef struct { #define MBEDTLS_PSA_GENERATE_KEY_IOP_INIT { 0 } #endif +/* Context structure for the Mbed TLS interruptible key agreement implementation. */ +typedef struct { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) && defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecdh_context MBEDTLS_PRIVATE(ctx); + uint32_t MBEDTLS_PRIVATE(num_ops); +#else + /* Make the struct non-empty if algs not supported. */ + unsigned MBEDTLS_PRIVATE(dummy); +#endif +} mbedtls_psa_key_agreement_interruptible_operation_t; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) && defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_PSA_KEY_AGREEMENT_IOP_INIT { MBEDTLS_ECDH_CONTEXT_INIT, 0 } +#else +#define MBEDTLS_PSA_KEY_AGREEMENT_IOP_INIT { 0 } +#endif + #endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */ diff --git a/tf-psa-crypto/include/psa/crypto_struct.h b/tf-psa-crypto/include/psa/crypto_struct.h index 76ef5c4394..ded3af02e3 100644 --- a/tf-psa-crypto/include/psa/crypto_struct.h +++ b/tf-psa-crypto/include/psa/crypto_struct.h @@ -508,14 +508,18 @@ struct psa_key_agreement_iop_s { * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); - + mbedtls_psa_key_agreement_interruptible_operation_t MBEDTLS_PRIVATE(mbedtls_ctx); + uint32_t MBEDTLS_PRIVATE(num_ops); + psa_key_attributes_t MBEDTLS_PRIVATE(attributes); + unsigned int MBEDTLS_PRIVATE(error_occurred) : 1; #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_KEY_AGREEMENT_IOP_INIT { 0 } #else -#define PSA_KEY_AGREEMENT_IOP_INIT { 0 } +#define PSA_KEY_AGREEMENT_IOP_INIT { 0, MBEDTLS_PSA_KEY_AGREEMENT_IOP_INIT, 0, \ + PSA_KEY_ATTRIBUTES_INIT, 0 } #endif static inline struct psa_key_agreement_iop_s diff --git a/tf-psa-crypto/tests/suites/test_suite_psa_crypto.data b/tf-psa-crypto/tests/suites/test_suite_psa_crypto.data index dab2ee75a4..707e5b002b 100644 --- a/tf-psa-crypto/tests/suites/test_suite_psa_crypto.data +++ b/tf-psa-crypto/tests/suites/test_suite_psa_crypto.data @@ -7357,6 +7357,102 @@ PSA key agreement: FFDH RFC7919 6144 key + HKDF-SHA256: read 1+255 depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT:PSA_WANT_DH_RFC7919_6144 key_agreement_output:PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):"bbaec0a6c20e67aa77bd9db1f682b20227d3e17944ccf9ea639e437202309c29dc876a8d209e81e59e1d7584284089c4ffb3356e28acca6c94164752e7e331cee7fccdb3d08604a5faaf91c02cab4ea6ad2926e28d1dee9fadd437b2b8a5116c689869c0972529e4c362aaa8427c95f42d8a60c1f38f9f672c837a097bcd1a8c068c11a33ce36517915dae1ba47e2646aef079e6c84b9656991ef0f6ceb9f7f95c97e7232cc5c41c0335aed99169133702cb8d95ef1e9eb5af583f3469a77277243fe61f16dd5b4f9f4972e3d30050f289f891daf8146ff87cf2845c419dfe2ca0525c5e2e8fc6566d7118fadaf0103b24319061f862e2584e5fba1063d55365b78379820d335ee924ac0871ceb3a2a339fba250011371b53426bab5f48e9704b7a9e77d14d5f6cafcfbdb45463e6935be31bc87eafd9b6d228a5b76c2baa6364f450a4ac557dd07ed4b1a13f5603e2b3bb270e831f0f2950f52c52d866fdaeb748a4cbb6f20b332795fffb8cf77a34ef75d8105973f1fdada6a3b050a28c12268104a8f1cce9a86ebce1749a97e9e5f00608229799aa5b7a356fca7b8bb5c7829cb18a136836bb37f5165deb89b33f0b69c473236025bc649d382d008fbc7c8c84390b9d86b173e45fa1e162e0eabd7914f2ec4c26d5350be064fc0d68bf16446188dd4a76ac1267a63b764070b48342a884891eeddbba95257348764c646aef160523af105a719aedb041a28b81516dbe89e80592f687eb341aff447a4165ac145889ae3e8a14c948c82b581b35d8f7d1c4f5e0f838773a472ad0025b1ca0b1c8bfe58c42079194b9aa9c5a1139472e7f917655a3ae297c9a8e3bfa6e108242a5ac01b92a9e94d7b51fbe2732d68f1ec5c12607add5e9bddbe5a4837e9fa16a66b5d83456df4f9febb14158dc5ea467b7cc288fe58f28cade38fa3d4c8864c3cb93bda6d39ad28f7dab8b8c0be34f675d268d82ba6a2e22ba49a5e7de5d08edae35ec17d1419288719a4f82dfb7aad6f7b68c4216c69b83af7438771622e48381841d1fcb6081d41b1b84eae37912b34dc8df1794bb47ad87f94d9c841aa98":"31b48495f611fd0205994fc523bfbc6b72949417f28392d30c1c98878bde0ca467ab6d6fe58522df9749154f95c9683f9590c295cd2b62ff9c59f2a71aaa3f7cb72761740cdcac8994c3623e8c07e2991dac60c2ccba818623013467cfca64f9a3b58523d4a4982571365db08aa9de048303c2a48d1c02c9aafc2ecd6eaae1c5bce8314503d0711d755b59134cbfc773250690121f58fc5171ea34fe88e753d5ab3da23e0557aa326b408c2f55aad2b6f40504509c2203f353bcb17e7b2c61fdcba04c3f8c136ef5d14c38ded6ff0455f59f3052b52b2d45f76a2c3b4b09af388a57ebd9d33393853b83b8033b6973cf662907e62380b66b4ce04b82ab8fcd35f40083a330587e27daa0f84c21fc5d04af03104785f85cb880ae61024cf6cfd1dc14149fdff6653968458fb5761cf2cbf8263e915099eb209d1d149bd7a5b4e48b108f07a1f7c17aa4cbf7b3aa25075956f93f127d46b6392834e7781e46f0e2d1ba14ce2f2d91f9db106bf94c7110ace1bf6105cd9351031e0ec7b52a599ae41256581c1379be5882c352c750709c1b8d37cd8d1442ae5547db0f5a1371eca211f028428572a0fcc4c0852ec1f9be4de14a32536087f520cdeaf54c52b203bb6ff0008b2099fb0e1dff4547563a71db416c5b97ef8e7677d8edd15a2ae75dc64b817117fe5e0478cfa1a18e15cb44cfcc990c5f01127b3906187c18562c876631a046a70015e84b6c553be23168e572cedb5912a6505ff8bb65722cc0e9556e967600711b8d8a8e414811c9809aa3e15f680fdbb2b2297e414824fda530b501b278c35f3f0f0ac61da3262de7b8aa44e31544c593c8521f8ce4921b8d7df7d7382c97718efd03650caa5620bc0e6fb9753dfe26c78b0b6a3231391b9324ee6b7c81b45e7e90e5573ab6cb263b114d78eaba7eb2bc668dd57b6eef126abcdf8355656beac58ddbaeb0551a4083fd5a2bd0e405d35737b7c3c6f0f0190403c13b57e3ef7b6b76206725758523ef98e4053fb8e05147a74577b61b0935dc5eb699945d3290e78bcc9015c9c3210ffed7d6e96c6c8202e46ad37155d07f3e8c2d9a":"10":"5d324ec021d57640dee474c442f3a25390de6ff13175f70fad977003bd78fcdfeda87d2a5cc8447b9729990b11e7949c6ebb37a2d3c2fa69a85d79d216a6a489c8c5186576c112ca94c1bce156b819fb010a4168e8c91e777b87dceb0de4f1828c45297e3b513f4ff57bfb874a7c0d3cd709332922394bcddbc0bf959668810ce1ec8dbff662ea620b9ee7186cdde9845185ea87ded242fbffb7f526d875b6b1dbd09a4008b4d2c1034621a75efd6140c7d6fc883d79f7c3b7f7ae21b74e62a9c26f682c9dd48cacdc7f0c4ec5eb32a5c505aa5949d4008ece502bca5612f84ae73164acd2d3399cc9aee5cf615de62dd31c63a407f5c988b5c61a124ce08c" +PSA key agreement interruptible: ECDH SECP256R1 (RFC 5903): Num of ops: 5 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":5 + +PSA key agreement interruptible: ECDH SECP256R1 (RFC 5903): Num of ops: 100 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":100 + +PSA key agreement interruptible: ECDH SECP256R1 (RFC 5903): Num of ops: 0 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":0 + +PSA key agreement interruptible: ECDH SECP256R1 (RFC 5903): Num of ops: Max +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED + +PSA key agreement interruptible: ECDH SECP384R1 (RFC 5903): Num of ops: 5 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_384 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"04e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":"11187331c279962d93d604243fd592cb9d0a926f422e47187521287e7156c5c4d603135569b9e9d09cf5d4a270f59746":5 + +PSA key agreement interruptible: ECDH SECP384R1 (RFC 5903): Num of ops: 100 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_384 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"04e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":"11187331c279962d93d604243fd592cb9d0a926f422e47187521287e7156c5c4d603135569b9e9d09cf5d4a270f59746":100 + +PSA key agreement interruptible: ECDH SECP384R1 (RFC 5903): Num of ops: 0 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_384 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"04e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":"11187331c279962d93d604243fd592cb9d0a926f422e47187521287e7156c5c4d603135569b9e9d09cf5d4a270f59746":0 + +PSA key agreement interruptible: ECDH SECP384R1 (RFC 5903): Num of ops: Max +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_384 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"04e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":"11187331c279962d93d604243fd592cb9d0a926f422e47187521287e7156c5c4d603135569b9e9d09cf5d4a270f59746":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED + +PSA key agreement interruptible: ECDH SECP521R1 (RFC 5903): Num of ops: 5 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_521 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"0400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":"01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f97894e5e6b2d79b04d1427e73ca4baa240a34786859810c06b3c715a3a8cc3151f2bee417996d19f3ddea":5 + +PSA key agreement interruptible: ECDH SECP521R1 (RFC 5903): Num of ops: 100 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_521 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"0400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":"01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f97894e5e6b2d79b04d1427e73ca4baa240a34786859810c06b3c715a3a8cc3151f2bee417996d19f3ddea":100 + +PSA key agreement interruptible: ECDH SECP521R1 (RFC 5903): Num of ops: 0 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_521 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"0400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":"01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f97894e5e6b2d79b04d1427e73ca4baa240a34786859810c06b3c715a3a8cc3151f2bee417996d19f3ddea":0 + +PSA key agreement interruptible: ECDH SECP521R1 (RFC 5903): Num of ops: Max +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_521 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"0400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":"01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f97894e5e6b2d79b04d1427e73ca4baa240a34786859810c06b3c715a3a8cc3151f2bee417996d19f3ddea":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED + +PSA key agreement interruptible: ECDH brainpoolP256r1 (RFC 7027): Num of ops: 5 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_256 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":"89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b":5 + +PSA key agreement interruptible: ECDH brainpoolP256r1 (RFC 7027): Num of ops: 100 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_256 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":"89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b":100 + +PSA key agreement interruptible: ECDH brainpoolP256r1 (RFC 7027): Num of ops: 0 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_256 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":"89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b":0 + +PSA key agreement interruptible: ECDH brainpoolP256r1 (RFC 7027): Num of ops: Max +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_256 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":"89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED + +PSA key agreement interruptible: ECDH brainpoolP384r1 (RFC 7027): Num of ops: 5 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_384 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042":"044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48":"0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42":5 + +PSA key agreement interruptible: ECDH brainpoolP384r1 (RFC 7027): Num of ops: 100 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_384 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042":"044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48":"0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42":100 + +PSA key agreement interruptible: ECDH brainpoolP384r1 (RFC 7027): Num of ops: 0 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_384 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042":"044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48":"0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42":0 + +PSA key agreement interruptible: ECDH brainpoolP384r1 (RFC 7027): Num of ops: Max +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_384 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042":"044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48":"0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED + +PSA key agreement interruptible: ECDH brainpoolP512r1 (RFC 7027): Num of ops: 5 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_512 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422":"049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa":"a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f":5 + +PSA key agreement interruptible: ECDH brainpoolP512r1 (RFC 7027): Num of ops: 100 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_512 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422":"049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa":"a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f":100 + +PSA key agreement interruptible: ECDH brainpoolP512r1 (RFC 7027): Num of ops: 0 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_512 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422":"049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa":"a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f":0 + +PSA key agreement interruptible: ECDH brainpoolP512r1 (RFC 7027): Num of ops: Max +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_512 +key_agreement_interruptible:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422":"049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa":"a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED + PSA generate random: 0 bytes generate_random:0 diff --git a/tf-psa-crypto/tests/suites/test_suite_psa_crypto.function b/tf-psa-crypto/tests/suites/test_suite_psa_crypto.function index eaafd90ff4..99e88807e7 100644 --- a/tf-psa-crypto/tests/suites/test_suite_psa_crypto.function +++ b/tf-psa-crypto/tests/suites/test_suite_psa_crypto.function @@ -1234,6 +1234,37 @@ static void interruptible_signverify_get_minmax_completes(uint32_t max_ops, *max_completes = 1; } } + +/* ECP need to block for a minimum number of operations even if max_ops is set to a + lower value. This functions calculates this minimum value given the curve size + and the window size. */ +static uint32_t interruptible_key_agreement_get_min_num_ops(size_t key_bits) +{ + /* Those values are taken from documentation of mbedtls_ecp_set_max_ops() + in ecp.h. Those values can change at any time. */ + switch (key_bits) { + case 256: + { + const uint32_t min_values[5] = { 208, 208, 160, 136, 124 }; // P-256 + return min_values[6 - MBEDTLS_ECP_WINDOW_SIZE]; + break; + } + case 384: + { + const uint32_t min_values[5] = { 682, 416, 320, 272, 248 }; // P-384 + return min_values[6 - MBEDTLS_ECP_WINDOW_SIZE]; + break; + } + case 512: + case 521: + { + const uint32_t min_values[5] = { 1364, 832, 640, 544, 496 }; // P-521 + return min_values[6 - MBEDTLS_ECP_WINDOW_SIZE]; + break; + } + } + return 0; +} #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) && defined(MBEDTLS_ASN1_PARSE_C) @@ -9826,6 +9857,116 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */ +void key_agreement_interruptible(int alg_arg, + int our_key_type_arg, data_t *our_key_data, + data_t *peer_key_data, + data_t *expected_output, int max_ops_arg) +{ + mbedtls_svc_key_id_t our_key = MBEDTLS_SVC_KEY_ID_INIT; + mbedtls_svc_key_id_t output_key = MBEDTLS_SVC_KEY_ID_INIT; + psa_algorithm_t alg = alg_arg; + psa_key_type_t our_key_type = our_key_type_arg; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_attributes_t shared_secret_attributes = PSA_KEY_ATTRIBUTES_INIT; + unsigned char *output = NULL; + size_t output_length = ~0; + size_t key_bits; + uint32_t max_ops = max_ops_arg; + uint32_t num_ops = 0; + uint32_t min_num_ops = 0; + size_t num_ops_prior = 0; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + + psa_key_agreement_iop_t operation = psa_key_agreement_iop_init(); + + PSA_ASSERT(psa_crypto_init()); + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, our_key_type); + PSA_ASSERT(psa_import_key(&attributes, + our_key_data->x, our_key_data->len, + &our_key)); + + PSA_ASSERT(psa_get_key_attributes(our_key, &attributes)); + key_bits = psa_get_key_bits(&attributes); + + psa_set_key_type(&shared_secret_attributes, PSA_KEY_TYPE_DERIVE); + psa_set_key_usage_flags(&shared_secret_attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT); + + /* Validate size macros */ + TEST_LE_U(expected_output->len, + PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(our_key_type, key_bits)); + TEST_LE_U(PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(our_key_type, key_bits), + PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE); + + psa_interruptible_set_max_ops(max_ops); + + TEST_CALLOC(output, expected_output->len); + + num_ops_prior = psa_key_agreement_iop_get_num_ops(&operation); + TEST_EQUAL(num_ops_prior, 0); + + PSA_ASSERT(psa_key_agreement_iop_setup(&operation, our_key, peer_key_data->x, + peer_key_data->len, alg, &shared_secret_attributes)); + + num_ops_prior = psa_key_agreement_iop_get_num_ops(&operation); + /* psa_key_agreement_iop_setup() takes a number of ops because it calls + mbedtls_ecp_check_pubkey() */ + TEST_EQUAL(num_ops_prior, MBEDTLS_ECP_OPS_CHK); + + min_num_ops = interruptible_key_agreement_get_min_num_ops(key_bits); + + do { + + status = psa_key_agreement_iop_complete(&operation, &output_key); + + if (status == PSA_SUCCESS || status == PSA_OPERATION_INCOMPLETE) { + /* Ensure that each operation finished in less than or equal + maximum number of operations specefied unless the maximum + number of operations was less than the minium possible for + the curve size. */ + num_ops = psa_key_agreement_iop_get_num_ops(&operation); + if (max_ops <= min_num_ops) { + TEST_LE_U(num_ops - num_ops_prior, min_num_ops); + } else { + TEST_LE_U(num_ops - num_ops_prior, max_ops); + } + + num_ops_prior = num_ops; + + /* Ensure calling get_num_ops() twice still returns the same + * number of ops as previously reported. */ + num_ops = psa_key_agreement_iop_get_num_ops(&operation); + + TEST_EQUAL(num_ops, num_ops_prior); + } + } while (status == PSA_OPERATION_INCOMPLETE); + + TEST_EQUAL(status, PSA_SUCCESS); + + PSA_ASSERT(psa_export_key(output_key, output, expected_output->len, &output_length)); + + TEST_MEMORY_COMPARE(output, output_length, + expected_output->x, expected_output->len); + + PSA_ASSERT(psa_key_agreement_iop_abort(&operation)); + + num_ops = psa_key_agreement_iop_get_num_ops(&operation); + TEST_EQUAL(num_ops, 0); + +exit: + psa_destroy_key(our_key); + psa_destroy_key(output_key); + mbedtls_free(output); + PSA_DONE(); +} + +/* END_CASE */ + + /* BEGIN_CASE */ void key_agreement_capacity(int alg_arg, int our_key_type_arg, data_t *our_key_data,