Merge pull request #9490 from waleed-elmelegy-arm/add-iop-key-agrmnt-api

Add PSA interruptible key agreement APIs
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3a84b3..a7f92f5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -410,6 +410,7 @@
         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 0000000..92dfde1
--- /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 8318e8b..eba6c51 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 7ab2bea..4d674e7 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_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 e5c7225..44d87d6 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 @@
     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 523ce80..02f6bcb 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_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 31c93ae..054841e 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 @@
                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 6c402dc..8ed0fee 100755
--- a/tests/scripts/test_psa_constant_names.py
+++ b/tests/scripts/test_psa_constant_names.py
@@ -163,6 +163,7 @@
     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 6e42a8b..1277df0 100644
--- a/tests/src/psa_test_wrappers.c
+++ b/tests/src/psa_test_wrappers.c
@@ -835,7 +835,7 @@
 /* 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 @@
 /* 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 e1e0eab..ceaa243 100644
--- a/tf-psa-crypto/core/psa_crypto.c
+++ b/tf-psa-crypto/core/psa_crypto.c
@@ -7731,6 +7731,24 @@
     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 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 @@
     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 1753554..d775761 100644
--- a/tf-psa-crypto/core/psa_crypto_core.h
+++ b/tf-psa-crypto/core/psa_crypto_core.h
@@ -701,6 +701,110 @@
     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 22d5d84..40b7277 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 @@
 }
 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 a6a5069..3d3e479 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 @@
 } 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 @@
 }
 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 b340614..87d63ed 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 @@
 #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 @@
     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 acb2482..57b10c9 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 @@
 /* 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 392e792..f83413e 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 @@
     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 ef314d2..39d01de 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 @@
   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 af046da..ae44123 100644
--- a/tf-psa-crypto/drivers/p256-m/CMakeLists.txt
+++ b/tf-psa-crypto/drivers/p256-m/CMakeLists.txt
@@ -12,6 +12,7 @@
          $<BUILD_INTERFACE:${MBEDTLS_DIR}/include>
          $<BUILD_INTERFACE:${TF_PSA_CRYPTO_DIR}/include>
          $<BUILD_INTERFACE:${TF_PSA_CRYPTO_DIR}/drivers/builtin/include>
+         $<BUILD_INTERFACE:${TF_PSA_CRYPTO_DIR}/drivers/everest/include>
          $<INSTALL_INTERFACE:include>
   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 58b6887..62f1dca 100644
--- a/tf-psa-crypto/include/psa/crypto.h
+++ b/tf-psa-crypto/include/psa/crypto.h
@@ -5123,7 +5123,7 @@
 
 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_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 c9c0c6b..14e759b 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 @@
 #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 76ef5c4..ded3af0 100644
--- a/tf-psa-crypto/include/psa/crypto_struct.h
+++ b/tf-psa-crypto/include/psa/crypto_struct.h
@@ -508,14 +508,18 @@
      * 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 dab2ee7..707e5b0 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 @@
 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 eaafd90..99e8880 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 @@
         *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 @@
 }
 /* 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,