Add internal implementation

Signed-off-by: Paul Elliott <paul.elliott@arm.com>
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index a21f6d9..b31d51b 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -81,6 +81,7 @@
 #include "mbedtls/sha1.h"
 #include "mbedtls/sha256.h"
 #include "mbedtls/sha512.h"
+#include "hash_info.h"
 
 #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(*(array)))
 
@@ -310,6 +311,9 @@
         case MBEDTLS_ERR_ECP_RANDOM_FAILED:
             return PSA_ERROR_INSUFFICIENT_ENTROPY;
 
+        case MBEDTLS_ERR_ECP_IN_PROGRESS:
+            return PSA_OPERATION_INCOMPLETE;
+
         case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:
             return PSA_ERROR_CORRUPTION_DETECTED;
 
@@ -3360,7 +3364,424 @@
     return PSA_SUCCESS;
 }
 
+/****************************************************************/
+/* Asymmetric interruptible cryptography internal               */
+/* implementations                                              */
+/****************************************************************/
 
+static uint32_t mbedtls_psa_interruptible_max_ops =
+    PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED;
+
+void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops)
+{
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    /* Internal implementation uses zero to indicate infinite number max ops,
+     * therefore avoid this value, and set to minimum possible. */
+    if (max_ops == 0) {
+        max_ops = 1;
+    }
+
+    mbedtls_psa_interruptible_max_ops = max_ops;
+    mbedtls_ecp_set_max_ops(max_ops);
+#else
+    (void) max_ops;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+uint32_t mbedtls_psa_interruptible_get_max_ops(void)
+{
+    return mbedtls_psa_interruptible_max_ops;
+}
+
+uint32_t mbedtls_psa_sign_hash_get_num_ops(
+    const mbedtls_psa_sign_hash_interruptible_operation_t *operation)
+{
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    return operation->restart_ctx.ecp.ops_done;
+#else
+    (void) operation;
+    return 0;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+uint32_t mbedtls_psa_verify_hash_get_num_ops(
+    const mbedtls_psa_verify_hash_interruptible_operation_t *operation)
+{
+    #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    return operation->restart_ctx.ecp.ops_done;
+#else
+    (void) operation;
+    return 0;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_sign_hash_start(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
+    size_t key_buffer_size, psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (PSA_KEY_TYPE_IS_ECC(attributes->core.type)) {
+        if (PSA_ALG_IS_ECDSA(alg)) {
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+            defined(MBEDTLS_ECP_RESTARTABLE)
+
+#if !defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
+            if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
+                return PSA_ERROR_NOT_SUPPORTED;
+            }
+#endif
+
+            /* Ensure default is set even if
+             * mbedtls_psa_interruptible_get_max_ops() has not been called. */
+            mbedtls_ecp_set_max_ops(mbedtls_psa_interruptible_get_max_ops());
+
+            status = mbedtls_psa_ecp_load_representation(attributes->core.type,
+                                                         attributes->core.bits,
+                                                         key_buffer,
+                                                         key_buffer_size,
+                                                         &operation->ctx);
+
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+
+            mbedtls_ecdsa_restart_init(&operation->restart_ctx);
+
+            mbedtls_mpi_init(&operation->r);
+            mbedtls_mpi_init(&operation->s);
+
+            operation->curve_bytes = PSA_BITS_TO_BYTES(
+                operation->ctx->grp.pbits);
+
+            psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
+            operation->md_alg = mbedtls_hash_info_md_from_psa(hash_alg);
+            operation->alg = alg;
+
+            operation->hash = hash;
+            operation->hash_length = hash_length;
+
+#else
+            (void) operation;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) alg;
+            (void) hash;
+            (void) hash_length;
+
+            return PSA_ERROR_NOT_SUPPORTED;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+        } else {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else {
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_sign_hash_complete(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature, size_t signature_size,
+    size_t *signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    if (signature_size < 2 * operation->curve_bytes) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+
+    if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
+        status = mbedtls_to_psa_error(
+            mbedtls_ecdsa_sign_det_restartable(&operation->ctx->grp,
+                                               &operation->r,
+                                               &operation->s,
+                                               &operation->ctx->d,
+                                               operation->hash,
+                                               operation->hash_length,
+                                               operation->md_alg,
+                                               mbedtls_psa_get_random,
+                                               MBEDTLS_PSA_RANDOM_STATE,
+                                               &operation->restart_ctx));
+#else /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+        return PSA_ERROR_NOT_SUPPORTED;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+    } else {
+
+        status = mbedtls_to_psa_error(
+            mbedtls_ecdsa_sign_restartable(&operation->ctx->grp,
+                                           &operation->r,
+                                           &operation->s,
+                                           &operation->ctx->d,
+                                           operation->hash,
+                                           operation->hash_length,
+                                           mbedtls_psa_get_random,
+                                           MBEDTLS_PSA_RANDOM_STATE,
+                                           mbedtls_psa_get_random,
+                                           MBEDTLS_PSA_RANDOM_STATE,
+                                           &operation->restart_ctx));
+    }
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    } else {
+        status =  mbedtls_to_psa_error(
+            mbedtls_mpi_write_binary(&operation->r,
+                                     signature,
+                                     operation->curve_bytes));
+
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        status =  mbedtls_to_psa_error(
+            mbedtls_mpi_write_binary(&operation->s,
+                                     signature +
+                                     operation->curve_bytes,
+                                     operation->curve_bytes));
+
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        *signature_length = operation->curve_bytes * 2;
+
+        return PSA_SUCCESS;
+    }
+ #else
+
+    (void) operation;
+    (void) status;
+    (void) signature;
+    (void) signature_size;
+    (void) signature_length;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_sign_hash_abort(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation)
+{
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    if (operation->ctx) {
+        mbedtls_ecdsa_free(operation->ctx);
+        mbedtls_free(operation->ctx);
+    }
+
+    mbedtls_ecdsa_restart_free(&operation->restart_ctx);
+
+    mbedtls_mpi_free(&operation->r);
+    mbedtls_mpi_free(&operation->s);
+
+    return PSA_SUCCESS;
+
+#else
+
+    (void) operation;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_verify_hash_start(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (PSA_KEY_TYPE_IS_ECC(attributes->core.type)) {
+        if (PSA_ALG_IS_ECDSA(alg)) {
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+            defined(MBEDTLS_ECP_RESTARTABLE)
+
+            /* Ensure default is set even if
+             * mbedtls_psa_interruptible_get_max_ops() has not been called. */
+            mbedtls_ecp_set_max_ops(mbedtls_psa_interruptible_get_max_ops());
+
+            status = mbedtls_psa_ecp_load_representation(attributes->core.type,
+                                                         attributes->core.bits,
+                                                         key_buffer,
+                                                         key_buffer_size,
+                                                         &operation->ctx);
+
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+
+            operation->curve_bytes = PSA_BITS_TO_BYTES(
+                operation->ctx->grp.pbits);
+
+
+            if (signature_length != 2 * operation->curve_bytes) {
+                return PSA_ERROR_INVALID_SIGNATURE;
+            }
+
+            mbedtls_mpi_init(&operation->r);
+            status = mbedtls_to_psa_error(
+                mbedtls_mpi_read_binary(&operation->r,
+                                        signature,
+                                        operation->curve_bytes));
+
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+
+            mbedtls_mpi_init(&operation->s);
+            status = mbedtls_to_psa_error(
+                mbedtls_mpi_read_binary(&operation->s,
+                                        signature +
+                                        operation->curve_bytes,
+                                        operation->curve_bytes));
+
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+
+            /* Check whether the public part is loaded. If not, load it. */
+            if (mbedtls_ecp_is_zero(&operation->ctx->Q)) {
+                int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+                ret = mbedtls_ecp_mul(&operation->ctx->grp,
+                                      &operation->ctx->Q,
+                                      &operation->ctx->d,
+                                      &operation->ctx->grp.G,
+                                      mbedtls_psa_get_random,
+                                      MBEDTLS_PSA_RANDOM_STATE);
+
+                if (ret != 0) {
+                    return mbedtls_to_psa_error(ret);
+                }
+            }
+
+            mbedtls_ecdsa_restart_init(&operation->restart_ctx);
+
+            operation->hash = hash;
+            operation->hash_length = hash_length;
+#else
+            (void) operation;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) alg;
+            (void) hash;
+            (void) hash_length;
+            (void) signature;
+            (void) signature_length;
+
+            return PSA_ERROR_NOT_SUPPORTED;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+        } else {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else {
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_verify_hash_complete(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation)
+{
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    return mbedtls_to_psa_error(
+        mbedtls_ecdsa_verify_restartable(&operation->ctx->grp,
+                                         operation->hash,
+                                         operation->hash_length,
+                                         &operation->ctx->Q,
+                                         &operation->r,
+                                         &operation->s,
+                                         &operation->restart_ctx));
+
+#else
+    (void) operation;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_verify_hash_abort(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation)
+{
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    if (operation->ctx) {
+        mbedtls_ecdsa_free(operation->ctx);
+        mbedtls_free(operation->ctx);
+    }
+
+    mbedtls_ecdsa_restart_free(&operation->restart_ctx);
+
+    mbedtls_mpi_free(&operation->r);
+    mbedtls_mpi_free(&operation->s);
+
+    return PSA_SUCCESS;
+
+#else
+    (void) operation;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
 
 /****************************************************************/
 /* Symmetric cryptography */
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 38e4bc5..2f3cb64 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -606,4 +606,303 @@
     size_t shared_secret_size,
     size_t *shared_secret_length);
 
+/**
+ * \brief Set the maximum number of ops allowed to be executed by an
+ *        interruptible function in a single call.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       interruptible_set_max_ops entry point. This function behaves as an
+ *       interruptible_set_max_ops entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in]  max_ops          The maximum number of ops to be executed in a
+ *                              single call, this can be a number from 0 to
+ *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0
+ *                              is obviously the least amount of work done per
+ *                              call.
+ */
+void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops);
+
+/**
+ * \brief Get the maximum number of ops allowed to be executed by an
+ *        interruptible function in a single call.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       interruptible_get_max_ops entry point. This function behaves as an
+ *       interruptible_get_max_ops entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \return                      Maximum number of ops allowed to be executed
+ *                              by an interruptible function in a single call.
+ */
+uint32_t mbedtls_psa_interruptible_get_max_ops(void);
+
+/**
+ * \brief Get the number of ops that a hash signing operation has taken so
+ *        far. If the operation has completed, then this will represent the
+ *        number of ops required for the entire operation. After initialization
+ *        or calling psa_sign_hash_interruptible_abort() on the operation, a
+ *        value of 0 will be returned.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_get_num_ops entry point. This function behaves as a
+ *       sign_get_num_ops entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \return                      Number of ops that the operation has taken so
+ *                              far.
+ */
+uint32_t mbedtls_psa_sign_hash_get_num_ops(
+    const mbedtls_psa_sign_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief Get the number of ops that a hash verification operation has taken
+ *        so far. If the operation has completed, then this will represent the
+ *        number of ops required for the entire operation. After initialization
+ *        or calling psa_verify_hash_interruptible_abort() on the operation, a
+ *        value of 0 will be returned.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_get_num_ops entry point. This function behaves as a
+ *       verify_get_num_ops entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_verify_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \return                      Number of ops that the operation has taken so
+ *                              far.
+ */
+uint32_t mbedtls_psa_verify_hash_get_num_ops(
+    const mbedtls_psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief  Start signing a hash or short message with a private key, in an
+ *         interruptible manner.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash_start entry point. This function behaves as a
+ *       sign_hash_start entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              the type of the key.
+ * \param[in] hash              The hash or message to sign.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation started successfully - call \c psa_sign_hash_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_sign_hash_start(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
+    size_t key_buffer_size, psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length);
+
+/**
+ * \brief Continue and eventually complete the action of signing a hash or
+ *        short message with a private key, in an interruptible manner.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash_complete entry point. This function behaves as a
+ *       sign_hash_complete entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param signature_size        Size of the \p signature buffer in bytes. This
+ *                              must be appropriate for the selected
+ *                              algorithm and key.
+ * \param[out] signature_length On success, the number of bytes that make up
+ *                              the returned signature value.
+ *
+ * \retval #PSA_SUCCESS
+ *         Operation completed successfully
+ *
+ * \retval #PSA_OPERATION_INCOMPLETE
+ *         Operation was interrupted due to the setting of \c
+ *         psa_interruptible_set_max_ops(), there is still work to be done,
+ *         please call this function again with the same operation object.
+ *
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+psa_status_t mbedtls_psa_sign_hash_complete(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature, size_t signature_size,
+    size_t *signature_length);
+
+/**
+ * \brief Abort a sign hash operation.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver sign_hash_abort
+ *       entry point. This function behaves as a sign_hash_abort entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to abort.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation was aborted successfully.
+ */
+psa_status_t mbedtls_psa_sign_hash_abort(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief  Start reading and verifying a hash or short message, in an
+ *         interruptible manner.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_hash_start entry point. This function behaves as a
+ *       verify_hash_start entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_verify_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              the type of the key.
+ * \param[in] hash              The hash whose signature is to be verified.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ * \param[in] signature         Buffer containing the signature to verify.
+ * \param signature_length      Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation started successfully - call \c psa_sign_hash_complete()
+ *         with the same context to complete the operation
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         An unsupported 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_verify_hash_start(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length);
+
+/**
+ * \brief Continue and eventually complete the action of signing a hash or
+ *        short message with a private key, in an interruptible manner.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash_complete entry point. This function behaves as a
+ *       sign_hash_complete entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \retval #PSA_SUCCESS
+ *         Operation completed successfully, and the passed signature is valid.
+ *
+ * \retval #PSA_OPERATION_INCOMPLETE
+ *         Operation was interrupted due to the setting of \c
+ *         psa_interruptible_set_max_ops(), there is still work to be done,
+ *         please call this function again with the same operation object.
+ *
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed
+ *         signature is not a valid signature.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+psa_status_t mbedtls_psa_verify_hash_complete(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief Abort a verify signed hash operation.
+ *
+ * \warning This is a beta API, and thus subject to change at any point. It is
+ *          not bound by the usual interface stability promises.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_hash_abort entry point. This function behaves as a
+ *       verify_hash_abort entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_verify_hash_interruptible_operation_t
+ *                              to abort.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation was aborted successfully.
+ */
+psa_status_t mbedtls_psa_verify_hash_abort(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation);
+
 #endif /* PSA_CRYPTO_CORE_H */