Merge pull request #7076 from mprse/parse_RFC822_name

Add parsing of x509 RFC822 name + test
diff --git a/ChangeLog.d/add_interruptible_sign_hash b/ChangeLog.d/add_interruptible_sign_hash
new file mode 100644
index 0000000..3d93303
--- /dev/null
+++ b/ChangeLog.d/add_interruptible_sign_hash
@@ -0,0 +1,5 @@
+Features
+   * Add an interruptible version of sign and verify hash to the PSA interface,
+     backed by internal library support for ECDSA signing and verification.
+
+
diff --git a/ChangeLog.d/empty-retval-description.txt b/ChangeLog.d/empty-retval-description.txt
new file mode 100644
index 0000000..491adf5
--- /dev/null
+++ b/ChangeLog.d/empty-retval-description.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Silence warnings from clang -Wdocumentation about empty \retval
+     descriptions, which started appearing with Clang 15. Fixes #6960.
diff --git a/ChangeLog.d/fix-oid-to-string-bugs.txt b/ChangeLog.d/fix-oid-to-string-bugs.txt
new file mode 100644
index 0000000..799f444
--- /dev/null
+++ b/ChangeLog.d/fix-oid-to-string-bugs.txt
@@ -0,0 +1,6 @@
+Bugfix
+   * Fix bug in conversion from OID to string in
+     mbedtls_oid_get_numeric_string(). OIDs such as 2.40.0.25 are now printed
+     correctly.
+   * Reject OIDs with overlong-encoded subidentifiers when converting
+     OID-to-string.
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index 0c744da..c33c7e3 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -27,3 +27,18 @@
 DOT_GRAPH_MAX_NODES    = 200
 MAX_DOT_GRAPH_DEPTH    = 1000
 DOT_TRANSPARENT        = YES
+
+# We mostly use \retval declarations to document which error codes a function
+# can return. The reader can follow the hyperlink to the definition of the
+# constant to get the generic documentation of that error code. If we don't
+# have anything to say about the specific error code for the specific
+# function, we can leave the description part of the \retval command blank.
+# This is perfectly valid as far as Doxygen is concerned. However, with
+# Clang >=15, the -Wdocumentation option emits a warning for empty
+# descriptions.
+#   https://github.com/Mbed-TLS/mbedtls/issues/6960
+#   https://github.com/llvm/llvm-project/issues/60315
+# As a workaround, you can write something like
+#     \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+# This avoids writing redundant text and keeps Clang happy.
+ALIASES += emptydescription=""
diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h
index 9847a68..c5d9701 100644
--- a/include/mbedtls/ecdsa.h
+++ b/include/mbedtls/ecdsa.h
@@ -222,6 +222,134 @@
                                void *p_rng_blind);
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
+#if !defined(MBEDTLS_ECDSA_SIGN_ALT)
+/**
+ * \brief               This function computes the ECDSA signature of a
+ *                      previously-hashed message, in a restartable way.
+ *
+ * \note                The deterministic version implemented in
+ *                      mbedtls_ecdsa_sign_det_restartable() is usually
+ *                      preferred.
+ *
+ * \note                This function is like \c mbedtls_ecdsa_sign() but
+ *                      it can return early and restart according to the
+ *                      limit set with \c mbedtls_ecp_set_max_ops() to
+ *                      reduce blocking.
+ *
+ * \note                If the bitlength of the message hash is larger
+ *                      than the bitlength of the group order, then the
+ *                      hash is truncated as defined in <em>Standards for
+ *                      Efficient Cryptography Group (SECG): SEC1 Elliptic
+ *                      Curve Cryptography</em>, section 4.1.3, step 5.
+ *
+ * \see                 ecp.h
+ *
+ * \param grp           The context for the elliptic curve to use.
+ *                      This must be initialized and have group parameters
+ *                      set, for example through mbedtls_ecp_group_load().
+ * \param r             The MPI context in which to store the first part
+ *                      the signature. This must be initialized.
+ * \param s             The MPI context in which to store the second part
+ *                      the signature. This must be initialized.
+ * \param d             The private signing key. This must be initialized
+ *                      and setup, for example through
+ *                      mbedtls_ecp_gen_privkey().
+ * \param buf           The hashed content to be signed. This must be a readable
+ *                      buffer of length \p blen Bytes. It may be \c NULL if
+ *                      \p blen is zero.
+ * \param blen          The length of \p buf in Bytes.
+ * \param f_rng         The RNG function. This must not be \c NULL.
+ * \param p_rng         The RNG context to be passed to \p f_rng. This may be
+ *                      \c NULL if \p f_rng doesn't need a context parameter.
+ * \param f_rng_blind   The RNG function used for blinding. This must not be
+ *                      \c NULL.
+ * \param p_rng_blind   The RNG context to be passed to \p f_rng. This may be
+ *                      \c NULL if \p f_rng doesn't need a context parameter.
+ * \param rs_ctx        The restart context to use. This may be \c NULL
+ *                      to disable restarting. If it is not \c NULL, it
+ *                      must point to an initialized restart context.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                      operations was reached: see \c
+ *                      mbedtls_ecp_set_max_ops().
+ * \return              Another \c MBEDTLS_ERR_ECP_XXX, \c
+ *                      MBEDTLS_ERR_MPI_XXX or \c MBEDTLS_ERR_ASN1_XXX
+ *                      error code on failure.
+ */
+int mbedtls_ecdsa_sign_restartable(
+    mbedtls_ecp_group *grp,
+    mbedtls_mpi *r, mbedtls_mpi *s,
+    const mbedtls_mpi *d,
+    const unsigned char *buf, size_t blen,
+    int (*f_rng)(void *, unsigned char *, size_t),
+    void *p_rng,
+    int (*f_rng_blind)(void *, unsigned char *, size_t),
+    void *p_rng_blind,
+    mbedtls_ecdsa_restart_ctx *rs_ctx);
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+
+/**
+ * \brief               This function computes the ECDSA signature of a
+ *                      previously-hashed message, in a restartable way.
+ *
+ * \note                This function is like \c
+ *                      mbedtls_ecdsa_sign_det_ext() but it can return
+ *                      early and restart according to the limit set with
+ *                      \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \note                If the bitlength of the message hash is larger
+ *                      than the bitlength of the group order, then the
+ *                      hash is truncated as defined in <em>Standards for
+ *                      Efficient Cryptography Group (SECG): SEC1 Elliptic
+ *                      Curve Cryptography</em>, section 4.1.3, step 5.
+ *
+ * \see                 ecp.h
+ *
+ * \param grp           The context for the elliptic curve to use.
+ *                      This must be initialized and have group parameters
+ *                      set, for example through mbedtls_ecp_group_load().
+ * \param r             The MPI context in which to store the first part
+ *                      the signature. This must be initialized.
+ * \param s             The MPI context in which to store the second part
+ *                      the signature. This must be initialized.
+ * \param d             The private signing key. This must be initialized
+ *                      and setup, for example through
+ *                      mbedtls_ecp_gen_privkey().
+ * \param buf           The hashed content to be signed. This must be a readable
+ *                      buffer of length \p blen Bytes. It may be \c NULL if
+ *                      \p blen is zero.
+ * \param blen          The length of \p buf in Bytes.
+ * \param f_rng_blind   The RNG function used for blinding. This must not be
+ *                      \c NULL.
+ * \param p_rng_blind   The RNG context to be passed to \p f_rng. This may be
+ *                      \c NULL if \p f_rng doesn't need a context parameter.
+ * \param rs_ctx        The restart context to use. This may be \c NULL
+ *                      to disable restarting. If it is not \c NULL, it
+ *                      must point to an initialized restart context.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                      operations was reached: see \c
+ *                      mbedtls_ecp_set_max_ops().
+ * \return              Another \c MBEDTLS_ERR_ECP_XXX, \c
+ *                      MBEDTLS_ERR_MPI_XXX or \c MBEDTLS_ERR_ASN1_XXX
+ *                      error code on failure.
+ */
+int mbedtls_ecdsa_sign_det_restartable(
+    mbedtls_ecp_group *grp,
+    mbedtls_mpi *r, mbedtls_mpi *s,
+    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+    mbedtls_md_type_t md_alg,
+    int (*f_rng_blind)(void *, unsigned char *, size_t),
+    void *p_rng_blind,
+    mbedtls_ecdsa_restart_ctx *rs_ctx);
+
+#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
+
+#endif /* !MBEDTLS_ECDSA_SIGN_ALT */
+
 /**
  * \brief           This function verifies the ECDSA signature of a
  *                  previously-hashed message.
@@ -257,6 +385,51 @@
                          const mbedtls_ecp_point *Q, const mbedtls_mpi *r,
                          const mbedtls_mpi *s);
 
+#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
+/**
+ * \brief           This function verifies the ECDSA signature of a
+ *                  previously-hashed message, in a restartable manner
+ *
+ * \note            If the bitlength of the message hash is larger than the
+ *                  bitlength of the group order, then the hash is truncated as
+ *                  defined in <em>Standards for Efficient Cryptography Group
+ *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ *                  4.1.4, step 3.
+ *
+ * \see             ecp.h
+ *
+ * \param grp       The ECP group to use.
+ *                  This must be initialized and have group parameters
+ *                  set, for example through mbedtls_ecp_group_load().
+ * \param buf       The hashed content that was signed. This must be a readable
+ *                  buffer of length \p blen Bytes. It may be \c NULL if
+ *                  \p blen is zero.
+ * \param blen      The length of \p buf in Bytes.
+ * \param Q         The public key to use for verification. This must be
+ *                  initialized and setup.
+ * \param r         The first integer of the signature.
+ *                  This must be initialized.
+ * \param s         The second integer of the signature.
+ *                  This must be initialized.
+ * \param rs_ctx    The restart context to use. This may be \c NULL to disable
+ *                  restarting. If it is not \c NULL, it must point to an
+ *                  initialized restart context.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return          An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
+ *                  error code on failure.
+ */
+int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,
+                                     const unsigned char *buf, size_t blen,
+                                     const mbedtls_ecp_point *Q,
+                                     const mbedtls_mpi *r,
+                                     const mbedtls_mpi *s,
+                                     mbedtls_ecdsa_restart_ctx *rs_ctx);
+
+#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
+
 /**
  * \brief           This function computes the ECDSA signature and writes it
  *                  to a buffer, serialized as defined in <em>RFC-4492:
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index 7a28a19..b6144d9 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -141,6 +141,15 @@
     MBEDTLS_ECP_TYPE_MONTGOMERY,           /* y^2 = x^3 + a x^2 + x    */
 } mbedtls_ecp_curve_type;
 
+/*
+ * Curve modulus types
+ */
+typedef enum {
+    MBEDTLS_ECP_MOD_NONE = 0,
+    MBEDTLS_ECP_MOD_COORDINATE,
+    MBEDTLS_ECP_MOD_SCALAR
+} mbedtls_ecp_modulus_type;
+
 /**
  * Curve information, for use by other modules.
  *
@@ -472,6 +481,12 @@
  *                  only enabled for specific sides and key exchanges
  *                  (currently only for clients and ECDHE-ECDSA).
  *
+ * \warning         Using the PSA interruptible interfaces with keys in local
+ *                  storage and no accelerator driver will also call this
+ *                  function to set the values specified via those interfaces,
+ *                  overwriting values previously set. Care should be taken if
+ *                  mixing these two interfaces.
+ *
  * \param max_ops   Maximum number of basic operations done in a row.
  *                  Default: 0 (unlimited).
  *                  Lower (non-zero) values mean ECC functions will block for
diff --git a/include/mbedtls/pkcs7.h b/include/mbedtls/pkcs7.h
index 5ddd5a3..126eac4 100644
--- a/include/mbedtls/pkcs7.h
+++ b/include/mbedtls/pkcs7.h
@@ -136,21 +136,11 @@
 mbedtls_pkcs7_signer_info;
 
 /**
- * Structure holding attached data as part of PKCS7 signed data format
- */
-typedef struct mbedtls_pkcs7_data {
-    mbedtls_pkcs7_buf MBEDTLS_PRIVATE(oid);
-    mbedtls_pkcs7_buf MBEDTLS_PRIVATE(data);
-}
-mbedtls_pkcs7_data;
-
-/**
  * Structure holding the signed data section
  */
 typedef struct mbedtls_pkcs7_signed_data {
     int MBEDTLS_PRIVATE(version);
     mbedtls_pkcs7_buf MBEDTLS_PRIVATE(digest_alg_identifiers);
-    struct mbedtls_pkcs7_data MBEDTLS_PRIVATE(content);
     int MBEDTLS_PRIVATE(no_of_certs);
     mbedtls_x509_crt MBEDTLS_PRIVATE(certs);
     int MBEDTLS_PRIVATE(no_of_crls);
@@ -165,7 +155,6 @@
  */
 typedef struct mbedtls_pkcs7 {
     mbedtls_pkcs7_buf MBEDTLS_PRIVATE(raw);
-    mbedtls_pkcs7_buf MBEDTLS_PRIVATE(content_type_oid);
     mbedtls_pkcs7_signed_data MBEDTLS_PRIVATE(signed_data);
 }
 mbedtls_pkcs7;
@@ -178,7 +167,7 @@
 void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7);
 
 /**
- * \brief          Parse a single DER formatted pkcs7 content.
+ * \brief          Parse a single DER formatted pkcs7 detached signature.
  *
  * \param pkcs7    The pkcs7 structure to be filled by parser for the output.
  * \param buf      The buffer holding only the DER encoded pkcs7.
@@ -188,6 +177,7 @@
  * \note           This function makes an internal copy of the PKCS7 buffer
  *                 \p buf. In particular, \p buf may be destroyed or reused
  *                 after this call returns.
+ * \note           Signatures with internal data are not supported.
  *
  * \return         The \c mbedtls_pkcs7_type of \p buf, if successful.
  * \return         A negative error code on failure.
@@ -207,7 +197,8 @@
  *                 matches.
  *
  *                 This function does not use the certificates held within the
- *                 PKCS7 structure itself.
+ *                 PKCS7 structure itself, and does not check that the
+ *                 certificate is signed by a trusted certification authority.
  *
  * \param pkcs7    PKCS7 structure containing signature.
  * \param cert     Certificate containing key to verify signature.
@@ -228,15 +219,15 @@
  * \brief          Verification of PKCS7 signature against a caller-supplied
  *                 certificate.
  *
- *                 For each signer in the PKCS structure, this function computes
- *                 a signature over the supplied hash, using the supplied
- *                 certificate and the same digest algorithm as specified by the
- *                 signer. It then compares this signature against the
- *                 signer's signature; verification succeeds if any comparison
- *                 matches.
+ *                 For each signer in the PKCS structure, this function
+ *                 validates a signature over the supplied hash, using the
+ *                 supplied certificate and the same digest algorithm as
+ *                 specified by the signer. Verification succeeds if any
+ *                 signature is good.
  *
  *                 This function does not use the certificates held within the
- *                 PKCS7 structure itself.
+ *                 PKCS7 structure itself, and does not check that the
+ *                 certificate is signed by a trusted certification authority.
  *
  * \param pkcs7    PKCS7 structure containing signature.
  * \param cert     Certificate containing key to verify signature.
@@ -244,7 +235,7 @@
  * \param hashlen  Length of the hash.
  *
  * \note           This function is different from mbedtls_pkcs7_signed_data_verify()
- *                 in a way that it directly receives the hash of the data.
+ *                 in that it is directly passed the hash of the data.
  *
  * \return         0 if the signature verifies, or a negative error code on failure.
  */
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 2b9b2a2..5394eee 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -88,16 +88,16 @@
  * initialization may have security implications, for example due to improper
  * seeding of the random number generator.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
  */
 psa_status_t psa_crypto_init(void);
 
@@ -368,14 +368,14 @@
  *                              On failure, equivalent to a
  *                              freshly-initialized structure.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -486,7 +486,7 @@
  *                          identifier defined in \p attributes.
  *                          \c 0 on failure.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_INVALID_HANDLE
  *         \p source_key is invalid.
  * \retval #PSA_ERROR_ALREADY_EXISTS
@@ -502,14 +502,14 @@
  *         The source key does not have the #PSA_KEY_USAGE_COPY usage flag, or
  *         the source key is not exportable and its lifetime does not
  *         allow copying it to the target's lifetime.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -631,14 +631,14 @@
  *         the key data is not correctly formatted, or
  *         the size in \p attributes is nonzero and does not match the size
  *         of the key data.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -718,22 +718,22 @@
  * \param[out] data_length  On success, the number of bytes
  *                          that make up the key data.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The key does not have the #PSA_KEY_USAGE_EXPORT flag.
- * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p data buffer is too small. You can determine a
  *         sufficient buffer size by calling
  *         #PSA_EXPORT_KEY_OUTPUT_SIZE(\c type, \c bits)
  *         where \c type is the key type
  *         and \c bits is the key size in bits.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -793,22 +793,22 @@
  * \param[out] data_length  On success, the number of bytes
  *                          that make up the key data.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The key is neither a public key nor a key pair.
- * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p data buffer is too small. You can determine a
  *         sufficient buffer size by calling
  *         #PSA_EXPORT_KEY_OUTPUT_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits)
  *         where \c type is the key type
  *         and \c bits is the key size in bits.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -846,13 +846,13 @@
  *         Success.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a hash algorithm.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         \p hash_size is too small
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -884,10 +884,10 @@
  *         \p alg is not supported or is not a hash algorithm.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p input_length or \p hash_length do not match the hash size for \p alg
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -977,10 +977,10 @@
  *         \p alg is not a supported hash algorithm.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p alg is not a hash algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1003,10 +1003,10 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1049,10 +1049,10 @@
  *         The size of the \p hash buffer is too small. You can determine a
  *         sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg)
  *         where \c alg is the hash algorithm that is calculated.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1090,10 +1090,10 @@
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The hash of the message was calculated successfully, but it
  *         differs from the expected hash.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1120,10 +1120,10 @@
  *
  * \param[in,out] operation     Initialized hash operation.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -1146,11 +1146,11 @@
  * \param[in,out] target_operation  The operation object to set up.
  *                                  It must be initialized but not active.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The \p source_operation state is not valid (it must be active), or
  *         the \p target_operation state is not valid (it must be inactive), or
@@ -1190,18 +1190,18 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a MAC algorithm.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         \p mac_size is too small
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_STORAGE_FAILURE
  *         The key could not be retrieved from storage.
  * \retval #PSA_ERROR_BAD_STATE
@@ -1233,16 +1233,16 @@
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The MAC of the message was calculated successfully, but it
  *         differs from the expected value.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a MAC algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_STORAGE_FAILURE
  *         The key could not be retrieved from storage.
  * \retval #PSA_ERROR_BAD_STATE
@@ -1338,16 +1338,16 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a MAC algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_STORAGE_FAILURE
  *         The key could not be retrieved from storage.
  * \retval #PSA_ERROR_BAD_STATE
@@ -1400,16 +1400,16 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \c key is not compatible with \c alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \c alg is not supported or is not a MAC algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_STORAGE_FAILURE
  *         The key could not be retrieved from storage.
  * \retval #PSA_ERROR_BAD_STATE
@@ -1437,11 +1437,11 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1485,11 +1485,11 @@
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p mac buffer is too small. You can determine a
  *         sufficient buffer size by calling PSA_MAC_LENGTH().
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be an active mac sign
  *         operation), or the library has not been previously initialized
@@ -1528,11 +1528,11 @@
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The MAC of the message was calculated successfully, but it
  *         differs from the expected MAC.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be an active mac verify
  *         operation), or the library has not been previously initialized
@@ -1560,10 +1560,10 @@
  *
  * \param[in,out] operation Initialized MAC operation.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -1599,18 +1599,18 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a cipher algorithm.
- * \retval #PSA_ERROR_BUFFER_TOO_SMALL
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -1646,18 +1646,18 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a cipher algorithm.
- * \retval #PSA_ERROR_BUFFER_TOO_SMALL
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -1753,17 +1753,17 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a cipher algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1816,17 +1816,17 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a cipher algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1859,11 +1859,11 @@
  *         Success.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p iv buffer is too small.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active, with no IV set),
  *         or the library has not been previously initialized
@@ -1900,11 +1900,11 @@
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The size of \p iv is not acceptable for the chosen algorithm,
  *         or the chosen algorithm does not use an IV.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be an active cipher
  *         encrypt operation, with no IV set), or the library has not been
@@ -1941,11 +1941,11 @@
  *         Success.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active, with an IV set
  *         if required for the algorithm), or the library has not been
@@ -1993,11 +1993,11 @@
  *         padding, and the ciphertext does not contain valid padding.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active, with an IV set
  *         if required for the algorithm), or the library has not been
@@ -2026,10 +2026,10 @@
  *
  * \param[in,out] operation     Initialized cipher operation.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2082,23 +2082,23 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         \p ciphertext_size is too small.
  *         #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, \p alg,
  *         \p plaintext_length) or
  *         #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length) can be used to
  *         determine the required buffer size.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2153,25 +2153,25 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The ciphertext is not authentic.
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         \p plaintext_size is too small.
  *         #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, \p alg,
  *         \p ciphertext_length) or
  *         #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length) can be used
  *         to determine the required buffer size.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2280,16 +2280,16 @@
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive), or
  *         the library has not been previously initialized by psa_crypto_init().
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_STORAGE_FAILURE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2344,17 +2344,17 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive), or the
  *         library has not been previously initialized by psa_crypto_init().
@@ -2388,11 +2388,11 @@
  *         Success.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p nonce buffer is too small.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be an active aead encrypt
  *         operation, with no nonce set), or the library has not been
@@ -2428,11 +2428,11 @@
  *         Success.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The size of \p nonce is not acceptable for the chosen algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active, with no nonce
  *         set), or the library has not been previously initialized
@@ -2473,10 +2473,10 @@
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         At least one of the lengths is not acceptable for the chosen
  *         algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active, and
  *         psa_aead_update_ad() and psa_aead_update() must not have been
@@ -2520,11 +2520,11 @@
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The total input length overflows the additional data length that
  *         was previously specified with psa_aead_set_lengths().
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active, have a nonce
  *         set, have lengths set if required by the algorithm, and
@@ -2605,11 +2605,11 @@
  *         specified with psa_aead_set_lengths(), or
  *         the total input length overflows the plaintext length that
  *         was previously specified with psa_aead_set_lengths().
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active, have a nonce
  *         set, and have lengths set if required by the algorithm), or the
@@ -2691,11 +2691,11 @@
  *         the total length of input to psa_aead_update() so far is
  *         less than the plaintext length that was previously
  *         specified with psa_aead_set_lengths().
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be an active encryption
  *         operation with a nonce set), or the library has not been previously
@@ -2774,11 +2774,11 @@
  *         the total length of input to psa_aead_update() so far is
  *         less than the plaintext length that was previously
  *         specified with psa_aead_set_lengths().
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be an active decryption
  *         operation with a nonce set), or the library has not been previously
@@ -2809,10 +2809,10 @@
  *
  * \param[in,out] operation     Initialized AEAD operation.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2858,8 +2858,8 @@
  * \param[out] signature_length On success, the number of bytes that make up
  *                              the returned signature value.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,
  *         or it does not permit the requested algorithm.
@@ -2869,16 +2869,16 @@
  *         #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_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2914,23 +2914,23 @@
  * \param[out] signature        Buffer containing the signature to verify.
  * \param[in]  signature_length Size of the \p signature buffer in bytes.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,
  *         or it does not permit the requested algorithm.
  * \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
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2967,23 +2967,23 @@
  * \param[out] signature_length On success, the number of bytes
  *                              that make up the returned signature value.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \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_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -3023,18 +3023,18 @@
  *
  * \retval #PSA_SUCCESS
  *         The signature is valid.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \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
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -3076,23 +3076,23 @@
  * \param[out] output_length    On success, the number of bytes
  *                              that make up the returned output.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small. You can
  *         determine a sufficient buffer size by calling
  *         #PSA_ASYMMETRIC_ENCRYPT_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_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -3136,24 +3136,24 @@
  * \param[out] output_length    On success, the number of bytes
  *                              that make up the returned output.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small. You can
  *         determine a sufficient buffer size by calling
  *         #PSA_ASYMMETRIC_DECRYPT_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_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
- * \retval #PSA_ERROR_INVALID_PADDING
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_INVALID_PADDING \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -3263,11 +3263,11 @@
  *         \c alg is not a key derivation algorithm.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \c alg is not supported or is not a key derivation algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -3287,10 +3287,10 @@
  * \param[in] operation     The operation to query.
  * \param[out] capacity     On success, the capacity of the operation.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -3311,14 +3311,14 @@
  *                          It must be less or equal to the operation's
  *                          current capacity.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p capacity is larger than the operation's current capacity.
  *         In this case, the operation object remains valid and its capacity
  *         remains unchanged.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active), or the
  *         library has not been previously initialized by psa_crypto_init().
@@ -3367,11 +3367,11 @@
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \c step is not compatible with the operation's algorithm, or
  *         \c step does not allow direct inputs.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid for this input \p step, or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -3410,11 +3410,11 @@
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \c step is not compatible with the operation's algorithm, or
  *         \c step does not allow numeric inputs.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid for this input \p step, or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -3468,7 +3468,7 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The key allows neither #PSA_KEY_USAGE_DERIVE nor
  *         #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this
@@ -3477,11 +3477,11 @@
  *         \c step is not compatible with the operation's algorithm, or
  *         \c step does not allow key inputs of the given type
  *         or does not allow key inputs at all.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid for this input \p step, or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -3536,8 +3536,8 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \c private_key is not compatible with \c alg,
  *         or \p peer_key is not valid for \c alg or not compatible with
@@ -3545,11 +3545,11 @@
  *         from a key agreement.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \c alg is not supported or is not a key derivation algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid for this key agreement \p step,
  *         or the library has not been previously initialized by psa_crypto_init().
@@ -3580,7 +3580,7 @@
  * \param[out] output       Buffer where the output will be written.
  * \param output_length     Number of bytes to output.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         One of the inputs was a key whose policy didn't allow
  *         #PSA_KEY_USAGE_DERIVE.
@@ -3591,11 +3591,11 @@
  *                          The operation's capacity is set to 0, thus
  *                          subsequent calls to this function will not
  *                          succeed, even with a smaller output buffer.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active and completed
  *         all required input steps), or the library has not been previously
@@ -3738,14 +3738,14 @@
  *         #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
  *         key; or one of the inputs was a key whose policy didn't allow
  *         #PSA_KEY_USAGE_DERIVE.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active and completed
  *         all required input steps), or the library has not been previously
@@ -3786,7 +3786,7 @@
  * \param output_length     Length of the expected output; this is also the
  *                          number of bytes that will be read.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The output was read successfully, but it differs from the expected
  *         output.
@@ -3799,11 +3799,11 @@
  *                          the operation's capacity is set to 0, thus
  *                          subsequent calls to this function will not
  *                          succeed, even with a smaller expected output.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active and completed
  *         all required input steps), or the library has not been previously
@@ -3845,7 +3845,7 @@
  *                          computed by a previous call to
  *                          psa_key_derivation_output_key().
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The output was read successfully, but if differs from the expected
  *         output.
@@ -3863,11 +3863,11 @@
  *                          the operation's capacity is set to 0, thus
  *                          subsequent calls to this function will not
  *                          succeed, even with a smaller expected output.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active and completed
  *         all required input steps), or the library has not been previously
@@ -3893,10 +3893,10 @@
  *
  * \param[in,out] operation    The operation to abort.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -3934,8 +3934,8 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p alg is not a key agreement algorithm, or
  *         \p private_key is not compatible with \p alg,
@@ -3945,11 +3945,11 @@
  *         \p output_size is too small
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not a supported key agreement algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -3981,13 +3981,13 @@
  * \param[out] output       Output buffer for the generated data.
  * \param output_size       Number of bytes to generate and output.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -4024,17 +4024,17 @@
  * \retval #PSA_ERROR_ALREADY_EXISTS
  *         This is an attempt to create a persistent key, and there is
  *         already a persistent key with the given identifier.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -4045,6 +4045,628 @@
 
 /**@}*/
 
+/** \defgroup interruptible_hash Interruptible sign/verify hash
+ * @{
+ */
+
+/** The type of the state data structure for interruptible hash
+ *  signing operations.
+ *
+ * Before calling any function on a sign hash operation object, the
+ * application must initialize it by any of the following means:
+ * - Set the structure to all-bits-zero, for example:
+ *   \code
+ *   psa_sign_hash_interruptible_operation_t operation;
+ *   memset(&operation, 0, sizeof(operation));
+ *   \endcode
+ * - Initialize the structure to logical zero values, for example:
+ *   \code
+ *   psa_sign_hash_interruptible_operation_t operation = {0};
+ *   \endcode
+ * - Initialize the structure to the initializer
+ *   #PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT, for example:
+ *   \code
+ *   psa_sign_hash_interruptible_operation_t operation =
+ *   PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT;
+ *   \endcode
+ * - Assign the result of the function
+ *   psa_sign_hash_interruptible_operation_init() to the structure, for
+ *   example:
+ *   \code
+ *   psa_sign_hash_interruptible_operation_t operation;
+ *   operation = psa_sign_hash_interruptible_operation_init();
+ *   \endcode
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice. */
+typedef struct psa_sign_hash_interruptible_operation_s psa_sign_hash_interruptible_operation_t;
+
+/** The type of the state data structure for interruptible hash
+ *  verification operations.
+ *
+ * Before calling any function on a sign hash operation object, the
+ * application must initialize it by any of the following means:
+ * - Set the structure to all-bits-zero, for example:
+ *   \code
+ *   psa_verify_hash_interruptible_operation_t operation;
+ *   memset(&operation, 0, sizeof(operation));
+ *   \endcode
+ * - Initialize the structure to logical zero values, for example:
+ *   \code
+ *   psa_verify_hash_interruptible_operation_t operation = {0};
+ *   \endcode
+ * - Initialize the structure to the initializer
+ *   #PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT, for example:
+ *   \code
+ *   psa_verify_hash_interruptible_operation_t operation =
+ *   PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT;
+ *   \endcode
+ * - Assign the result of the function
+ *   psa_verify_hash_interruptible_operation_init() to the structure, for
+ *   example:
+ *   \code
+ *   psa_verify_hash_interruptible_operation_t operation;
+ *   operation = psa_verify_hash_interruptible_operation_init();
+ *   \endcode
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice. */
+typedef struct psa_verify_hash_interruptible_operation_s psa_verify_hash_interruptible_operation_t;
+
+/**
+ * \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 time taken to execute a single op is
+ *                              implementation specific and depends on
+ *                              software, hardware, the algorithm, key type and
+ *                              curve chosen. Even within a single operation,
+ *                              successive ops can take differing amounts of
+ *                              time. The only guarantee is that lower values
+ *                              for \p max_ops means functions will block for a
+ *                              lesser maximum amount of time. The functions
+ *                              \c psa_sign_interruptible_get_num_ops() and
+ *                              \c psa_verify_interruptible_get_num_ops() are
+ *                              provided to help with tuning this value.
+ *
+ * \note                        This value defaults to
+ *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, which
+ *                              means the whole operation will be done in one
+ *                              go, regardless of the number of ops required.
+ *
+ * \note                        If more ops are needed to complete a
+ *                              computation, #PSA_OPERATION_INCOMPLETE will be
+ *                              returned by the function performing the
+ *                              computation. It is then the caller's
+ *                              responsibility to either call again with the
+ *                              same operation context until it returns 0 or an
+ *                              error code; or to call the relevant abort
+ *                              function if the answer is no longer required.
+ *
+ * \note                        The interpretation of \p max_ops is also
+ *                              implementation defined. On a hard real time
+ *                              system, this can indicate a hard deadline, as a
+ *                              real-time system needs a guarantee of not
+ *                              spending more than X time, however care must be
+ *                              taken in such an implementation to avoid the
+ *                              situation whereby calls just return, not being
+ *                              able to do any actual work within the allotted
+ *                              time.  On a non-real-time system, the
+ *                              implementation can be more relaxed, but again
+ *                              whether this number should be interpreted as as
+ *                              hard or soft limit or even whether a less than
+ *                              or equals as regards to ops executed in a
+ *                              single call is implementation defined.
+ *
+ * \note                        For keys in local storage when no accelerator
+ *                              driver applies, please see also the
+ *                              documentation for \c mbedtls_ecp_set_max_ops(),
+ *                              which is the internal implementation in these
+ *                              cases.
+ *
+ * \warning                     With implementations that interpret this number
+ *                              as a hard limit, setting this number too small
+ *                              may result in an infinite loop, whereby each
+ *                              call results in immediate return with no ops
+ *                              done (as there is not enough time to execute
+ *                              any), and thus no result will ever be achieved.
+ *
+ * \note                        This only applies to functions whose
+ *                              documentation mentions they may return
+ *                              #PSA_OPERATION_INCOMPLETE.
+ *
+ * \param 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 the least amount of work done per call.
+ */
+void 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. This will return the last
+ *                              value set by
+ *                              \c psa_interruptible_set_max_ops() or
+ *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED if
+ *                              that function has never been called.
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ * \return                      Maximum number of ops allowed to be
+ *                              executed by an interruptible function in a
+ *                              single call.
+ */
+uint32_t 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
+ *                              \c 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.
+ *
+ *                              This is a helper provided to help you tune the
+ *                              value passed to \c
+ *                              psa_interruptible_set_max_ops().
+ *
+ * \param operation             The \c 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 psa_sign_hash_get_num_ops(
+    const 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 \c
+ *                              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.
+ *
+ *                              This is a helper provided to help you tune the
+ *                              value passed to \c
+ *                              psa_interruptible_set_max_ops().
+ *
+ * \param operation             The \c
+ *                              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 psa_verify_hash_get_num_ops(
+    const psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief                       Start signing a hash or short message with a
+ *                              private key, in an interruptible manner.
+ *
+ * \see                         \c psa_sign_hash_complete()
+ *
+ * \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                        This function combined with \c
+ *                              psa_sign_hash_complete() is equivalent to
+ *                              \c psa_sign_hash() but
+ *                              \c psa_sign_hash_complete() can return early and
+ *                              resume according to the limit set with \c
+ *                              psa_interruptible_set_max_ops() to reduce the
+ *                              maximum time spent in a function call.
+ *
+ * \note                        Users should call \c psa_sign_hash_complete()
+ *                              repeatedly on the same context after a
+ *                              successful call to this function until \c
+ *                              psa_sign_hash_complete() either returns 0 or an
+ *                              error. \c psa_sign_hash_complete() will return
+ *                              #PSA_OPERATION_INCOMPLETE if there is more work
+ *                              to do. Alternatively users can call
+ *                              \c psa_sign_hash_abort() at any point if they no
+ *                              longer want the result.
+ *
+ * \note                        If this function returns an error status, the
+ *                              operation enters an error state and must be
+ *                              aborted by calling \c psa_sign_hash_abort().
+ *
+ * \param[in, out] operation    The \c psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must be an asymmetric key pair. The key must
+ *                              allow the usage #PSA_KEY_USAGE_SIGN_HASH.
+ * \param alg                   A signature algorithm (\c PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ *                              is true), that is compatible with
+ *                              the type of \p 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_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_SIGN_HASH flag, or it does
+ *         not permit the requested algorithm.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         An operation has previously been started on this context, and is
+ *         still in progress.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_sign_hash_start(
+    psa_sign_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key, 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.
+ *
+ * \see                         \c psa_sign_hash_start()
+ *
+ * \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                        This function combined with \c
+ *                              psa_sign_hash_start() is equivalent to
+ *                              \c psa_sign_hash() but this function can return
+ *                              early and resume according to the limit set with
+ *                              \c psa_interruptible_set_max_ops() to reduce the
+ *                              maximum time spent in a function call.
+ *
+ * \note                        Users should call this function on the same
+ *                              operation object repeatedly until it either
+ *                              returns 0 or an error. This function will return
+ *                              #PSA_OPERATION_INCOMPLETE if there is more work
+ *                              to do. Alternatively users can call
+ *                              \c psa_sign_hash_abort() at any point if they no
+ *                              longer want the result.
+ *
+ * \note                        When this function returns successfully, the
+ *                              operation becomes inactive. If this function
+ *                              returns an error status, the operation enters an
+ *                              error state and must be aborted by calling
+ *                              \c psa_sign_hash_abort().
+ *
+ * \param[in, out] operation    The \c psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first, and have
+ *                              had \c psa_sign_hash_start() called with it
+ *                              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:
+ *                              - The required signature size is
+ *                                #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c
+ *                                key_bits, \c alg) where \c key_type and \c
+ *                                key_bits are the type and bit-size
+ *                                respectively of key.
+ *                              - #PSA_SIGNATURE_MAX_SIZE evaluates to the
+ *                                maximum signature size of any supported
+ *                                signature algorithm.
+ * \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.
+ *         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_BAD_STATE
+ *         An operation was not previously started on this context via
+ *         \c psa_sign_hash_start().
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has either not been previously initialized by
+ *         psa_crypto_init()  or you did not previously call
+ *         psa_sign_hash_start() with this operation object. It is
+ *         implementation-dependent whether a failure to initialize results in
+ *         this error code.
+ */
+psa_status_t psa_sign_hash_complete(
+    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                        This function is the only function that clears
+ *                              the number of ops completed as part of the
+ *                              operation. Please ensure you copy this value via
+ *                              \c psa_sign_hash_get_num_ops() if required
+ *                              before calling.
+ *
+ * \note                        Aborting an operation frees all associated
+ *                              resources except for the \p operation structure
+ *                              itself. Once aborted, the operation object can
+ *                              be reused for another operation by calling \c
+ *                              psa_sign_hash_start() again.
+ *
+ * \note                        You may call this function any time after the
+ *                              operation object has been initialized. In
+ *                              particular, calling \c psa_sign_hash_abort()
+ *                              after the operation has already been terminated
+ *                              by a call to \c psa_sign_hash_abort() or
+ *                              psa_sign_hash_complete() is safe.
+ *
+ * \param[in,out] operation     Initialized sign hash operation.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation was aborted successfully.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief                       Start reading and verifying a hash or short
+ *                              message, in an interruptible manner.
+ *
+ * \see                         \c psa_verify_hash_complete()
+ *
+ * \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                        This function combined with \c
+ *                              psa_verify_hash_complete() is equivalent to
+ *                              \c psa_verify_hash() but \c
+ *                              psa_verify_hash_complete() can return early and
+ *                              resume according to the limit set with \c
+ *                              psa_interruptible_set_max_ops() to reduce the
+ *                              maximum time spent in a function.
+ *
+ * \note                        Users should call \c psa_verify_hash_complete()
+ *                              repeatedly on the same operation object after a
+ *                              successful call to this function until \c
+ *                              psa_verify_hash_complete() either returns 0 or
+ *                              an error. \c psa_verify_hash_complete() will
+ *                              return #PSA_OPERATION_INCOMPLETE if there is
+ *                              more work to do. Alternatively users can call
+ *                              \c psa_verify_hash_abort() at any point if they
+ *                              no longer want the result.
+ *
+ * \note                        If this function returns an error status, the
+ *                              operation enters an error state and must be
+ *                              aborted by calling \c psa_verify_hash_abort().
+ *
+ * \param[in, out] operation    The \c psa_verify_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \param key                   Identifier of the key to use for the operation.
+ *                              The key must allow the usage
+ *                              #PSA_KEY_USAGE_VERIFY_HASH.
+ * \param alg                   A signature algorithm (\c PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ *                              is true), that is compatible with
+ *                              the type of \p 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 - please call \c
+ *         psa_verify_hash_complete() with the same context to complete the
+ *         operation.
+ *
+ * \retval #PSA_ERROR_BAD_STATE
+ *         Another operation has already been started on this context, and is
+ *         still in progress.
+ *
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_VERIFY_HASH flag, or it does
+ *         not permit the requested algorithm.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval PSA_ERROR_DATA_CORRUPT
+ * \retval PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_verify_hash_start(
+    psa_verify_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key, 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
+ *                              reading and verifying a hash or short message
+ *                              signed with a private key, in an interruptible
+ *                              manner.
+ *
+ * \see                         \c psa_verify_hash_start()
+ *
+ * \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                        This function combined with \c
+ *                              psa_verify_hash_start() is equivalent to
+ *                              \c psa_verify_hash() but this function can
+ *                              return early and resume according to the limit
+ *                              set with \c psa_interruptible_set_max_ops() to
+ *                              reduce the maximum time spent in a function
+ *                              call.
+ *
+ * \note                        Users should call this function on the same
+ *                              operation object repeatedly until it either
+ *                              returns 0 or an error. This function will return
+ *                              #PSA_OPERATION_INCOMPLETE if there is more work
+ *                              to do. Alternatively users can call
+ *                              \c psa_verify_hash_abort() at any point if they
+ *                              no longer want the result.
+ *
+ * \note                        When this function returns successfully, the
+ *                              operation becomes inactive. If this function
+ *                              returns an error status, the operation enters an
+ *                              error state and must be aborted by calling
+ *                              \c psa_verify_hash_abort().
+ *
+ * \param[in, out] operation    The \c psa_verify_hash_interruptible_operation_t
+ *                              to use. This must be initialized first, and have
+ *                              had \c psa_verify_hash_start() called with it
+ *                              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.
+ *         Call this function again with the same operation object.
+ *
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed
+ *         signature is not a valid signature.
+ *\retval #PSA_ERROR_BAD_STATE
+ *         An operation was not previously started on this context via
+ *         \c psa_verify_hash_start().
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has either not been previously initialized by
+ *         psa_crypto_init() or you did not previously call
+ *         psa_verify_hash_start() on this object. It is
+ *         implementation-dependent whether a failure to initialize results in
+ *         this error code.
+ */
+psa_status_t psa_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief                     Abort a verify 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                      This function is the only function that clears the
+ *                            number of ops completed as part of the operation.
+ *                            Please ensure you copy this value via
+ *                            \c psa_verify_hash_get_num_ops() if required
+ *                            before calling.
+ *
+ * \note                      Aborting an operation frees all associated
+ *                            resources except for the operation structure
+ *                            itself. Once aborted, the operation object can be
+ *                            reused for another operation by calling \c
+ *                            psa_verify_hash_start() again.
+ *
+ * \note                      You may call this function any time after the
+ *                            operation object has been initialized.
+ *                            In particular, calling \c psa_verify_hash_abort()
+ *                            after the operation has already been terminated by
+ *                            a call to \c psa_verify_hash_abort() or
+ *                            psa_verify_hash_complete() is safe.
+ *
+ * \param[in,out] operation   Initialized verify hash operation.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation was aborted successfully.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *operation);
+
+
+/**@}*/
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/psa/crypto_builtin_composites.h b/include/psa/crypto_builtin_composites.h
index b7f0b11..9f23551 100644
--- a/include/psa/crypto_builtin_composites.h
+++ b/include/psa/crypto_builtin_composites.h
@@ -107,4 +107,78 @@
 
 #define MBEDTLS_PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, { 0 } }
 
+#include "mbedtls/ecdsa.h"
+
+/* Context structure for the Mbed TLS interruptible sign hash implementation. */
+typedef struct {
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+    mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx);
+    mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx);
+
+    uint32_t MBEDTLS_PRIVATE(num_ops);
+
+    size_t MBEDTLS_PRIVATE(coordinate_bytes);
+    psa_algorithm_t MBEDTLS_PRIVATE(alg);
+    mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg);
+    uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+    size_t MBEDTLS_PRIVATE(hash_length);
+
+#else
+    /* Make the struct non-empty if algs not supported. */
+    unsigned MBEDTLS_PRIVATE(dummy);
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+} mbedtls_psa_sign_hash_interruptible_operation_t;
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+#define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 }
+#else
+#define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 }
+#endif
+
+/* Context structure for the Mbed TLS interruptible verify hash
+ * implementation.*/
+typedef struct {
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx);
+    mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx);
+
+    uint32_t MBEDTLS_PRIVATE(num_ops);
+
+    uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+    size_t MBEDTLS_PRIVATE(hash_length);
+
+    mbedtls_mpi MBEDTLS_PRIVATE(r);
+    mbedtls_mpi MBEDTLS_PRIVATE(s);
+
+#else
+    /* Make the struct non-empty if algs not supported. */
+    unsigned MBEDTLS_PRIVATE(dummy);
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+
+} mbedtls_psa_verify_hash_interruptible_operation_t;
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+#define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, \
+        { 0 } }
+#else
+#define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 }
+#endif
+
+
+
 #endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */
diff --git a/include/psa/crypto_compat.h b/include/psa/crypto_compat.h
index 97e6584..3544f96 100644
--- a/include/psa/crypto_compat.h
+++ b/include/psa/crypto_compat.h
@@ -105,11 +105,11 @@
  *         permission to access it. Note that this specification does not
  *         define any way to create such a key, but it may be possible
  *         through implementation-specific means.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -149,8 +149,8 @@
  *         \p handle was a valid handle or \c 0. It is now closed.
  * \retval #PSA_ERROR_INVALID_HANDLE
  *         \p handle is not a valid handle nor \c 0.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
diff --git a/include/psa/crypto_driver_contexts_composites.h b/include/psa/crypto_driver_contexts_composites.h
index bcd000e..1b95814 100644
--- a/include/psa/crypto_driver_contexts_composites.h
+++ b/include/psa/crypto_driver_contexts_composites.h
@@ -114,5 +114,15 @@
 #endif
 } psa_driver_aead_context_t;
 
+typedef union {
+    unsigned dummy; /* Make sure this union is always non-empty */
+    mbedtls_psa_sign_hash_interruptible_operation_t mbedtls_ctx;
+} psa_driver_sign_hash_interruptible_context_t;
+
+typedef union {
+    unsigned dummy; /* Make sure this union is always non-empty */
+    mbedtls_psa_verify_hash_interruptible_operation_t mbedtls_ctx;
+} psa_driver_verify_hash_interruptible_context_t;
+
 #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */
 /* End of automatically generated file. */
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index bd1b5af..582d942 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -189,12 +189,12 @@
  *         or the specified slot number is not valid.
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The caller is not authorized to register the specified key slot.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -491,10 +491,10 @@
  *                              according to \p type as described above.
  * \param data_length           Size of the \p data buffer in bytes.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
                                            psa_key_type_t type,
@@ -521,8 +521,8 @@
  * \param[out] data_length      On success, the number of bytes
  *                              that make up the key domain parameters data.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription
  */
 psa_status_t psa_get_key_domain_parameters(
     const psa_key_attributes_t *attributes,
@@ -1352,8 +1352,8 @@
  *         compatible with the PAKE algorithm, or the hash algorithm in
  *         \p cipher_suite is not supported or not compatible with the PAKE
  *         algorithm and primitive.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid, or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1397,11 +1397,11 @@
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         The key type or key size of \p password is not supported with the
  *         \p operation's cipher suite.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must have been set up.), or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1439,9 +1439,9 @@
  *         suite.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         The value of \p user_id is not supported by the implementation.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid, or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1480,9 +1480,9 @@
  *         suite.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         The algorithm doesn't associate a second identity with the session.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         Calling psa_pake_set_peer() is invalid with the \p operation's
  *         algorithm, the operation state is not valid, or the library has not
@@ -1524,8 +1524,8 @@
  *         The \p role is not a valid PAKE role in the \p operation’s algorithm.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         The \p role for this algorithm is not supported or is not valid.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid, or
  *         the library has not been previously initialized by psa_crypto_init().
@@ -1575,13 +1575,13 @@
  *         \p step is not compatible with the operation's algorithm.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p step is not supported with the operation's algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active, and fully set
  *         up, and this call must conform to the algorithm's requirements
@@ -1631,12 +1631,12 @@
  *         \p step p is not supported with the \p operation's algorithm, or the
  *         \p input is not supported for the \p operation's algorithm, cipher
  *         suite or \p step.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active, and fully set
  *         up, and this call must conform to the algorithm's requirements
@@ -1691,12 +1691,12 @@
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         Input from a PAKE is not supported by the algorithm in the \p output
  *         key derivation operation.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The PAKE operation state is not valid (it must be active, but beyond
  *         that validity is specific to the algorithm), or
@@ -1728,8 +1728,8 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
diff --git a/include/psa/crypto_se_driver.h b/include/psa/crypto_se_driver.h
index a052789..9ae631f 100644
--- a/include/psa/crypto_se_driver.h
+++ b/include/psa/crypto_se_driver.h
@@ -385,8 +385,8 @@
  * \param[in] direction         Indicates whether the operation is an encrypt
  *                              or decrypt
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context,
                                                   void *op_context,
@@ -407,7 +407,7 @@
  * \param[in] p_iv              A buffer containing the initialization vector
  * \param[in] iv_length         The size (in bytes) of the `p_iv` buffer
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context,
                                                    const uint8_t *p_iv,
@@ -429,7 +429,7 @@
  * \param[out] p_output_length      After completion, will contain the number
  *                                  of bytes placed in the `p_output` buffer
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context,
                                                    const uint8_t *p_input,
@@ -450,7 +450,7 @@
  * \param[out] p_output_length  After completion, will contain the number of
  *                              bytes placed in the `p_output` buffer
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context,
                                                    uint8_t *p_output,
@@ -485,8 +485,8 @@
  * \param[in] output_size       The allocated size in bytes of the `p_output`
  *                              buffer
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context,
                                                 psa_key_slot_number_t key_slot,
@@ -554,7 +554,7 @@
  * \param[out] p_signature_length   On success, the number of bytes
  *                                  that make up the returned signature value
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context,
                                                      psa_key_slot_number_t key_slot,
@@ -618,7 +618,7 @@
  * \param[out] p_output_length  On success, the number of bytes that make up
  *                              the returned output
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context,
                                                         psa_key_slot_number_t key_slot,
@@ -658,7 +658,7 @@
  * \param[out] p_output_length  On success, the number of bytes
  *                              that make up the returned output
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context,
                                                         psa_key_slot_number_t key_slot,
@@ -904,8 +904,8 @@
  *         Success.
  *         The core will record \c *key_slot as the key slot where the key
  *         is stored and will update the persistent data in storage.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_allocate_key_t)(
     psa_drv_se_context_t *drv_context,
@@ -1043,13 +1043,13 @@
  * \param[out] p_data_length    On success, the number of bytes
  *                              that make up the key data.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_DOES_NOT_EXIST
- * \retval #PSA_ERROR_NOT_PERMITTED
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context,
                                                 psa_key_slot_number_t key,
@@ -1196,7 +1196,7 @@
  * \param[in] source_key        The key to be used as the source material for
  *                              the key derivation
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context,
                                                           void *op_context,
@@ -1216,7 +1216,7 @@
  * \param[in] p_collateral      A buffer containing the collateral data
  * \param[in] collateral_size   The size in bytes of the collateral
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context,
                                                                uint32_t collateral_id,
@@ -1231,7 +1231,7 @@
  * \param[in] dest_key          The slot where the generated key material
  *                              should be placed
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context,
                                                            psa_key_slot_number_t dest_key);
@@ -1245,7 +1245,7 @@
  * \param[out] p_output_length  Upon success, contains the number of bytes of
  *                              key material placed in `p_output`
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context,
                                                            uint8_t *p_output,
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 7a6caa2..934bc17 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -491,6 +491,66 @@
     return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits);
 }
 
+/**
+ * \brief The context for PSA interruptible hash signing.
+ */
+struct psa_sign_hash_interruptible_operation_s {
+    /** Unique ID indicating which driver got assigned to do the
+     * operation. Since driver contexts are driver-specific, swapping
+     * drivers halfway through the operation is not supported.
+     * ID values are auto-generated in psa_crypto_driver_wrappers.h
+     * ID value zero means the context is not valid or not assigned to
+     * any driver (i.e. none of the driver contexts are active). */
+    unsigned int MBEDTLS_PRIVATE(id);
+
+    psa_driver_sign_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx);
+
+    unsigned int MBEDTLS_PRIVATE(error_occurred) : 1;
+
+    uint32_t MBEDTLS_PRIVATE(num_ops);
+};
+
+#define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 }
+
+static inline struct psa_sign_hash_interruptible_operation_s
+psa_sign_hash_interruptible_operation_init(void)
+{
+    const struct psa_sign_hash_interruptible_operation_s v =
+        PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT;
+
+    return v;
+}
+
+/**
+ * \brief The context for PSA interruptible hash verification.
+ */
+struct psa_verify_hash_interruptible_operation_s {
+    /** Unique ID indicating which driver got assigned to do the
+     * operation. Since driver contexts are driver-specific, swapping
+     * drivers halfway through the operation is not supported.
+     * ID values are auto-generated in psa_crypto_driver_wrappers.h
+     * ID value zero means the context is not valid or not assigned to
+     * any driver (i.e. none of the driver contexts are active). */
+    unsigned int MBEDTLS_PRIVATE(id);
+
+    psa_driver_verify_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx);
+
+    unsigned int MBEDTLS_PRIVATE(error_occurred) : 1;
+
+    uint32_t MBEDTLS_PRIVATE(num_ops);
+};
+
+#define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 }
+
+static inline struct psa_verify_hash_interruptible_operation_s
+psa_verify_hash_interruptible_operation_init(void)
+{
+    const struct psa_verify_hash_interruptible_operation_s v =
+        PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT;
+
+    return v;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index ee95745..39acd96 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -335,6 +335,13 @@
  */
 #define PSA_ERROR_DATA_INVALID          ((psa_status_t)-153)
 
+/** The function that returns this status is defined as interruptible and
+ *  still has work to do, thus the user should call the function again with the
+ *  same operation context until it either returns #PSA_SUCCESS or any other
+ *  error. This is not an error per se, more a notification of status.
+ */
+#define PSA_OPERATION_INCOMPLETE           ((psa_status_t)-248)
+
 /* *INDENT-ON* */
 
 /**@}*/
@@ -2739,4 +2746,18 @@
 
 /**@}*/
 
+/**@}*/
+
+/** \defgroup interruptible Interruptible operations
+ * @{
+ */
+
+/** Maximum value for use with \c psa_interruptible_set_max_ops() to determine
+ *  the maximum number of ops allowed to be executed by an interruptible
+ *  function in a single call.
+ */
+#define PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED UINT32_MAX
+
+/**@}*/
+
 #endif /* PSA_CRYPTO_VALUES_H */
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 3ddb82b..eb3c303 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -239,13 +239,13 @@
  * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
  * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
  */
-static int ecdsa_sign_restartable(mbedtls_ecp_group *grp,
-                                  mbedtls_mpi *r, mbedtls_mpi *s,
-                                  const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                                  int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                                  int (*f_rng_blind)(void *, unsigned char *, size_t),
-                                  void *p_rng_blind,
-                                  mbedtls_ecdsa_restart_ctx *rs_ctx)
+int mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp,
+                                   mbedtls_mpi *r, mbedtls_mpi *s,
+                                   const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+                                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                                   int (*f_rng_blind)(void *, unsigned char *, size_t),
+                                   void *p_rng_blind,
+                                   mbedtls_ecdsa_restart_ctx *rs_ctx)
 {
     int ret, key_tries, sign_tries;
     int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
@@ -394,8 +394,8 @@
                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     /* Use the same RNG for both blinding and ephemeral key generation */
-    return ecdsa_sign_restartable(grp, r, s, d, buf, blen,
-                                  f_rng, p_rng, f_rng, p_rng, NULL);
+    return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
+                                          f_rng, p_rng, f_rng, p_rng, NULL);
 }
 #endif /* !MBEDTLS_ECDSA_SIGN_ALT */
 
@@ -406,13 +406,13 @@
  * note:    The f_rng_blind parameter must not be NULL.
  *
  */
-static int ecdsa_sign_det_restartable(mbedtls_ecp_group *grp,
-                                      mbedtls_mpi *r, mbedtls_mpi *s,
-                                      const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                                      mbedtls_md_type_t md_alg,
-                                      int (*f_rng_blind)(void *, unsigned char *, size_t),
-                                      void *p_rng_blind,
-                                      mbedtls_ecdsa_restart_ctx *rs_ctx)
+int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp,
+                                       mbedtls_mpi *r, mbedtls_mpi *s,
+                                       const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+                                       mbedtls_md_type_t md_alg,
+                                       int (*f_rng_blind)(void *, unsigned char *, size_t),
+                                       void *p_rng_blind,
+                                       mbedtls_ecdsa_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_hmac_drbg_context rng_ctx;
@@ -462,9 +462,9 @@
     ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen,
                              mbedtls_hmac_drbg_random, p_rng);
 #else
-    ret = ecdsa_sign_restartable(grp, r, s, d, buf, blen,
-                                 mbedtls_hmac_drbg_random, p_rng,
-                                 f_rng_blind, p_rng_blind, rs_ctx);
+    ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
+                                         mbedtls_hmac_drbg_random, p_rng,
+                                         f_rng_blind, p_rng_blind, rs_ctx);
 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
 
 cleanup:
@@ -487,8 +487,8 @@
                                                   size_t),
                                void *p_rng_blind)
 {
-    return ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg,
-                                      f_rng_blind, p_rng_blind, NULL);
+    return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg,
+                                              f_rng_blind, p_rng_blind, NULL);
 }
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
@@ -497,11 +497,12 @@
  * Verify ECDSA signature of hashed message (SEC1 4.1.4)
  * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
  */
-static int ecdsa_verify_restartable(mbedtls_ecp_group *grp,
-                                    const unsigned char *buf, size_t blen,
-                                    const mbedtls_ecp_point *Q,
-                                    const mbedtls_mpi *r, const mbedtls_mpi *s,
-                                    mbedtls_ecdsa_restart_ctx *rs_ctx)
+int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,
+                                     const unsigned char *buf, size_t blen,
+                                     const mbedtls_ecp_point *Q,
+                                     const mbedtls_mpi *r,
+                                     const mbedtls_mpi *s,
+                                     mbedtls_ecdsa_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi e, s_inv, u1, u2;
@@ -610,7 +611,7 @@
                          const mbedtls_mpi *r,
                          const mbedtls_mpi *s)
 {
-    return ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL);
+    return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL);
 }
 #endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
 
@@ -665,9 +666,9 @@
     mbedtls_mpi_init(&s);
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-    MBEDTLS_MPI_CHK(ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d,
-                                               hash, hlen, md_alg, f_rng,
-                                               p_rng, rs_ctx));
+    MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d,
+                                                       hash, hlen, md_alg, f_rng,
+                                                       p_rng, rs_ctx));
 #else
     (void) md_alg;
 
@@ -678,9 +679,9 @@
                                        hash, hlen, f_rng, p_rng));
 #else
     /* Use the same RNG for both blinding and ephemeral key generation */
-    MBEDTLS_MPI_CHK(ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d,
-                                           hash, hlen, f_rng, p_rng, f_rng,
-                                           p_rng, rs_ctx));
+    MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d,
+                                                   hash, hlen, f_rng, p_rng, f_rng,
+                                                   p_rng, rs_ctx));
 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
@@ -760,8 +761,8 @@
         goto cleanup;
     }
 #else
-    if ((ret = ecdsa_verify_restartable(&ctx->grp, hash, hlen,
-                                        &ctx->Q, &r, &s, rs_ctx)) != 0) {
+    if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen,
+                                                &ctx->Q, &r, &s, rs_ctx)) != 0) {
         goto cleanup;
     }
 #endif /* MBEDTLS_ECDSA_VERIFY_ALT */
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index 1a027d6..b352e76 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -5534,6 +5534,188 @@
 }
 #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
 
-#endif /* !MBEDTLS_ECP_ALT */
+#if defined(MBEDTLS_TEST_HOOKS)
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                              const mbedtls_ecp_group_id id,
+                              const mbedtls_ecp_curve_type ctype)
+{
+    mbedtls_mpi_uint *p = NULL;
+    size_t p_limbs;
 
+    if (!(ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE || \
+          ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_SCALAR)) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    switch (id) {
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP192R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp192r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp192r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP224R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp224r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp224r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP256R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp256r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp256r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP384R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp384r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp384r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP521R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp521r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp521r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP256R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) brainpoolP256r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) brainpoolP256r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP384R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) brainpoolP384r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) brainpoolP384r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP512R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) brainpoolP512r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) brainpoolP512r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+        case MBEDTLS_ECP_DP_CURVE25519:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) curve25519_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p));
+            } else {
+                p = (mbedtls_mpi_uint *) curve25519_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP192K1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp192k1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp192k1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP224K1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp224k1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp224k1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP256K1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp256k1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp256k1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+        case MBEDTLS_ECP_DP_CURVE448:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) curve448_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p));
+            } else {
+                p = (mbedtls_mpi_uint *) curve448_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n));
+            }
+            break;
+#endif
+
+        default:
+        case MBEDTLS_ECP_DP_NONE:
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs,
+                                      MBEDTLS_MPI_MOD_REP_MONTGOMERY)) {
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+    return 0;
+}
+#endif /* MBEDTLS_TEST_HOOKS */
+#endif /* !MBEDTLS_ECP_ALT */
 #endif /* MBEDTLS_ECP_C */
diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h
index 3d1321c..aba7cca 100644
--- a/library/ecp_invasive.h
+++ b/library/ecp_invasive.h
@@ -28,6 +28,7 @@
 
 #include "common.h"
 #include "mbedtls/bignum.h"
+#include "bignum_mod.h"
 #include "mbedtls/ecp.h"
 
 #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C)
@@ -117,6 +118,28 @@
 
 #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
 
+/** Initialise a modulus with hard-coded const curve data.
+ *
+ * \note            The caller is responsible for the \p N modulus' memory.
+ *                  mbedtls_mpi_mod_modulus_free(&N) should be invoked at the
+ *                  end of its lifecycle.
+ *
+ * \param[in,out] N The address of the modulus structure to populate.
+ *                  Must be initialized.
+ * \param[in] id    The mbedtls_ecp_group_id for which to initialise the modulus.
+ * \param[in] ctype The mbedtls_ecp_curve_type identifier for a coordinate modulus (P)
+ *                  or a scalar modulus (N).
+ *
+ * \return          \c 0 if successful.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the given MPIs do not
+ *                  have the correct number of limbs.
+ *
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                              const mbedtls_ecp_group_id id,
+                              const mbedtls_ecp_curve_type ctype);
+
 #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */
 
 #endif /* MBEDTLS_ECP_INVASIVE_H */
diff --git a/library/oid.c b/library/oid.c
index e7c1224..86214b2 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -834,21 +834,55 @@
     p = buf;
     n = size;
 
-    /* First byte contains first two dots */
-    if (oid->len > 0) {
-        ret = mbedtls_snprintf(p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40);
-        OID_SAFE_SNPRINTF;
+    /* First subidentifier contains first two OID components */
+    i = 0;
+    value = 0;
+    if ((oid->p[0]) == 0x80) {
+        /* Overlong encoding is not allowed */
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
     }
 
-    value = 0;
-    for (i = 1; i < oid->len; i++) {
+    while (i < oid->len && ((oid->p[i] & 0x80) != 0)) {
         /* Prevent overflow in value. */
-        if (((value << 7) >> 7) != value) {
-            return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
+        if (value > (UINT_MAX >> 7)) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+
+        value |= oid->p[i] & 0x7F;
+        value <<= 7;
+        i++;
+    }
+    if (i >= oid->len) {
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
+    /* Last byte of first subidentifier */
+    value |= oid->p[i] & 0x7F;
+    i++;
+
+    unsigned int component1 = value / 40;
+    if (component1 > 2) {
+        /* The first component can only be 0, 1 or 2.
+         * If oid->p[0] / 40 is greater than 2, the leftover belongs to
+         * the second component. */
+        component1 = 2;
+    }
+    unsigned int component2 = value - (40 * component1);
+    ret = mbedtls_snprintf(p, n, "%u.%u", component1, component2);
+    OID_SAFE_SNPRINTF;
+
+    value = 0;
+    for (; i < oid->len; i++) {
+        /* Prevent overflow in value. */
+        if (value > (UINT_MAX >> 7)) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+        if ((value == 0) && ((oid->p[i]) == 0x80)) {
+            /* Overlong encoding is not allowed */
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
         }
 
         value <<= 7;
-        value += oid->p[i] & 0x7F;
+        value |= oid->p[i] & 0x7F;
 
         if (!(oid->p[i] & 0x80)) {
             /* Last byte */
diff --git a/library/pkcs7.c b/library/pkcs7.c
index 4fdbe36..010d706 100644
--- a/library/pkcs7.c
+++ b/library/pkcs7.c
@@ -57,7 +57,10 @@
     ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED
                                | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
     if (ret != 0) {
-        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
+    } else if ((size_t) (end - *p) != *len) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
+                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
     return ret;
@@ -184,13 +187,13 @@
     size_t len2 = 0;
     unsigned char *end_set, *end_cert, *start;
 
-    if ((ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
-                                    | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) {
-        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
-            return 0;
-        } else {
-            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
-        }
+    ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+    if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+        return 0;
+    }
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
     }
     start = *p;
     end_set = *p + len1;
@@ -213,12 +216,11 @@
         return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
     }
 
-    *p = start;
-    if ((ret = mbedtls_x509_crt_parse_der(certs, *p, len1)) < 0) {
+    if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) {
         return MBEDTLS_ERR_PKCS7_INVALID_CERT;
     }
 
-    *p = *p + len1;
+    *p = end_cert;
 
     /*
      * Since in this version we strictly support single certificate, and reaching
@@ -285,7 +287,8 @@
  * and unauthenticatedAttributes.
  **/
 static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,
-                                 mbedtls_pkcs7_signer_info *signer)
+                                 mbedtls_pkcs7_signer_info *signer,
+                                 mbedtls_x509_buf *alg)
 {
     unsigned char *end_signer, *end_issuer_and_sn;
     int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -343,8 +346,15 @@
         goto out;
     }
 
-    /* Assume authenticatedAttributes is nonexistent */
+    /* Check that the digest algorithm used matches the one provided earlier */
+    if (signer->alg_identifier.tag != alg->tag ||
+        signer->alg_identifier.len != alg->len ||
+        memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) {
+        ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
+        goto out;
+    }
 
+    /* Asssume authenticatedAttributes is nonexistent */
     ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier);
     if (ret != 0) {
         goto out;
@@ -377,7 +387,8 @@
  * Return negative error code for failure.
  **/
 static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end,
-                                      mbedtls_pkcs7_signer_info *signers_set)
+                                      mbedtls_pkcs7_signer_info *signers_set,
+                                      mbedtls_x509_buf *digest_alg)
 {
     unsigned char *end_set;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -397,7 +408,7 @@
 
     end_set = *p + len;
 
-    ret = pkcs7_get_signer_info(p, end_set, signers_set);
+    ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg);
     if (ret != 0) {
         return ret;
     }
@@ -412,7 +423,7 @@
             goto cleanup;
         }
 
-        ret = pkcs7_get_signer_info(p, end_set, signer);
+        ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg);
         if (ret != 0) {
             mbedtls_free(signer);
             goto cleanup;
@@ -454,7 +465,7 @@
 {
     unsigned char *p = buf;
     unsigned char *end = buf + buflen;
-    unsigned char *end_set, *end_content_info;
+    unsigned char *end_content_info = NULL;
     size_t len = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_md_type_t md_alg;
@@ -465,16 +476,19 @@
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
     }
 
-    end_set = p + len;
+    if (p + len != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
     /* Get version of signed data */
-    ret = pkcs7_get_version(&p, end_set, &signed_data->version);
+    ret = pkcs7_get_version(&p, end, &signed_data->version);
     if (ret != 0) {
         return ret;
     }
 
     /* Get digest algorithm */
-    ret = pkcs7_get_digest_algorithm_set(&p, end_set,
+    ret = pkcs7_get_digest_algorithm_set(&p, end,
                                          &signed_data->digest_alg_identifiers);
     if (ret != 0) {
         return ret;
@@ -485,12 +499,15 @@
         return MBEDTLS_ERR_PKCS7_INVALID_ALG;
     }
 
-    /* Do not expect any content */
-    ret = pkcs7_get_content_info_type(&p, end_set, &end_content_info,
-                                      &signed_data->content.oid);
+    mbedtls_pkcs7_buf content_type;
+    memset(&content_type, 0, sizeof(content_type));
+    ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type);
     if (ret != 0) {
         return ret;
     }
+    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) {
+        return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
+    }
 
     if (p != end_content_info) {
         /* Determine if valid content is present */
@@ -509,13 +526,9 @@
         return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
     }
 
-    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid)) {
-        return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
-    }
-
     /* Look for certificates, there may or may not be any */
     mbedtls_x509_crt_init(&signed_data->certs);
-    ret = pkcs7_get_certificates(&p, end_set, &signed_data->certs);
+    ret = pkcs7_get_certificates(&p, end, &signed_data->certs);
     if (ret < 0) {
         return ret;
     }
@@ -531,7 +544,10 @@
     signed_data->no_of_crls = 0;
 
     /* Get signers info */
-    ret = pkcs7_get_signers_info_set(&p, end_set, &signed_data->signers);
+    ret = pkcs7_get_signers_info_set(&p,
+                                     end,
+                                     &signed_data->signers,
+                                     &signed_data->digest_alg_identifiers);
     if (ret < 0) {
         return ret;
     }
@@ -550,10 +566,9 @@
                             const size_t buflen)
 {
     unsigned char *p;
-    unsigned char *end, *end_content_info;
+    unsigned char *end;
     size_t len = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    int isoidset = 0;
 
     if (pkcs7 == NULL) {
         return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
@@ -569,34 +584,45 @@
     pkcs7->raw.len = buflen;
     end = p + buflen;
 
-    ret = pkcs7_get_content_info_type(&p, end, &end_content_info,
-                                      &pkcs7->content_type_oid);
+    ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_SEQUENCE);
     if (ret != 0) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
+        goto out;
+    }
+
+    if ((size_t) (end - p) != len) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
+                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        goto out;
+    }
+
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
+        if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+            goto out;
+        }
+        p = pkcs7->raw.p;
         len = buflen;
         goto try_data;
     }
 
-    /* Ensure PKCS7 data uses the exact number of bytes specified in buflen */
-    if (end_content_info != end) {
-        ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+    if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) {
+        /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */
+        if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len)
+            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len)
+            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len)
+            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len)
+            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) {
+            /* OID is valid according to the spec, but unsupported */
+            ret =  MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+        } else {
+            /* OID is invalid according to the spec */
+            ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+        }
         goto out;
     }
 
-    if (!MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &pkcs7->content_type_oid)
-        || !MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, &pkcs7->content_type_oid)
-        || !MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, &pkcs7->content_type_oid)
-        || !MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DIGESTED_DATA, &pkcs7->content_type_oid)
-        || !MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid)) {
-        ret =  MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
-        goto out;
-    }
-
-    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_SIGNED_DATA, &pkcs7->content_type_oid)) {
-        ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
-        goto out;
-    }
-
-    isoidset = 1;
+    p += len;
 
     ret = pkcs7_get_next_content_len(&p, end, &len);
     if (ret != 0) {
@@ -615,12 +641,6 @@
         goto out;
     }
 
-    if (!isoidset) {
-        pkcs7->content_type_oid.tag = MBEDTLS_ASN1_OID;
-        pkcs7->content_type_oid.len = MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS7_SIGNED_DATA);
-        pkcs7->content_type_oid.p = (unsigned char *) MBEDTLS_OID_PKCS7_SIGNED_DATA;
-    }
-
     ret = MBEDTLS_PKCS7_SIGNED_DATA;
 
 out:
@@ -653,6 +673,39 @@
         return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
     }
 
+    ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg);
+    if (ret != 0) {
+        return ret;
+    }
+
+    md_info = mbedtls_md_info_from_type(md_alg);
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+    }
+
+    hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1);
+    if (hash == NULL) {
+        return MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
+    }
+
+    /* BEGIN must free hash before jumping out */
+    if (is_data_hash) {
+        if (datalen != mbedtls_md_get_size(md_info)) {
+            ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+        } else {
+            memcpy(hash, data, datalen);
+        }
+    } else {
+        ret = mbedtls_md(md_info, data, datalen, hash);
+    }
+    if (ret != 0) {
+        mbedtls_free(hash);
+        return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+    }
+
+    /* assume failure */
+    ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+
     /*
      * Potential TODOs
      * Currently we iterate over all signers and return success if any of them
@@ -662,61 +715,30 @@
      * identification and SignerIdentifier fields first. That would also allow
      * us to distinguish between 'no signature for key' and 'signature for key
      * failed to validate'.
-     *
-     * We could also cache hashes by md, so if there are several sigs all using
-     * the same algo we don't recalculate the hash each time.
      */
     for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) {
-        ret = mbedtls_oid_get_md_alg(&signer->alg_identifier, &md_alg);
-        if (ret != 0) {
-            ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
-            continue;
-        }
-
-        md_info = mbedtls_md_info_from_type(md_alg);
-        if (md_info == NULL) {
-            ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
-            continue;
-        }
-
-        hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1);
-        if (hash == NULL) {
-            return MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
-        }
-        /* BEGIN must free hash before jumping out */
-        if (is_data_hash) {
-            if (datalen != mbedtls_md_get_size(md_info)) {
-                ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
-            } else {
-                memcpy(hash, data, datalen);
-            }
-        } else {
-            ret = mbedtls_md(md_info, data, datalen, hash);
-        }
-        if (ret != 0) {
-            ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
-            mbedtls_free(hash);
-            continue;
-        }
-
         ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash,
                                 mbedtls_md_get_size(md_info),
                                 signer->sig.p, signer->sig.len);
-        mbedtls_free(hash);
-        /* END must free hash before jumping out */
 
         if (ret == 0) {
             break;
         }
     }
 
+    mbedtls_free(hash);
+    /* END must free hash before jumping out */
     return ret;
 }
+
 int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
                                      const mbedtls_x509_crt *cert,
                                      const unsigned char *data,
                                      size_t datalen)
 {
+    if (data == NULL) {
+        return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+    }
     return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0);
 }
 
@@ -725,6 +747,9 @@
                                      const unsigned char *hash,
                                      size_t hashlen)
 {
+    if (hash == NULL) {
+        return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+    }
     return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1);
 }
 
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index a683fdb..4445577 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;
 
@@ -1673,12 +1677,12 @@
  *
  * \retval #PSA_SUCCESS
  *         The key was successfully created.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_ALREADY_EXISTS
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  *
  * \return If this function fails, the key slot is an invalid state.
  *         You must call psa_fail_key_creation() to wipe and free the slot.
@@ -2679,6 +2683,37 @@
     return PSA_SUCCESS;
 }
 
+/**
+ * \brief                       Fill the unused part of the output buffer (the
+ *                              whole buffer on error, the trailing part on
+ *                              success) with something that isn't a valid
+ *                              signature (barring an attack on the signature
+ *                              and deliberately-crafted input), in case the
+ *                              caller doesn't check the return status properly.
+ *
+ * \param output_buffer         pointer to buffer to wipe. May not be NULL
+ *                              unless \p output_buffer_size is zero.
+ * \param status                status of function called to generate
+ *                              output_buffer originally
+ * \param output_buffer_size    Size of output buffer. If zero, \p output_buffer
+ *                              could be NULL
+ * \param output_buffer_length  Length of data written to output_buffer, must be
+ *                              less than \p output_buffer_size
+ */
+static void psa_wipe_output_buffer(uint8_t *output_buffer, psa_status_t status,
+                                   size_t output_buffer_size, size_t output_buffer_length)
+{
+    if (status == PSA_SUCCESS) {
+        memset(output_buffer + output_buffer_length, '!',
+               output_buffer_size - output_buffer_length);
+    } else if (output_buffer_size > 0) {
+        memset(output_buffer, '!', output_buffer_size);
+    }
+    /* If output_buffer_size is 0 then we have nothing to do. We must
+     * not call memset because output_buffer may be NULL in this
+     * case.*/
+}
+
 static psa_status_t psa_sign_internal(mbedtls_svc_key_id_t key,
                                       int input_is_message,
                                       psa_algorithm_t alg,
@@ -2741,18 +2776,8 @@
 
 
 exit:
-    /* Fill the unused part of the output buffer (the whole buffer on error,
-     * the trailing part on success) with something that isn't a valid signature
-     * (barring an attack on the signature and deliberately-crafted input),
-     * in case the caller doesn't check the return status properly. */
-    if (status == PSA_SUCCESS) {
-        memset(signature + *signature_length, '!',
-               signature_size - *signature_length);
-    } else {
-        memset(signature, '!', signature_size);
-    }
-    /* If signature_size is 0 then we have nothing to do. We must not call
-     * memset because signature may be NULL in this case. */
+    psa_wipe_output_buffer(signature, status, signature_size,
+                           *signature_length);
 
     unlock_status = psa_unlock_key_slot(slot);
 
@@ -3124,7 +3149,766 @@
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
+/****************************************************************/
+/* Asymmetric interruptible cryptography                        */
+/****************************************************************/
 
+void psa_interruptible_set_max_ops(uint32_t max_ops)
+{
+    psa_driver_wrapper_interruptible_set_max_ops(max_ops);
+}
+
+uint32_t psa_interruptible_get_max_ops(void)
+{
+    return psa_driver_wrapper_interruptible_get_max_ops();
+}
+
+
+uint32_t psa_sign_hash_get_num_ops(
+    const psa_sign_hash_interruptible_operation_t *operation)
+{
+    return operation->num_ops;
+}
+
+uint32_t psa_verify_hash_get_num_ops(
+    const psa_verify_hash_interruptible_operation_t *operation)
+{
+    return operation->num_ops;
+}
+
+static psa_status_t psa_sign_hash_abort_internal(
+    psa_sign_hash_interruptible_operation_t *operation)
+{
+    if (operation->id == 0) {
+        /* The object has (apparently) been initialized but it is not (yet)
+         * in use. It's ok to call abort on such an object, and there's
+         * nothing to do. */
+        return PSA_SUCCESS;
+    }
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_driver_wrapper_sign_hash_abort(operation);
+
+    operation->id = 0;
+
+    /* Do not clear either the error_occurred or num_ops elements here as they
+     * only want to be cleared by the application calling abort, not by abort
+     * being called at completion of an operation. */
+
+    return status;
+}
+
+psa_status_t psa_sign_hash_start(
+    psa_sign_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key, psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    /* Check that start has not been previously called, or operation has not
+     * previously errored. */
+    if (operation->id != 0 || operation->error_occurred) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    status = psa_sign_verify_check_alg(0, alg);
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        return status;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot,
+                                                   PSA_KEY_USAGE_SIGN_HASH,
+                                                   alg);
+
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    psa_key_attributes_t attributes = {
+        .core = slot->attr
+    };
+
+    /* Ensure ops count gets reset, in case of operation re-use. */
+    operation->num_ops = 0;
+
+    status = psa_driver_wrapper_sign_hash_start(operation, &attributes,
+                                                slot->key.data,
+                                                slot->key.bytes, alg,
+                                                hash, hash_length);
+exit:
+
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        psa_sign_hash_abort_internal(operation);
+    }
+
+    unlock_status = psa_unlock_key_slot(slot);
+
+    if (unlock_status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+    }
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+
+psa_status_t psa_sign_hash_complete(
+    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;
+
+    *signature_length = 0;
+
+    /* Check that start has been called first, and that operation has not
+     * previously errored. */
+    if (operation->id == 0 || operation->error_occurred) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    /* Immediately reject a zero-length signature buffer. This guarantees that
+     * signature must be a valid pointer. */
+    if (signature_size == 0) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_sign_hash_complete(operation, signature,
+                                                   signature_size,
+                                                   signature_length);
+
+    /* Update ops count with work done. */
+    operation->num_ops = psa_driver_wrapper_sign_hash_get_num_ops(operation);
+
+exit:
+
+    psa_wipe_output_buffer(signature, status, signature_size,
+                           *signature_length);
+
+    if (status != PSA_OPERATION_INCOMPLETE) {
+        if (status != PSA_SUCCESS) {
+            operation->error_occurred = 1;
+        }
+
+        psa_sign_hash_abort_internal(operation);
+    }
+
+    return status;
+}
+
+psa_status_t psa_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *operation)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_sign_hash_abort_internal(operation);
+
+    /* We clear the number of ops done here, so that it is not cleared when
+     * the operation fails or succeeds, only on manual abort. */
+    operation->num_ops = 0;
+
+    /* Likewise, failure state. */
+    operation->error_occurred = 0;
+
+    return status;
+}
+
+static psa_status_t psa_verify_hash_abort_internal(
+    psa_verify_hash_interruptible_operation_t *operation)
+{
+    if (operation->id == 0) {
+        /* The object has (apparently) been initialized but it is not (yet)
+         * in use. It's ok to call abort on such an object, and there's
+         * nothing to do. */
+        return PSA_SUCCESS;
+    }
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_driver_wrapper_verify_hash_abort(operation);
+
+    operation->id = 0;
+
+    /* Do not clear either the error_occurred or num_ops elements here as they
+     * only want to be cleared by the application calling abort, not by abort
+     * being called at completion of an operation. */
+
+    return status;
+}
+
+psa_status_t psa_verify_hash_start(
+    psa_verify_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key, 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;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    /* Check that start has not been previously called, or operation has not
+     * previously errored. */
+    if (operation->id != 0 || operation->error_occurred) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    status = psa_sign_verify_check_alg(0, alg);
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        return status;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot,
+                                                   PSA_KEY_USAGE_VERIFY_HASH,
+                                                   alg);
+
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        return status;
+    }
+
+    psa_key_attributes_t attributes = {
+        .core = slot->attr
+    };
+
+    /* Ensure ops count gets reset, in case of operation re-use. */
+    operation->num_ops = 0;
+
+    status = psa_driver_wrapper_verify_hash_start(operation, &attributes,
+                                                  slot->key.data,
+                                                  slot->key.bytes,
+                                                  alg, hash, hash_length,
+                                                  signature, signature_length);
+
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        psa_verify_hash_abort_internal(operation);
+    }
+
+    unlock_status = psa_unlock_key_slot(slot);
+
+    if (unlock_status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+    }
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+psa_status_t psa_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *operation)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    /* Check that start has been called first, and that operation has not
+     * previously errored. */
+    if (operation->id == 0 || operation->error_occurred) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_verify_hash_complete(operation);
+
+    /* Update ops count with work done. */
+    operation->num_ops = psa_driver_wrapper_verify_hash_get_num_ops(
+        operation);
+
+exit:
+
+    if (status != PSA_OPERATION_INCOMPLETE) {
+        if (status != PSA_SUCCESS) {
+            operation->error_occurred = 1;
+        }
+
+        psa_verify_hash_abort_internal(operation);
+    }
+
+    return status;
+}
+
+psa_status_t psa_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *operation)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_verify_hash_abort_internal(operation);
+
+    /* We clear the number of ops done here, so that it is not cleared when
+     * the operation fails or succeeds, only on manual abort. */
+    operation->num_ops = 0;
+
+    /* Likewise, failure state. */
+    operation->error_occurred = 0;
+
+    return status;
+}
+
+/****************************************************************/
+/* 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)
+{
+    mbedtls_psa_interruptible_max_ops = 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_ecp_set_max_ops(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->num_ops;
+#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->num_ops;
+#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;
+    size_t required_hash_length;
+
+    if (!PSA_KEY_TYPE_IS_ECC(attributes->core.type)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (!PSA_ALG_IS_ECDSA(alg)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    mbedtls_ecdsa_restart_init(&operation->restart_ctx);
+
+    /* Ensure num_ops is zero'ed in case of context re-use. */
+    operation->num_ops = 0;
+
+    /* Ensure default is set even if
+     * mbedtls_psa_interruptible_set_max_ops() has not been called. */
+    mbedtls_psa_interruptible_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->coordinate_bytes = PSA_BITS_TO_BYTES(
+        operation->ctx->grp.nbits);
+
+    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;
+
+    /* We only need to store the same length of hash as the private key size
+     * here, it would be truncated by the internal implementation anyway. */
+    required_hash_length = (hash_length < operation->coordinate_bytes ?
+                            hash_length : operation->coordinate_bytes);
+
+    if (required_hash_length > sizeof(operation->hash)) {
+        /* Shouldn't happen, but better safe than sorry. */
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    memcpy(operation->hash, hash, required_hash_length);
+    operation->hash_length = required_hash_length;
+
+    return PSA_SUCCESS;
+
+#else
+    (void) operation;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+    (void) status;
+    (void) required_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 ) */
+}
+
+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)
+{
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi r;
+    mbedtls_mpi s;
+
+    mbedtls_mpi_init(&r);
+    mbedtls_mpi_init(&s);
+
+    if (signature_size < 2 * operation->coordinate_bytes) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    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,
+                                               &r,
+                                               &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) */
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto exit;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+    } else {
+        status = mbedtls_to_psa_error(
+            mbedtls_ecdsa_sign_restartable(&operation->ctx->grp,
+                                           &r,
+                                           &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));
+    }
+
+    /* Hide the fact that the restart context only holds a delta of number of
+     * ops done during the last operation, not an absolute value. */
+    operation->num_ops += operation->restart_ctx.ecp.ops_done;
+
+    if (status == PSA_SUCCESS) {
+        status =  mbedtls_to_psa_error(
+            mbedtls_mpi_write_binary(&r,
+                                     signature,
+                                     operation->coordinate_bytes)
+            );
+
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        status =  mbedtls_to_psa_error(
+            mbedtls_mpi_write_binary(&s,
+                                     signature +
+                                     operation->coordinate_bytes,
+                                     operation->coordinate_bytes)
+            );
+
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        *signature_length = operation->coordinate_bytes * 2;
+
+        status = PSA_SUCCESS;
+    }
+
+exit:
+
+    mbedtls_mpi_free(&r);
+    mbedtls_mpi_free(&s);
+    return status;
+
+ #else
+
+    (void) operation;
+    (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);
+        operation->ctx = NULL;
+    }
+
+    mbedtls_ecdsa_restart_free(&operation->restart_ctx);
+
+    operation->num_ops = 0;
+
+    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;
+    size_t coordinate_bytes = 0;
+    size_t required_hash_length = 0;
+
+    if (!PSA_KEY_TYPE_IS_ECC(attributes->core.type)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (!PSA_ALG_IS_ECDSA(alg)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    mbedtls_ecdsa_restart_init(&operation->restart_ctx);
+    mbedtls_mpi_init(&operation->r);
+    mbedtls_mpi_init(&operation->s);
+
+    /* Ensure num_ops is zero'ed in case of context re-use. */
+    operation->num_ops = 0;
+
+    /* Ensure default is set even if
+     * mbedtls_psa_interruptible_set_max_ops() has not been called. */
+    mbedtls_psa_interruptible_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;
+    }
+
+    coordinate_bytes = PSA_BITS_TO_BYTES(operation->ctx->grp.nbits);
+
+    if (signature_length != 2 * coordinate_bytes) {
+        return PSA_ERROR_INVALID_SIGNATURE;
+    }
+
+    status = mbedtls_to_psa_error(
+        mbedtls_mpi_read_binary(&operation->r,
+                                signature,
+                                coordinate_bytes));
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = mbedtls_to_psa_error(
+        mbedtls_mpi_read_binary(&operation->s,
+                                signature +
+                                coordinate_bytes,
+                                coordinate_bytes));
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = mbedtls_psa_ecp_load_public_part(operation->ctx);
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* We only need to store the same length of hash as the private key size
+     * here, it would be truncated by the internal implementation anyway. */
+    required_hash_length = (hash_length < coordinate_bytes ? hash_length :
+                            coordinate_bytes);
+
+    if (required_hash_length > sizeof(operation->hash)) {
+        /* Shouldn't happen, but better safe than sorry. */
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    memcpy(operation->hash, hash, required_hash_length);
+    operation->hash_length = required_hash_length;
+
+    return PSA_SUCCESS;
+#else
+    (void) operation;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+    (void) signature;
+    (void) signature_length;
+    (void) status;
+    (void) coordinate_bytes;
+    (void) required_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 ) */
+}
+
+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)
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = 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));
+
+    /* Hide the fact that the restart context only holds a delta of number of
+     * ops done during the last operation, not an absolute value. */
+    operation->num_ops += operation->restart_ctx.ecp.ops_done;
+
+    return status;
+#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);
+        operation->ctx = NULL;
+    }
+
+    mbedtls_ecdsa_restart_free(&operation->restart_ctx);
+
+    operation->num_ops = 0;
+
+    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_aead.h b/library/psa_crypto_aead.h
index 2ae8fe8..4b24b0f 100644
--- a/library/psa_crypto_aead.h
+++ b/library/psa_crypto_aead.h
@@ -71,10 +71,10 @@
  * \retval #PSA_SUCCESS Success.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         ciphertext_size is too small.
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_aead_encrypt(
     const psa_key_attributes_t *attributes,
@@ -134,10 +134,10 @@
  *         The cipher is not authentic.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         plaintext_size is too small.
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_aead_decrypt(
     const psa_key_attributes_t *attributes,
diff --git a/library/psa_crypto_cipher.h b/library/psa_crypto_cipher.h
index 6cc6bf6..bf43ff0 100644
--- a/library/psa_crypto_cipher.h
+++ b/library/psa_crypto_cipher.h
@@ -59,10 +59,10 @@
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_cipher_encrypt_setup(
     mbedtls_psa_cipher_operation_t *operation,
@@ -89,10 +89,10 @@
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_cipher_decrypt_setup(
     mbedtls_psa_cipher_operation_t *operation,
@@ -116,11 +116,11 @@
  *                              the core to be less or equal to
  *                              PSA_CIPHER_IV_MAX_SIZE.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The size of \p iv is not acceptable for the chosen algorithm,
  *         or the chosen algorithm does not use an IV.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t mbedtls_psa_cipher_set_iv(
     mbedtls_psa_cipher_operation_t *operation,
@@ -142,10 +142,10 @@
  * \param[out] output_length    On success, the number of bytes
  *                              that make up the returned output.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t mbedtls_psa_cipher_update(
     mbedtls_psa_cipher_operation_t *operation,
@@ -165,7 +165,7 @@
  * \param[out] output_length    On success, the number of bytes
  *                              that make up the returned output.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The total input size passed to this operation is not valid for
  *         this particular algorithm. For example, the algorithm is a based
@@ -176,7 +176,7 @@
  *         padding, and the ciphertext does not contain valid padding.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t mbedtls_psa_cipher_finish(
     mbedtls_psa_cipher_operation_t *operation,
@@ -195,7 +195,7 @@
  *
  * \param[in,out] operation     Initialized cipher operation.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  */
 psa_status_t mbedtls_psa_cipher_abort(mbedtls_psa_cipher_operation_t *operation);
 
@@ -224,10 +224,10 @@
  *                              the returned output. Initialized to zero
  *                              by the core.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -275,10 +275,10 @@
  *                              the returned output. Initialized to zero
  *                              by the core.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 38e4bc5..4acd7aa 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -209,7 +209,7 @@
  * \retval #PSA_SUCCESS
  *         Success. This includes the case of a key slot that was
  *         already fully wiped.
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot);
 
@@ -285,9 +285,9 @@
  * \retval #PSA_SUCCESS  The key was imported successfully.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The key data is not correctly formatted.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t psa_import_key_into_slot(
     const psa_key_attributes_t *attributes,
@@ -310,12 +310,12 @@
  *                              \p data
  *
  * \retval #PSA_SUCCESS  The key was exported successfully.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t psa_export_key_internal(
     const psa_key_attributes_t *attributes,
@@ -338,12 +338,12 @@
  *                              \p data
  *
  * \retval #PSA_SUCCESS  The public key was exported successfully.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t psa_export_public_key_internal(
     const psa_key_attributes_t *attributes,
@@ -364,7 +364,7 @@
  *
  * \retval #PSA_SUCCESS
  *         The key was generated successfully.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         Key size in bits or type not supported.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
@@ -399,18 +399,18 @@
  * \param[out] signature_length On success, the number of bytes
  *                              that make up the returned signature value.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \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 the 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
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
  */
 psa_status_t psa_sign_message_builtin(
     const psa_key_attributes_t *attributes,
@@ -445,9 +445,9 @@
  * \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
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t psa_verify_message_builtin(
     const psa_key_attributes_t *attributes,
@@ -475,18 +475,18 @@
  * \param[out] signature_length On success, the number of bytes
  *                              that make up the returned signature value.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \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 the 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
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
  */
 psa_status_t psa_sign_hash_builtin(
     const psa_key_attributes_t *attributes,
@@ -519,9 +519,9 @@
  * \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
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t psa_verify_hash_builtin(
     const psa_key_attributes_t *attributes,
@@ -577,8 +577,8 @@
  *                                  up the returned shared secret.
  * \retval #PSA_SUCCESS
  *         Success. Shared secret successfully calculated.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p alg is not a key agreement algorithm, or
  *         \p private_key is not compatible with \p alg,
@@ -588,12 +588,12 @@
  *         \p shared_secret_size is too small
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not a supported key agreement algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_BAD_STATE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE \emptydescription
  */
 psa_status_t psa_key_agreement_raw_builtin(
     const psa_key_attributes_t *attributes,
@@ -606,4 +606,272 @@
     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.
+ *
+ * \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.
+ *
+ * \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 for the
+ *        previous call. If no call or work has taken place, this will return
+ *        zero.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash_get_num_ops entry point. This function behaves as an
+ *       sign_hash_get_num_ops entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param   operation           The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \return                      Number of ops that were completed
+ *                              in the last call to \c
+ *                              mbedtls_psa_sign_hash_complete().
+ */
+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 for
+ *        the previous call. If no call or work has taken place, this will
+ *        return zero.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_hash_get_num_ops entry point. This function behaves as an
+ *       verify_hash_get_num_ops entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param   operation           The \c
+ *                              mbedtls_psa_verify_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \return                      Number of ops that were completed
+ *                              in the last call to \c
+ *                              mbedtls_psa_verify_hash_complete().
+ */
+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.
+ *
+ * \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.
+ *
+ * \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.
+ *
+ * \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.
+ *
+ * \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 either to load the key representation,
+ *        or to prepare the operation.
+ */
+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.
+ *
+ * \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.
+ *
+ * \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 */
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
index da3cd1d..e3edec7 100644
--- a/library/psa_crypto_driver_wrappers.h
+++ b/library/psa_crypto_driver_wrappers.h
@@ -67,6 +67,47 @@
     const uint8_t *signature, size_t signature_length);
 
 /*
+ * Interruptible Signature functions
+ */
+
+void psa_driver_wrapper_interruptible_set_max_ops(uint32_t max_ops);
+
+uint32_t psa_driver_wrapper_interruptible_get_max_ops(void);
+
+uint32_t psa_driver_wrapper_sign_hash_get_num_ops(
+    psa_sign_hash_interruptible_operation_t *operation);
+
+uint32_t psa_driver_wrapper_verify_hash_get_num_ops(
+    psa_verify_hash_interruptible_operation_t *operation);
+
+psa_status_t psa_driver_wrapper_sign_hash_start(
+    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 psa_driver_wrapper_sign_hash_complete(
+    psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature, size_t signature_size,
+    size_t *signature_length);
+
+psa_status_t psa_driver_wrapper_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *operation);
+
+psa_status_t psa_driver_wrapper_verify_hash_start(
+    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 psa_driver_wrapper_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *operation);
+
+psa_status_t psa_driver_wrapper_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *operation);
+
+/*
  * Key handling functions
  */
 
diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c
index c4ccefd..f70d804 100644
--- a/library/psa_crypto_ecp.c
+++ b/library/psa_crypto_ecp.c
@@ -404,6 +404,21 @@
     return mbedtls_to_psa_error(ret);
 }
 
+psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp)
+{
+    int ret = 0;
+
+    /* Check whether the public part is loaded. If not, load it. */
+    if (mbedtls_ecp_is_zero(&ecp->Q)) {
+        ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q,
+                              &ecp->d, &ecp->grp.G,
+                              mbedtls_psa_get_random,
+                              MBEDTLS_PSA_RANDOM_STATE);
+    }
+
+    return mbedtls_to_psa_error(ret);
+}
+
 psa_status_t mbedtls_psa_ecdsa_verify_hash(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer, size_t key_buffer_size,
@@ -412,7 +427,6 @@
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_keypair *ecp = NULL;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t curve_bytes;
     mbedtls_mpi r, s;
 
@@ -432,34 +446,39 @@
     mbedtls_mpi_init(&s);
 
     if (signature_length != 2 * curve_bytes) {
-        ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
+        status = PSA_ERROR_INVALID_SIGNATURE;
         goto cleanup;
     }
 
-    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r,
-                                            signature,
-                                            curve_bytes));
-    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&s,
-                                            signature + curve_bytes,
-                                            curve_bytes));
-
-    /* Check whether the public part is loaded. If not, load it. */
-    if (mbedtls_ecp_is_zero(&ecp->Q)) {
-        MBEDTLS_MPI_CHK(
-            mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
-                            mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE));
+    status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r,
+                                                          signature,
+                                                          curve_bytes));
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
     }
 
-    ret = mbedtls_ecdsa_verify(&ecp->grp, hash, hash_length,
-                               &ecp->Q, &r, &s);
+    status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s,
+                                                          signature + curve_bytes,
+                                                          curve_bytes));
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
 
+    status = mbedtls_psa_ecp_load_public_part(ecp);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash,
+                                                       hash_length, &ecp->Q,
+                                                       &r, &s));
 cleanup:
     mbedtls_mpi_free(&r);
     mbedtls_mpi_free(&s);
     mbedtls_ecp_keypair_free(ecp);
     mbedtls_free(ecp);
 
-    return mbedtls_to_psa_error(ret);
+    return status;
 }
 
 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
diff --git a/library/psa_crypto_ecp.h b/library/psa_crypto_ecp.h
index 71f9d6a..f4ad3d2 100644
--- a/library/psa_crypto_ecp.h
+++ b/library/psa_crypto_ecp.h
@@ -48,6 +48,15 @@
                                                  size_t data_length,
                                                  mbedtls_ecp_keypair **p_ecp);
 
+/** Load the public part of an internal ECP, if required.
+ *
+ * \param ecp               The ECP context to load the public part for.
+ *
+ * \return PSA_SUCCESS on success, otherwise an MPI error.
+ */
+
+psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp);
+
 /** Import an ECP key in binary format.
  *
  * \note The signature of this function is that of a PSA driver
@@ -70,9 +79,9 @@
  * \retval #PSA_SUCCESS  The ECP key was imported successfully.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The key data is not correctly formatted.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_ecp_import_key(
     const psa_key_attributes_t *attributes,
@@ -111,12 +120,12 @@
  *                              \p data
  *
  * \retval #PSA_SUCCESS  The ECP public key was exported successfully.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t mbedtls_psa_ecp_export_public_key(
     const psa_key_attributes_t *attributes,
@@ -166,17 +175,17 @@
  * \param[out] signature_length On success, the number of bytes
  *                              that make up the returned signature value.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \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 PSA_KEY_TYPE_ECC_KEY_PAIR, \c key_bits,
  *         \p alg) where \c key_bits is the bit-size of the ECC 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
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
  */
 psa_status_t mbedtls_psa_ecdsa_sign_hash(
     const psa_key_attributes_t *attributes,
@@ -209,9 +218,9 @@
  * \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
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t mbedtls_psa_ecdsa_verify_hash(
     const psa_key_attributes_t *attributes,
@@ -247,8 +256,8 @@
  *                                  up the returned shared secret.
  * \retval #PSA_SUCCESS
  *         Success. Shared secret successfully calculated.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p alg is not a key agreement algorithm, or
  *         \p private_key is not compatible with \p alg,
@@ -258,8 +267,8 @@
  *         \p shared_secret_size is too small
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not a supported key agreement algorithm.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_key_agreement_ecdh(
     const psa_key_attributes_t *attributes,
diff --git a/library/psa_crypto_hash.h b/library/psa_crypto_hash.h
index 63874e8..d6bbd3f 100644
--- a/library/psa_crypto_hash.h
+++ b/library/psa_crypto_hash.h
@@ -48,8 +48,8 @@
  *         \p alg is not supported
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         \p hash_size is too small
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_hash_compute(
     psa_algorithm_t alg,
@@ -88,8 +88,8 @@
  *         \p alg is not supported
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive).
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_hash_setup(
     mbedtls_psa_hash_operation_t *operation,
@@ -115,13 +115,13 @@
  * \param[in,out] target_operation  The operation object to set up.
  *                                  It must be initialized but not active.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The \p source_operation state is not valid (it must be active).
  * \retval #PSA_ERROR_BAD_STATE
  *         The \p target_operation state is not valid (it must be inactive).
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t mbedtls_psa_hash_clone(
     const mbedtls_psa_hash_operation_t *source_operation,
@@ -147,8 +147,8 @@
  *         Success.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active).
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_hash_update(
     mbedtls_psa_hash_operation_t *operation,
@@ -186,8 +186,8 @@
  *         The size of the \p hash buffer is too small. You can determine a
  *         sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg)
  *         where \c alg is the hash algorithm that is calculated.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_hash_finish(
     mbedtls_psa_hash_operation_t *operation,
@@ -216,8 +216,8 @@
  *
  * \param[in,out] operation     Initialized hash operation.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_hash_abort(
     mbedtls_psa_hash_operation_t *operation);
diff --git a/library/psa_crypto_mac.h b/library/psa_crypto_mac.h
index 21c4de6..4f8024a 100644
--- a/library/psa_crypto_mac.h
+++ b/library/psa_crypto_mac.h
@@ -52,8 +52,8 @@
  *         \p alg is not supported.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         \p mac_size is too small
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_mac_compute(
     const psa_key_attributes_t *attributes,
@@ -89,8 +89,8 @@
  *         Success.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive).
  */
@@ -124,8 +124,8 @@
  *         Success.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive).
  */
@@ -158,8 +158,8 @@
  *         Success.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active).
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_mac_update(
     mbedtls_psa_mac_operation_t *operation,
@@ -200,8 +200,8 @@
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p mac buffer is too small. A sufficient buffer size
  *         can be determined by calling PSA_MAC_LENGTH().
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_mac_sign_finish(
     mbedtls_psa_mac_operation_t *operation,
@@ -241,8 +241,8 @@
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be an active mac verify
  *         operation).
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_mac_verify_finish(
     mbedtls_psa_mac_operation_t *operation,
@@ -267,8 +267,8 @@
  *
  * \param[in,out] operation Initialized MAC operation.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_mac_abort(
     mbedtls_psa_mac_operation_t *operation);
diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h
index c3acdd0..bc24ef5 100644
--- a/library/psa_crypto_rsa.h
+++ b/library/psa_crypto_rsa.h
@@ -61,9 +61,9 @@
  * \retval #PSA_SUCCESS  The RSA key was imported successfully.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The key data is not correctly formatted.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
  */
 psa_status_t mbedtls_psa_rsa_import_key(
     const psa_key_attributes_t *attributes,
@@ -102,12 +102,12 @@
  *                              \p data.
  *
  * \retval #PSA_SUCCESS  The RSA public key was exported successfully.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t mbedtls_psa_rsa_export_public_key(
     const psa_key_attributes_t *attributes,
@@ -158,17 +158,17 @@
  * \param[out] signature_length On success, the number of bytes
  *                              that make up the returned signature value.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \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 PSA_KEY_TYPE_RSA_KEY_PAIR, \c key_bits,
  *         \p alg) where \c key_bits is the bit-size of the RSA 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
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
  */
 psa_status_t mbedtls_psa_rsa_sign_hash(
     const psa_key_attributes_t *attributes,
@@ -202,9 +202,9 @@
  * \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
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
  */
 psa_status_t mbedtls_psa_rsa_verify_hash(
     const psa_key_attributes_t *attributes,
@@ -237,20 +237,20 @@
  * \param[out] output_length    On success, the number of bytes
  *                              that make up the returned output.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small. You can
  *         determine a sufficient buffer size by calling
  *         #PSA_ASYMMETRIC_ENCRYPT_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_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -294,21 +294,21 @@
  * \param[out] output_length    On success, the number of bytes
  *                              that make up the returned output.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small. You can
  *         determine a sufficient buffer size by calling
  *         #PSA_ASYMMETRIC_DECRYPT_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_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
- * \retval #PSA_ERROR_INVALID_PADDING
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_INVALID_PADDING \emptydescription
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index ff8ccde..c8366ab 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -88,9 +88,9 @@
  *         due to a lack of empty key slot, or available memory.
  * \retval #PSA_ERROR_DOES_NOT_EXIST
  *         There is no key with key identifier \p key.
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
  */
 psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
                                        psa_key_slot_t **p_slot);
@@ -118,9 +118,9 @@
  *                               associated to the returned slot.
  * \param[out] p_slot            On success, a pointer to the slot.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_BAD_STATE
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE \emptydescription
  */
 psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id,
                                     psa_key_slot_t **p_slot);
@@ -195,8 +195,8 @@
  *                          storage, returns a pointer to the driver table
  *                          associated with the key's storage location.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
  */
 psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,
                                        psa_se_drv_table_entry_t **p_drv);
@@ -205,7 +205,7 @@
  *
  * \param[in] lifetime  The key lifetime attribute.
  *
- * \retval #PSA_SUCCESS
+ * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_NOT_SUPPORTED The key is persistent but persistent keys
  *             are not supported.
  */
diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c
index 8225014..a8ed937 100644
--- a/library/psa_crypto_storage.c
+++ b/library/psa_crypto_storage.c
@@ -79,11 +79,11 @@
  * \param[out] data         Buffer where the data is to be written.
  * \param data_size         Size of the \c data buffer in bytes.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
  */
 static psa_status_t psa_crypto_storage_load(
     const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size)
@@ -131,11 +131,11 @@
  * \param data_length   The number of bytes
  *                      that make up the data.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_ALREADY_EXISTS
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
  */
 static psa_status_t psa_crypto_storage_store(const mbedtls_svc_key_id_t key,
                                              const uint8_t *data,
@@ -205,10 +205,10 @@
  *                          is to be obtained.
  * \param[out] data_length  The number of bytes that make up the data.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
- * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
  */
 static psa_status_t psa_crypto_storage_get_data_length(
     const mbedtls_svc_key_id_t key,
diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h
index 8e108c5..04768f8 100644
--- a/library/psa_crypto_storage.h
+++ b/library/psa_crypto_storage.h
@@ -96,14 +96,14 @@
  * \param[in] data          Buffer containing the key data.
  * \param data_length       The number of bytes that make up the key data.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_ALREADY_EXISTS
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
  */
 psa_status_t psa_save_persistent_key(const psa_core_key_attributes_t *attr,
                                      const uint8_t *data,
@@ -129,11 +129,11 @@
  * \param[out] data         Pointer to an allocated key data buffer on return.
  * \param[out] data_length  The number of bytes that make up the key data.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_DOES_NOT_EXIST
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
  */
 psa_status_t psa_load_persistent_key(psa_core_key_attributes_t *attr,
                                      uint8_t **data,
@@ -148,7 +148,7 @@
  * \retval #PSA_SUCCESS
  *         The key was successfully removed,
  *         or the key did not exist.
- * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
  */
 psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key);
 
@@ -190,9 +190,9 @@
  * \param[out] attr            On success, the attribute structure is filled
  *                             with the loaded key metadata.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
  */
 psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data,
                                              size_t storage_data_length,
@@ -322,10 +322,10 @@
  * You may call this function multiple times during a transaction to
  * atomically update the transaction state.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_DATA_CORRUPT
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
  */
 psa_status_t psa_crypto_save_transaction(void);
 
@@ -339,9 +339,9 @@
  *         #psa_crypto_transaction.
  * \retval #PSA_ERROR_DOES_NOT_EXIST
  *         There is no ongoing transaction.
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_DATA_INVALID
- * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
  */
 psa_status_t psa_crypto_load_transaction(void);
 
@@ -380,8 +380,8 @@
  *
  * \retval #PSA_SUCCESS
  *         Success
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The entropy seed file already exists.
  */
diff --git a/library/ssl_client.c b/library/ssl_client.c
index 963f8bb..ea64b21 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -945,16 +945,29 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */
     {
 
-        mbedtls_ssl_add_hs_hdr_to_checksum(ssl, MBEDTLS_SSL_HS_CLIENT_HELLO,
-                                           msg_len);
-        ssl->handshake->update_checksum(ssl, buf, msg_len - binders_len);
+        ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl,
+                                                 MBEDTLS_SSL_HS_CLIENT_HELLO,
+                                                 msg_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_add_hs_hdr_to_checksum", ret);
+            return ret;
+        }
+        ret = ssl->handshake->update_checksum(ssl, buf, msg_len - binders_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+            return ret;
+        }
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
         if (binders_len > 0) {
             MBEDTLS_SSL_PROC_CHK(
                 mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext(
                     ssl, buf + msg_len - binders_len, buf + msg_len));
-            ssl->handshake->update_checksum(ssl, buf + msg_len - binders_len,
-                                            binders_len);
+            ret = ssl->handshake->update_checksum(ssl, buf + msg_len - binders_len,
+                                                  binders_len);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+                return ret;
+            }
         }
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
 
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 2668a05..7385c6e 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -705,9 +705,12 @@
 
     mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
 
-    void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
-    void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *);
-    void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
+    MBEDTLS_CHECK_RETURN_CRITICAL
+    int (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
+    MBEDTLS_CHECK_RETURN_CRITICAL
+    int (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *);
+    MBEDTLS_CHECK_RETURN_CRITICAL
+    int (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
     mbedtls_ssl_tls_prf_cb *tls_prf;
 
     /*
@@ -1317,7 +1320,8 @@
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl);
 
-void mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl);
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
 MBEDTLS_CHECK_RETURN_CRITICAL
@@ -1328,7 +1332,8 @@
 int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl);
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl);
-void mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl);
 
 /**
  * \brief       Update record layer
@@ -1461,14 +1466,16 @@
 /*
  * Update checksum of handshake messages.
  */
-void mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl,
-                                        unsigned hs_type,
-                                        unsigned char const *msg,
-                                        size_t msg_len);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl,
+                                       unsigned hs_type,
+                                       unsigned char const *msg,
+                                       size_t msg_len);
 
-void mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl,
-                                        unsigned hs_type,
-                                        size_t total_hs_len);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl,
+                                       unsigned hs_type,
+                                       size_t total_hs_len);
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 9bedc25..d26d950 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -2639,7 +2639,12 @@
 
         /* Update running hashes of handshake messages seen */
         if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST && update_checksum != 0) {
-            ssl->handshake->update_checksum(ssl, ssl->out_msg, ssl->out_msglen);
+            ret = ssl->handshake->update_checksum(ssl, ssl->out_msg,
+                                                  ssl->out_msglen);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+                return ret;
+            }
         }
     }
 
@@ -3067,12 +3072,17 @@
     return 0;
 }
 
-void mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl)
+int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl)
 {
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
 
     if (mbedtls_ssl_is_handshake_over(ssl) == 0 && hs != NULL) {
-        ssl->handshake->update_checksum(ssl, ssl->in_msg, ssl->in_hslen);
+        ret = ssl->handshake->update_checksum(ssl, ssl->in_msg, ssl->in_hslen);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+            return ret;
+        }
     }
 
     /* Handshake message is complete, increment counter */
@@ -3103,6 +3113,7 @@
         memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer));
     }
 #endif
+    return 0;
 }
 
 /*
@@ -3928,7 +3939,11 @@
 
         if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
             update_hs_digest == 1) {
-            mbedtls_ssl_update_handshake_status(ssl);
+            ret = mbedtls_ssl_update_handshake_status(ssl);
+            if (0 != ret) {
+                MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret);
+                return ret;
+            }
         }
     } else {
         MBEDTLS_SSL_DEBUG_MSG(2, ("reuse previously read message"));
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 86f5c0b..441089f 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -418,8 +418,8 @@
                           const char *label,
                           const unsigned char *random, size_t rlen,
                           unsigned char *dstbuf, size_t dlen);
-static void ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *);
-static void ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int);
+static int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *);
+static int ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int);
 
 #endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
 
@@ -430,8 +430,8 @@
                           const unsigned char *random, size_t rlen,
                           unsigned char *dstbuf, size_t dlen);
 
-static void ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *);
-static void ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int);
+static int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *);
+static int ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int);
 #endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
 
 static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
@@ -444,14 +444,14 @@
                                   size_t len);
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-static void ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t);
+static int ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t);
 
 #if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-static void ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t);
+static int ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t);
 #endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
 
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-static void ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t);
+static int ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t);
 #endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
 
 int  mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf,
@@ -788,9 +788,9 @@
     }
 }
 
-void mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl,
-                                        unsigned hs_type,
-                                        size_t total_hs_len)
+int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl,
+                                       unsigned hs_type,
+                                       size_t total_hs_len)
 {
     unsigned char hs_hdr[4];
 
@@ -800,84 +800,137 @@
     hs_hdr[2] = MBEDTLS_BYTE_1(total_hs_len);
     hs_hdr[3] = MBEDTLS_BYTE_0(total_hs_len);
 
-    ssl->handshake->update_checksum(ssl, hs_hdr, sizeof(hs_hdr));
+    return ssl->handshake->update_checksum(ssl, hs_hdr, sizeof(hs_hdr));
 }
 
-void mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl,
-                                        unsigned hs_type,
-                                        unsigned char const *msg,
-                                        size_t msg_len)
+int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl,
+                                       unsigned hs_type,
+                                       unsigned char const *msg,
+                                       size_t msg_len)
 {
-    mbedtls_ssl_add_hs_hdr_to_checksum(ssl, hs_type, msg_len);
-    ssl->handshake->update_checksum(ssl, msg, msg_len);
+    int ret;
+    ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, hs_type, msg_len);
+    if (ret != 0) {
+        return ret;
+    }
+    return ssl->handshake->update_checksum(ssl, msg, msg_len);
 }
 
-void mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl)
+int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl)
 {
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) || \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status;
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#endif
+#else /* SHA-256 or SHA-384 */
     ((void) ssl);
+#endif /* SHA-256 or SHA-384 */
 #if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort(&ssl->handshake->fin_sha256_psa);
-    psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256);
+    status = psa_hash_abort(&ssl->handshake->fin_sha256_psa);
+    if (status != PSA_SUCCESS) {
+        return mbedtls_md_error_from_psa(status);
+    }
+    status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256);
+    if (status != PSA_SUCCESS) {
+        return mbedtls_md_error_from_psa(status);
+    }
 #else
-    mbedtls_sha256_starts(&ssl->handshake->fin_sha256, 0);
+    ret = mbedtls_sha256_starts(&ssl->handshake->fin_sha256, 0);
+    if (ret != 0) {
+        return ret;
+    }
 #endif
 #endif
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort(&ssl->handshake->fin_sha384_psa);
-    psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384);
+    status = psa_hash_abort(&ssl->handshake->fin_sha384_psa);
+    if (status != PSA_SUCCESS) {
+        return mbedtls_md_error_from_psa(status);
+    }
+    status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384);
+    if (status != PSA_SUCCESS) {
+        return mbedtls_md_error_from_psa(status);
+    }
 #else
-    mbedtls_sha512_starts(&ssl->handshake->fin_sha384, 1);
+    ret = mbedtls_sha512_starts(&ssl->handshake->fin_sha384, 1);
+    if (ret != 0) {
+        return ret;
+    }
 #endif
 #endif
+    return 0;
 }
 
-static void ssl_update_checksum_start(mbedtls_ssl_context *ssl,
-                                      const unsigned char *buf, size_t len)
+static int ssl_update_checksum_start(mbedtls_ssl_context *ssl,
+                                     const unsigned char *buf, size_t len)
 {
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) || \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len);
+    psa_status_t status;
 #else
-    mbedtls_sha256_update(&ssl->handshake->fin_sha256, buf, len);
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #endif
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len);
-#else
-    mbedtls_sha512_update(&ssl->handshake->fin_sha384, buf, len);
-#endif
-#endif
-#if !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    (void) ssl;
+#else /* SHA-256 or SHA-384 */
+    ((void) ssl);
     (void) buf;
     (void) len;
+#endif /* SHA-256 or SHA-384 */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len);
+    if (status != PSA_SUCCESS) {
+        return mbedtls_md_error_from_psa(status);
+    }
+#else
+    ret = mbedtls_sha256_update(&ssl->handshake->fin_sha256, buf, len);
+    if (ret != 0) {
+        return ret;
+    }
 #endif
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len);
+    if (status != PSA_SUCCESS) {
+        return mbedtls_md_error_from_psa(status);
+    }
+#else
+    ret = mbedtls_sha512_update(&ssl->handshake->fin_sha384, buf, len);
+    if (ret != 0) {
+        return ret;
+    }
+#endif
+#endif
+    return 0;
 }
 
 #if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-static void ssl_update_checksum_sha256(mbedtls_ssl_context *ssl,
-                                       const unsigned char *buf, size_t len)
+static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl,
+                                      const unsigned char *buf, size_t len)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len);
+    return mbedtls_md_error_from_psa(psa_hash_update(
+                                         &ssl->handshake->fin_sha256_psa, buf, len));
 #else
-    mbedtls_sha256_update(&ssl->handshake->fin_sha256, buf, len);
+    return mbedtls_sha256_update(&ssl->handshake->fin_sha256, buf, len);
 #endif
 }
 #endif
 
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-static void ssl_update_checksum_sha384(mbedtls_ssl_context *ssl,
-                                       const unsigned char *buf, size_t len)
+static int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl,
+                                      const unsigned char *buf, size_t len)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len);
+    return mbedtls_md_error_from_psa(psa_hash_update(
+                                         &ssl->handshake->fin_sha384_psa, buf, len));
 #else
-    mbedtls_sha512_update(&ssl->handshake->fin_sha384, buf, len);
+    return mbedtls_sha512_update(&ssl->handshake->fin_sha384, buf, len);
 #endif
 }
 #endif
@@ -889,19 +942,15 @@
 #if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     handshake->fin_sha256_psa = psa_hash_operation_init();
-    psa_hash_setup(&handshake->fin_sha256_psa, PSA_ALG_SHA_256);
 #else
     mbedtls_sha256_init(&handshake->fin_sha256);
-    mbedtls_sha256_starts(&handshake->fin_sha256, 0);
 #endif
 #endif
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     handshake->fin_sha384_psa = psa_hash_operation_init();
-    psa_hash_setup(&handshake->fin_sha384_psa, PSA_ALG_SHA_384);
 #else
     mbedtls_sha512_init(&handshake->fin_sha384);
-    mbedtls_sha512_starts(&handshake->fin_sha384, 1);
 #endif
 #endif
 
@@ -971,6 +1020,8 @@
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_handshake_init(mbedtls_ssl_context *ssl)
 {
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
     /* Clear old handshake information if present */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     if (ssl->transform_negotiate) {
@@ -1038,6 +1089,13 @@
     mbedtls_ssl_transform_init(ssl->transform_negotiate);
 #endif
 
+    /* Setup handshake checksums */
+    ret = mbedtls_ssl_reset_checksum(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret);
+        return ret;
+    }
+
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
     defined(MBEDTLS_SSL_SRV_C) && \
     defined(MBEDTLS_SSL_SESSION_TICKETS)
@@ -6285,7 +6343,10 @@
     if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) {
         lbl  = "extended master secret";
         seed = session_hash;
-        handshake->calc_verify(ssl, session_hash, &seed_len);
+        ret = handshake->calc_verify(ssl, session_hash, &seed_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret);
+        }
 
         MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret",
                               session_hash, seed_len);
@@ -6513,9 +6574,9 @@
 }
 
 #if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-void ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl,
-                                unsigned char *hash,
-                                size_t *hlen)
+int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl,
+                               unsigned char *hash,
+                               size_t *hlen)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     size_t hash_size;
@@ -6525,20 +6586,23 @@
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify sha256"));
     status = psa_hash_clone(&ssl->handshake->fin_sha256_psa, &sha256_psa);
     if (status != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash clone failed"));
-        return;
+        goto exit;
     }
 
     status = psa_hash_finish(&sha256_psa, hash, 32, &hash_size);
     if (status != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash finish failed"));
-        return;
+        goto exit;
     }
 
     *hlen = 32;
     MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen);
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify"));
+
+exit:
+    psa_hash_abort(&sha256_psa);
+    return mbedtls_md_error_from_psa(status);
 #else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_sha256_context sha256;
 
     mbedtls_sha256_init(&sha256);
@@ -6546,23 +6610,28 @@
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha256"));
 
     mbedtls_sha256_clone(&sha256, &ssl->handshake->fin_sha256);
-    mbedtls_sha256_finish(&sha256, hash);
+
+    ret = mbedtls_sha256_finish(&sha256, hash);
+    if (ret != 0) {
+        goto exit;
+    }
 
     *hlen = 32;
 
     MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen);
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify"));
 
+exit:
     mbedtls_sha256_free(&sha256);
+    return ret;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
-    return;
 }
 #endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-void ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl,
-                                unsigned char *hash,
-                                size_t *hlen)
+int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl,
+                               unsigned char *hash,
+                               size_t *hlen)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     size_t hash_size;
@@ -6572,20 +6641,23 @@
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify sha384"));
     status = psa_hash_clone(&ssl->handshake->fin_sha384_psa, &sha384_psa);
     if (status != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash clone failed"));
-        return;
+        goto exit;
     }
 
     status = psa_hash_finish(&sha384_psa, hash, 48, &hash_size);
     if (status != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash finish failed"));
-        return;
+        goto exit;
     }
 
     *hlen = 48;
     MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen);
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify"));
+
+exit:
+    psa_hash_abort(&sha384_psa);
+    return mbedtls_md_error_from_psa(status);
 #else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_sha512_context sha512;
 
     mbedtls_sha512_init(&sha512);
@@ -6593,16 +6665,21 @@
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha384"));
 
     mbedtls_sha512_clone(&sha512, &ssl->handshake->fin_sha384);
-    mbedtls_sha512_finish(&sha512, hash);
+
+    ret = mbedtls_sha512_finish(&sha512, hash);
+    if (ret != 0) {
+        goto exit;
+    }
 
     *hlen = 48;
 
     MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen);
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify"));
 
+exit:
     mbedtls_sha512_free(&sha512);
+    return ret;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
-    return;
 }
 #endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
@@ -7545,7 +7622,7 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 #if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-static void ssl_calc_finished_tls_sha256(
+static int ssl_calc_finished_tls_sha256(
     mbedtls_ssl_context *ssl, unsigned char *buf, int from)
 {
     int len = 12;
@@ -7556,6 +7633,7 @@
     psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT;
     psa_status_t status;
 #else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_sha256_context sha256;
 #endif
 
@@ -7575,14 +7653,12 @@
 
     status = psa_hash_clone(&ssl->handshake->fin_sha256_psa, &sha256_psa);
     if (status != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash clone failed"));
-        return;
+        goto exit;
     }
 
     status = psa_hash_finish(&sha256_psa, padbuf, sizeof(padbuf), &hash_size);
     if (status != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash finish failed"));
-        return;
+        goto exit;
     }
     MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 32);
 #else
@@ -7604,8 +7680,10 @@
                           sha256.state, sizeof(sha256.state));
 #endif
 
-    mbedtls_sha256_finish(&sha256, padbuf);
-    mbedtls_sha256_free(&sha256);
+    ret = mbedtls_sha256_finish(&sha256, padbuf);
+    if (ret != 0) {
+        goto exit;
+    }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
     ssl->handshake->tls_prf(session->master, 48, sender,
@@ -7616,12 +7694,21 @@
     mbedtls_platform_zeroize(padbuf, sizeof(padbuf));
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc  finished"));
+
+exit:
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_hash_abort(&sha256_psa);
+    return mbedtls_md_error_from_psa(status);
+#else
+    mbedtls_sha256_free(&sha256);
+    return ret;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
 #endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
 
 
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-static void ssl_calc_finished_tls_sha384(
+static int ssl_calc_finished_tls_sha384(
     mbedtls_ssl_context *ssl, unsigned char *buf, int from)
 {
     int len = 12;
@@ -7632,6 +7719,7 @@
     psa_hash_operation_t sha384_psa = PSA_HASH_OPERATION_INIT;
     psa_status_t status;
 #else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_sha512_context sha512;
 #endif
 
@@ -7651,14 +7739,12 @@
 
     status = psa_hash_clone(&ssl->handshake->fin_sha384_psa, &sha384_psa);
     if (status != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash clone failed"));
-        return;
+        goto exit;
     }
 
     status = psa_hash_finish(&sha384_psa, padbuf, sizeof(padbuf), &hash_size);
     if (status != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash finish failed"));
-        return;
+        goto exit;
     }
     MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 48);
 #else
@@ -7678,9 +7764,10 @@
     MBEDTLS_SSL_DEBUG_BUF(4, "finished sha512 state", (unsigned char *)
                           sha512.state, sizeof(sha512.state));
 #endif
-    mbedtls_sha512_finish(&sha512, padbuf);
-
-    mbedtls_sha512_free(&sha512);
+    ret = mbedtls_sha512_finish(&sha512, padbuf);
+    if (ret != 0) {
+        goto exit;
+    }
 #endif
 
     ssl->handshake->tls_prf(session->master, 48, sender,
@@ -7691,6 +7778,15 @@
     mbedtls_platform_zeroize(padbuf, sizeof(padbuf));
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc  finished"));
+
+exit:
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_hash_abort(&sha384_psa);
+    return mbedtls_md_error_from_psa(status);
+#else
+    mbedtls_sha512_free(&sha512);
+    return ret;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
 #endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
 
@@ -7787,7 +7883,10 @@
 
     mbedtls_ssl_update_out_pointers(ssl, ssl->transform_negotiate);
 
-    ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint);
+    ret = ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret);
+    }
 
     /*
      * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites
@@ -7897,7 +7996,10 @@
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished"));
 
-    ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1);
+    ret = ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret);
+    }
 
     if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index b427ae9..fc99fde 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -1090,6 +1090,7 @@
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl)
 {
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
     const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
     uint16_t dtls_legacy_version;
 
@@ -1160,7 +1161,11 @@
 
     /* Start over at ClientHello */
     ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
-    mbedtls_ssl_reset_checksum(ssl);
+    ret = mbedtls_ssl_reset_checksum(ssl);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_reset_checksum"), ret);
+        return ret;
+    }
 
     mbedtls_ssl_recv_flight_completed(ssl);
 
@@ -3283,7 +3288,11 @@
 sign:
 #endif
 
-    ssl->handshake->calc_verify(ssl, hash, &hashlen);
+    ret = ssl->handshake->calc_verify(ssl, hash, &hashlen);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret);
+        return ret;
+    }
 
     /*
      * digitally-signed struct {
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index 9298292..d5c8b7c 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -1020,7 +1020,11 @@
 
     MBEDTLS_SSL_DEBUG_BUF(4, "record contents", buf, msg_len);
 
-    ssl->handshake->update_checksum(ssl, buf, msg_len);
+    ret = ssl->handshake->update_checksum(ssl, buf, msg_len);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+        return ret;
+    }
 
     /*
      * Handshake layer:
@@ -4129,7 +4133,11 @@
     /* Calculate hash and verify signature */
     {
         size_t dummy_hlen;
-        ssl->handshake->calc_verify(ssl, hash, &dummy_hlen);
+        ret = ssl->handshake->calc_verify(ssl, hash, &dummy_hlen);
+        if (0 != ret) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret);
+            return ret;
+        }
     }
 
     if ((ret = mbedtls_pk_verify(peer_pk,
@@ -4139,7 +4147,11 @@
         return ret;
     }
 
-    mbedtls_ssl_update_handshake_status(ssl);
+    ret = mbedtls_ssl_update_handshake_status(ssl);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret);
+        return ret;
+    }
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify"));
 
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 1e79afa..0dd762e 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -1489,8 +1489,9 @@
 
         ssl->keep_current_message = 1;
         ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
-        mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_SERVER_HELLO,
-                                           buf, (size_t) (end - buf));
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                                MBEDTLS_SSL_HS_SERVER_HELLO,
+                                                                buf, (size_t) (end - buf)));
 
         if (mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) {
             ret = ssl_tls13_reset_key_share(ssl);
@@ -2056,8 +2057,9 @@
         MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_reset_transcript_for_hrr(ssl));
     }
 
-    mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_SERVER_HELLO,
-                                       buf, buf_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_SERVER_HELLO, buf,
+                                                            buf_len));
 
     if (is_hrr) {
         MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_hrr(ssl));
@@ -2214,8 +2216,9 @@
     }
 #endif
 
-    mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
-                                       buf, buf_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                                                            buf, buf_len));
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
     if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {
@@ -2259,8 +2262,8 @@
                              ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA,
                              &buf, &buf_len));
 
-    mbedtls_ssl_add_hs_hdr_to_checksum(
-        ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 0);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_hdr_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 0));
 
     MBEDTLS_SSL_PROC_CHK(
         mbedtls_ssl_finish_handshake_msg(ssl, buf_len, 0));
@@ -2458,8 +2461,9 @@
         MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request(ssl,
                                                                  buf, buf + buf_len));
 
-        mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
-                                           buf, buf_len);
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                                MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                                                                buf, buf_len));
     } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) {
         ret = 0;
     } else {
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 4fb73f9..f607e36 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -322,8 +322,9 @@
                                                             buf + buf_len, verify_buffer,
                                                             verify_buffer_len));
 
-    mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,
-                                       buf, buf_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,
+                                                            buf, buf_len));
 
 cleanup:
 
@@ -752,8 +753,9 @@
     /* Validate the certificate chain and set the verification results. */
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_validate_certificate(ssl));
 
-    mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_CERTIFICATE,
-                                       buf, buf_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_CERTIFICATE, buf,
+                                                            buf_len));
 
 cleanup:
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
@@ -868,8 +870,9 @@
                                                           buf + buf_len,
                                                           &msg_len));
 
-    mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_CERTIFICATE,
-                                       buf, msg_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_CERTIFICATE, buf,
+                                                            msg_len));
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                              ssl, buf_len, msg_len));
@@ -1070,8 +1073,9 @@
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_verify_body(
                              ssl, buf, buf + buf_len, &msg_len));
 
-    mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,
-                                       buf, msg_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, buf,
+                                                            msg_len));
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                              ssl, buf_len, msg_len));
@@ -1171,8 +1175,8 @@
 
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_finished_message(ssl, buf, buf + buf_len));
 
-    mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_FINISHED,
-                                       buf, buf_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_FINISHED, buf, buf_len));
 
 cleanup:
 
@@ -1248,8 +1252,8 @@
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_finished_message_body(
                              ssl, buf, buf + buf_len, &msg_len));
 
-    mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_FINISHED,
-                                       buf, msg_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_FINISHED, buf, msg_len));
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                              ssl, buf_len, msg_len));
@@ -1388,7 +1392,7 @@
                                                PSA_HASH_MAX_SIZE,
                                                &hash_len);
     if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(4, "mbedtls_ssl_get_handshake_transcript", ret);
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret);
         return ret;
     }
 
@@ -1399,37 +1403,20 @@
 
     hash_len += 4;
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    if (ciphersuite_info->mac == MBEDTLS_MD_SHA256) {
-        MBEDTLS_SSL_DEBUG_BUF(4, "Truncated SHA-256 handshake transcript",
-                              hash_transcript, hash_len);
+    MBEDTLS_SSL_DEBUG_BUF(4, "Truncated handshake transcript",
+                          hash_transcript, hash_len);
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        psa_hash_abort(&ssl->handshake->fin_sha256_psa);
-        psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256);
-#else
-        mbedtls_sha256_starts(&ssl->handshake->fin_sha256, 0);
-#endif
+    /* Reset running hash and replace it with a hash of the transcript */
+    ret = mbedtls_ssl_reset_checksum(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret);
+        return ret;
     }
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) {
-        MBEDTLS_SSL_DEBUG_BUF(4, "Truncated SHA-384 handshake transcript",
-                              hash_transcript, hash_len);
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        psa_hash_abort(&ssl->handshake->fin_sha384_psa);
-        psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384);
-#else
-        mbedtls_sha512_starts(&ssl->handshake->fin_sha384, 1);
-#endif
+    ret = ssl->handshake->update_checksum(ssl, hash_transcript, hash_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+        return ret;
     }
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) || \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    ssl->handshake->update_checksum(ssl, hash_transcript, hash_len);
-#endif \
-    /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA || MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
     return ret;
 }
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 81c289a..6b1c4c5 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -486,6 +486,7 @@
                                               const unsigned char *ciphersuites,
                                               const unsigned char *ciphersuites_end)
 {
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned char *identities = pre_shared_key_ext;
     const unsigned char *p_identity_len;
     size_t identities_len;
@@ -521,8 +522,12 @@
     MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, pre_shared_key_ext_end, binders_len);
     binders_end = p_binder_len + binders_len;
 
-    ssl->handshake->update_checksum(ssl, pre_shared_key_ext,
-                                    identities_end - pre_shared_key_ext);
+    ret = ssl->handshake->update_checksum(ssl, pre_shared_key_ext,
+                                          identities_end - pre_shared_key_ext);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+        return ret;
+    }
 
     while (p_identity_len < identities_end && p_binder_len < binders_end) {
         const unsigned char *identity;
@@ -530,7 +535,6 @@
         uint32_t obfuscated_ticket_age;
         const unsigned char *binder;
         size_t binder_len;
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         int psk_type;
         uint16_t cipher_suite;
         const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
@@ -642,9 +646,13 @@
     }
 
     /* Update the handshake transcript with the binder list. */
-    ssl->handshake->update_checksum(ssl,
-                                    identities_end,
-                                    (size_t) (binders_end - identities_end));
+    ret = ssl->handshake->update_checksum(ssl,
+                                          identities_end,
+                                          (size_t) (binders_end - identities_end));
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+        return ret;
+    }
     if (matched_identity == -1) {
         MBEDTLS_SSL_DEBUG_MSG(3, ("No matched PSK or ticket."));
         return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
@@ -1590,9 +1598,13 @@
     MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CLIENT_HELLO,
                            handshake->received_extensions);
 
-    mbedtls_ssl_add_hs_hdr_to_checksum(ssl,
-                                       MBEDTLS_SSL_HS_CLIENT_HELLO,
-                                       p - buf);
+    ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl,
+                                             MBEDTLS_SSL_HS_CLIENT_HELLO,
+                                             p - buf);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_add_hs_hdr_to_checksum"), ret);
+        return ret;
+    }
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
     /* Update checksum with either
@@ -1603,8 +1615,12 @@
     if (mbedtls_ssl_tls13_some_psk_enabled(ssl) &&
         mbedtls_ssl_conf_tls13_some_psk_enabled(ssl) &&
         (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY))) {
-        handshake->update_checksum(ssl, buf,
-                                   pre_shared_key_ext - buf);
+        ret = handshake->update_checksum(ssl, buf,
+                                         pre_shared_key_ext - buf);
+        if (0 != ret) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+            return ret;
+        }
         ret = ssl_tls13_parse_pre_shared_key_ext(ssl,
                                                  pre_shared_key_ext,
                                                  pre_shared_key_ext_end,
@@ -1620,7 +1636,11 @@
     } else
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
     {
-        handshake->update_checksum(ssl, buf, p - buf);
+        ret = handshake->update_checksum(ssl, buf, p - buf);
+        if (0 != ret) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+            return ret;
+        }
     }
 
     ret = ssl_tls13_determine_key_exchange_mode(ssl);
@@ -2134,8 +2154,8 @@
                                                            &msg_len,
                                                            0));
 
-    mbedtls_ssl_add_hs_msg_to_checksum(
-        ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len));
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                              ssl, buf_len, msg_len));
@@ -2207,8 +2227,8 @@
                                                            buf + buf_len,
                                                            &msg_len,
                                                            1));
-    mbedtls_ssl_add_hs_msg_to_checksum(
-        ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len));
 
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len,
@@ -2306,8 +2326,8 @@
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_encrypted_extensions_body(
                              ssl, buf, buf + buf_len, &msg_len));
 
-    mbedtls_ssl_add_hs_msg_to_checksum(
-        ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, msg_len);
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, msg_len));
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                              ssl, buf_len, msg_len));
@@ -2439,8 +2459,8 @@
         MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_request_body(
                                  ssl, buf, buf + buf_len, &msg_len));
 
-        mbedtls_ssl_add_hs_msg_to_checksum(
-            ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, buf, msg_len);
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, buf, msg_len));
 
         MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                                  ssl, buf_len, msg_len));
diff --git a/scripts/code_style.py b/scripts/code_style.py
index dd8305f..c31fb29 100755
--- a/scripts/code_style.py
+++ b/scripts/code_style.py
@@ -33,6 +33,14 @@
 def print_err(*args):
     print("Error: ", *args, file=sys.stderr)
 
+# Print the file names that will be skipped and the help message
+def print_skip(files_to_skip):
+    print()
+    print(*files_to_skip, sep=", SKIP\n", end=", SKIP\n")
+    print("Warning: The listed files will be skipped because\n"
+          "they are not known to git.")
+    print()
+
 # Match FILENAME(s) in "check SCRIPT (FILENAME...)"
 CHECK_CALL_RE = re.compile(r"\n\s*check\s+[^\s#$&*?;|]+([^\n#$&*?;|]+)",
                            re.ASCII)
@@ -174,22 +182,27 @@
     parser.add_argument('-f', '--fix', action='store_true',
                         help=('modify source files to fix the code style '
                               '(default: print diff, do not modify files)'))
-    # --files is almost useless: it only matters if there are no files
+    # --subset is almost useless: it only matters if there are no files
     # ('code_style.py' without arguments checks all files known to Git,
-    # 'code_style.py --files' does nothing). In particular,
-    # 'code_style.py --fix --files ...' is intended as a stable ("porcelain")
+    # 'code_style.py --subset' does nothing). In particular,
+    # 'code_style.py --fix --subset ...' is intended as a stable ("porcelain")
     # way to restyle a possibly empty set of files.
-    parser.add_argument('--files', action='store_true',
+    parser.add_argument('--subset', action='store_true',
                         help='only check the specified files (default with non-option arguments)')
     parser.add_argument('operands', nargs='*', metavar='FILE',
-                        help='files to check (if none: check files that are known to git)')
+                        help='files to check (files MUST be known to git, if none: check all)')
 
     args = parser.parse_args()
 
-    if args.files or args.operands:
-        src_files = args.operands
+    covered = frozenset(get_src_files())
+    # We only check files that are known to git
+    if args.subset or args.operands:
+        src_files = [f for f in args.operands if f in covered]
+        skip_src_files = [f for f in args.operands if f not in covered]
+        if skip_src_files:
+            print_skip(skip_src_files)
     else:
-        src_files = get_src_files()
+        src_files = list(covered)
 
     if args.fix:
         # Fix mode
diff --git a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
index bdf3315..0f42b8c 100644
--- a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
+++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
@@ -433,6 +433,269 @@
     }
 }
 
+void psa_driver_wrapper_interruptible_set_max_ops( uint32_t max_ops )
+{
+    /* TODO - dispatch to drivers dynamically registered for this
+     * service when registering is implemented. For now, fall
+     * through to internal implementation. */
+
+    mbedtls_psa_interruptible_set_max_ops( max_ops );
+}
+
+uint32_t psa_driver_wrapper_interruptible_get_max_ops( void )
+{
+    /* TODO - dispatch to drivers dynamically registered for this
+     * service when registering is implemented. For now, fall
+     * through to internal implementation. */
+
+    return mbedtls_psa_interruptible_get_max_ops( );
+}
+
+uint32_t psa_driver_wrapper_sign_hash_get_num_ops(
+    psa_sign_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        /* If uninitialised, return 0, as no work can have been done. */
+        case 0:
+            return 0;
+
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return(mbedtls_psa_sign_hash_get_num_ops(&operation->ctx.mbedtls_ctx));
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+uint32_t psa_driver_wrapper_verify_hash_get_num_ops(
+    psa_verify_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        /* If uninitialised, return 0, as no work can have been done. */
+        case 0:
+            return 0;
+
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return (mbedtls_psa_verify_hash_get_num_ops(&operation->ctx.mbedtls_ctx));
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_sign_hash_start(
+    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;
+    psa_key_location_t location =
+                                  PSA_KEY_LIFETIME_GET_LOCATION(
+                                                    attributes->core.lifetime );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+
+            /* Add test driver tests here */
+
+            /* Declared with fallback == true */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+            return( mbedtls_psa_sign_hash_start( &operation->ctx.mbedtls_ctx,
+                                                 attributes,
+                                                 key_buffer, key_buffer_size,
+                                                 alg, hash, hash_length ) );
+            break;
+
+            /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            ( void ) status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+
+    ( void ) operation;
+    ( void ) key_buffer;
+    ( void ) key_buffer_size;
+    ( void ) alg;
+    ( void ) hash;
+    ( void ) hash_length;
+
+        return( status );
+}
+
+psa_status_t psa_driver_wrapper_sign_hash_complete(
+    psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature, size_t signature_size,
+    size_t *signature_length )
+{
+    switch( operation->id )
+    {
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_sign_hash_complete( &operation->ctx.mbedtls_ctx,
+                                                    signature, signature_size,
+                                                    signature_length ) );
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    ( void ) signature;
+    ( void ) signature_size;
+    ( void ) signature_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_sign_hash_abort( &operation->ctx.mbedtls_ctx ) );
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_verify_hash_start(
+    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;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
+                                                    attributes->core.lifetime );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+
+            /* Add test driver tests here */
+
+            /* Declared with fallback == true */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+            return( mbedtls_psa_verify_hash_start( &operation->ctx.mbedtls_ctx,
+                                                   attributes,
+                                                   key_buffer, key_buffer_size,
+                                                   alg, hash, hash_length,
+                                                   signature, signature_length
+                                                   ) );
+            break;
+
+            /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            ( void ) status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+
+    ( void ) operation;
+    ( void ) key_buffer;
+    ( void ) key_buffer_size;
+    ( void ) alg;
+    ( void ) hash;
+    ( void ) hash_length;
+    ( void ) signature;
+    ( void ) signature_length;
+
+    return( status );
+}
+
+psa_status_t psa_driver_wrapper_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_verify_hash_complete(
+                                                     &operation->ctx.mbedtls_ctx
+                                                     ) );
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_verify_hash_abort( &operation->ctx.mbedtls_ctx
+                                                 ) );
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
 /** Calculate the key buffer size required to store the key material of a key
  *  associated with an opaque driver from input key data.
  *
@@ -441,9 +704,9 @@
  * \param[in] data_length       The input data length.
  * \param[out] key_buffer_size  Minimum buffer size to contain the key material.
  *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
  */
 psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data(
     const psa_key_attributes_t *attributes,
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 01b46f1..db16ab7 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -1278,6 +1278,10 @@
 	echo -e "Hello\xd" > $@
 all_final += $(pkcs7_test_file)
 
+pkcs7_zerolendata.bin:
+	printf '' > $@
+all_final += pkcs7_zerolendata.bin
+
 pkcs7_data_1.bin:
 	echo -e "2\xd" > $@
 all_final += pkcs7_data_1.bin
@@ -1311,6 +1315,11 @@
 	$(OPENSSL) x509 -in pkcs7-rsa-sha256-2.crt -out $@ -outform DER
 all_final += pkcs7-rsa-sha256-2.der
 
+# pkcs7 signature file over zero-len data
+pkcs7_zerolendata_detached.der: pkcs7_zerolendata.bin pkcs7-rsa-sha256-1.key pkcs7-rsa-sha256-1.crt
+	$(OPENSSL) smime -sign -md sha256 -nocerts -noattr -in pkcs7_zerolendata.bin -inkey pkcs7-rsa-sha256-1.key -outform DER -binary -signer pkcs7-rsa-sha256-1.crt -out pkcs7_zerolendata_detached.der
+all_final += pkcs7_zerolendata_detached.der
+
 # pkcs7 signature file with CERT
 pkcs7_data_cert_signed_sha256.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
 	$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
diff --git a/tests/data_files/pkcs7_zerolendata.bin b/tests/data_files/pkcs7_zerolendata.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/data_files/pkcs7_zerolendata.bin
diff --git a/tests/data_files/pkcs7_zerolendata_detached.der b/tests/data_files/pkcs7_zerolendata_detached.der
new file mode 100644
index 0000000..2a389ab
--- /dev/null
+++ b/tests/data_files/pkcs7_zerolendata_detached.der
Binary files differ
diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function
index 14dc8ae..a2bf396 100644
--- a/tests/suites/test_suite_constant_time.function
+++ b/tests/suites/test_suite_constant_time.function
@@ -18,7 +18,7 @@
 /* BEGIN_CASE */
 void mbedtls_ct_memcmp_null()
 {
-    uint32_t x;
+    uint32_t x = 0;
     TEST_ASSERT(mbedtls_ct_memcmp(&x, NULL, 0) == 0);
     TEST_ASSERT(mbedtls_ct_memcmp(NULL, &x, 0) == 0);
     TEST_ASSERT(mbedtls_ct_memcmp(NULL, NULL, 0) == 0);
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index 9a13793..3fbad92 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -1038,3 +1038,115 @@
 ECP check order for CURVE448
 depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
 ecp_check_order:MBEDTLS_ECP_DP_CURVE448:"3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3"
+
+ecp_setup #1 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_SECP192R1)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_mod_setup:"fffffffffffffffffffffffffffffffeffffffffffffffff":MBEDTLS_ECP_DP_SECP192R1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #2 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_SECP224R1)
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecp_mod_setup:"00000000ffffffffffffffffffffffffffffffff000000000000000000000001":MBEDTLS_ECP_DP_SECP224R1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #3 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_SECP256R1)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_mod_setup:"ffffffff00000001000000000000000000000000ffffffffffffffffffffffff":MBEDTLS_ECP_DP_SECP256R1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #4 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_SECP384R1)
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_mod_setup:"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff":MBEDTLS_ECP_DP_SECP384R1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #5 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_SECP521R1)
+depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+ecp_mod_setup:"1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":MBEDTLS_ECP_DP_SECP521R1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #6 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_BP256R1)
+depends_on:MBEDTLS_ECP_DP_BP256R1_ENABLED
+ecp_mod_setup:"a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377":MBEDTLS_ECP_DP_BP256R1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #7 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_BP384R1)
+depends_on:MBEDTLS_ECP_DP_BP384R1_ENABLED
+ecp_mod_setup:"8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53":MBEDTLS_ECP_DP_BP384R1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #8 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_BP512R1)
+depends_on:MBEDTLS_ECP_DP_BP512R1_ENABLED
+ecp_mod_setup:"aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3":MBEDTLS_ECP_DP_BP512R1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #9 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_CURVE25519)
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_mod_setup:"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed":MBEDTLS_ECP_DP_CURVE25519:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #10 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_SECP192K1)
+depends_on:MBEDTLS_ECP_DP_SECP192K1_ENABLED
+ecp_mod_setup:"fffffffffffffffffffffffffffffffffffffffeffffee37":MBEDTLS_ECP_DP_SECP192K1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #11 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_SECP224K1)
+depends_on:MBEDTLS_ECP_DP_SECP224K1_ENABLED
+ecp_mod_setup:"fffffffffffffffffffffffffffffffffffffffffffffffeffffe56d":MBEDTLS_ECP_DP_SECP224K1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #12 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_SECP256K1)
+depends_on:MBEDTLS_ECP_DP_SECP256K1_ENABLED
+ecp_mod_setup:"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f":MBEDTLS_ECP_DP_SECP256K1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #13 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_CURVE448)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_mod_setup:"000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff":MBEDTLS_ECP_DP_CURVE448:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #14 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_SECP192R1)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_mod_setup:"ffffffffffffffffffffffff99def836146bc9b1b4d22831":MBEDTLS_ECP_DP_SECP192R1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #15 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_SECP224R1)
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecp_mod_setup:"ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d":MBEDTLS_ECP_DP_SECP224R1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #16 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_SECP256R1)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_mod_setup:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551":MBEDTLS_ECP_DP_SECP256R1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #17 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_SECP384R1)
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_mod_setup:"ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973":MBEDTLS_ECP_DP_SECP384R1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #18 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_SECP521R1)
+depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+ecp_mod_setup:"1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409":MBEDTLS_ECP_DP_SECP521R1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #19 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_BP256R1)
+depends_on:MBEDTLS_ECP_DP_BP256R1_ENABLED
+ecp_mod_setup:"a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7":MBEDTLS_ECP_DP_BP256R1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #20 MBEDTLS_ECP_MOD_COORDINATE(MBEDTLS_ECP_DP_BP384R1)
+depends_on:MBEDTLS_ECP_DP_BP384R1_ENABLED
+ecp_mod_setup:"8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53":MBEDTLS_ECP_DP_BP384R1:MBEDTLS_ECP_MOD_COORDINATE:0
+
+ecp_setup #21 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_BP512R1)
+depends_on:MBEDTLS_ECP_DP_BP512R1_ENABLED
+ecp_mod_setup:"aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069":MBEDTLS_ECP_DP_BP512R1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #22 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_CURVE25519)
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_mod_setup:"1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed":MBEDTLS_ECP_DP_CURVE25519:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #23 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_SECP192K1)
+depends_on:MBEDTLS_ECP_DP_SECP192K1_ENABLED
+ecp_mod_setup:"fffffffffffffffffffffffe26f2fc170f69466a74defd8d":MBEDTLS_ECP_DP_SECP192K1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #24 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_SECP224K1)
+depends_on:MBEDTLS_ECP_DP_SECP224K1_ENABLED
+ecp_mod_setup:"000000010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7":MBEDTLS_ECP_DP_SECP224K1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #25 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_SECP256K1)
+depends_on:MBEDTLS_ECP_DP_SECP256K1_ENABLED
+ecp_mod_setup:"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141":MBEDTLS_ECP_DP_SECP256K1:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup #26 MBEDTLS_ECP_MOD_SCALAR(MBEDTLS_ECP_DP_CURVE448)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_mod_setup:"0000000000000003fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3":MBEDTLS_ECP_DP_CURVE448:MBEDTLS_ECP_MOD_SCALAR:0
+
+ecp_setup_negative_test #27 Invalid Moduli Type
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_mod_setup:"fffffffffffffffffffffffe26f2fc17f69466a74defd8d":MBEDTLS_ECP_DP_CURVE448:MBEDTLS_ECP_MOD_NONE:MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ecp_setup_negative_test #28 Invalid Curve Type
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_mod_setup:"fffffffffffffffffffffffe26f2fc17f69466a74defd8d":MBEDTLS_ECP_DP_NONE:MBEDTLS_ECP_MOD_SCALAR:MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 4e74d9b..96537c2 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -1,5 +1,6 @@
 /* BEGIN_HEADER */
 #include "mbedtls/ecp.h"
+#include "ecp_invasive.h"
 #include "mbedtls/ecdsa.h"
 #include "mbedtls/ecdh.h"
 
@@ -1387,3 +1388,43 @@
     mbedtls_free(N);
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void ecp_mod_setup(char *input_A, int id, int ctype, int iret)
+{
+    int ret;
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_modulus_init(&m);
+    mbedtls_mpi_uint *p = NULL;
+    size_t p_limbs;
+    size_t bytes;
+
+    TEST_EQUAL(mbedtls_test_read_mpi_core(&p, &p_limbs, input_A), 0);
+
+    ret = mbedtls_ecp_modulus_setup(&m, id, ctype);
+    TEST_EQUAL(ret, iret);
+
+    if (ret == 0) {
+
+        /* Test for limb sizes */
+        TEST_EQUAL(m.limbs, p_limbs);
+        bytes = p_limbs * sizeof(mbedtls_mpi_uint);
+
+        /* Test for validity of moduli by the presence of Montgomery consts */
+
+        TEST_ASSERT(m.rep.mont.mm != 0);
+        TEST_ASSERT(m.rep.mont.rr != NULL);
+
+
+        /* Compare output byte-by-byte */
+        ASSERT_COMPARE(p, bytes, m.p, bytes);
+
+        /* Test for user free-ing allocated memory */
+        mbedtls_mpi_mod_modulus_free(&m);
+    }
+
+exit:
+    mbedtls_mpi_mod_modulus_free(&m);
+    mbedtls_free(p);
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_oid.data b/tests/suites/test_suite_oid.data
index 1738841..b9fa654 100644
--- a/tests/suites/test_suite_oid.data
+++ b/tests/suites/test_suite_oid.data
@@ -89,3 +89,33 @@
 OID hash id - invalid oid
 oid_get_md_alg_id:"2B864886f70d0204":-1
 
+OID get numeric string - hardware module name
+oid_get_numeric_string:"2B06010505070804":0:"1.3.6.1.5.5.7.8.4"
+
+OID get numeric string - multi-byte subidentifier
+oid_get_numeric_string:"29903C":0:"1.1.2108"
+
+OID get numeric string - second component greater than 39
+oid_get_numeric_string:"81010000863A00":0:"2.49.0.0.826.0"
+
+OID get numeric string - multi-byte first subidentifier
+oid_get_numeric_string:"8837":0:"2.999"
+
+OID get numeric string - empty oid buffer
+oid_get_numeric_string:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
+
+OID get numeric string - no final / all bytes have top bit set
+oid_get_numeric_string:"818181":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
+
+# Encodes the number 0x0400000000 as a subidentifier which overflows 32-bits
+OID get numeric string - 32-bit overflow
+oid_get_numeric_string:"C080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID get numeric string - 32-bit overflow, second subidentifier
+oid_get_numeric_string:"2BC080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID get numeric string - overlong encoding
+oid_get_numeric_string:"8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID get numeric string - overlong encoding, second subidentifier
+oid_get_numeric_string:"2B8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
diff --git a/tests/suites/test_suite_oid.function b/tests/suites/test_suite_oid.function
index 687b216..3004b65 100644
--- a/tests/suites/test_suite_oid.function
+++ b/tests/suites/test_suite_oid.function
@@ -96,3 +96,24 @@
     }
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void oid_get_numeric_string(data_t *oid, int error_ret, char *result_str)
+{
+    char buf[256];
+    mbedtls_asn1_buf input_oid = { 0, 0, NULL };
+    int ret;
+
+    input_oid.tag = MBEDTLS_ASN1_OID;
+    input_oid.p = oid->x;
+    input_oid.len = oid->len;
+
+    ret = mbedtls_oid_get_numeric_string(buf, sizeof(buf), &input_oid);
+
+    if (error_ret == 0) {
+        TEST_ASSERT(strcmp(buf, result_str) == 0);
+    } else {
+        TEST_EQUAL(ret, error_ret);
+    }
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data
index 840a24b..9948537 100644
--- a/tests/suites/test_suite_pkcs7.data
+++ b/tests/suites/test_suite_pkcs7.data
@@ -38,6 +38,14 @@
 depends_on:MBEDTLS_SHA256_C
 pkcs7_parse:"data_files/pkcs7_data_cert_encrypted.der":MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE
 
+PKCS7 Signed Data Verification Pass zero-len data
+depends_on:MBEDTLS_SHA1_C:MBEDTLS_SHA256_C
+pkcs7_verify:"data_files/pkcs7_zerolendata_detached.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_zerolendata.bin":0:0
+
+PKCS7 Signed Data Verification Fail zero-len data
+depends_on:MBEDTLS_SHA1_C:MBEDTLS_SHA256_C
+pkcs7_verify:"data_files/pkcs7_zerolendata_detached.der":"data_files/pkcs7-rsa-sha256-2.der":"data_files/pkcs7_zerolendata.bin":0:MBEDTLS_ERR_RSA_VERIFY_FAILED
+
 PKCS7 Signed Data Verification Pass SHA256 #9
 depends_on:MBEDTLS_SHA256_C
 pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data.bin":0:0
diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function
index 62f9f66..91fe47b 100644
--- a/tests/suites/test_suite_pkcs7.function
+++ b/tests/suites/test_suite_pkcs7.function
@@ -125,7 +125,8 @@
     TEST_ASSERT(file != NULL);
 
     datalen = st.st_size;
-    ASSERT_ALLOC(data, datalen);
+    /* Special-case for zero-length input so that data will be non-NULL */
+    ASSERT_ALLOC(data, datalen == 0 ? 1 : datalen);
     buflen = fread((void *) data, sizeof(unsigned char), datalen, file);
     TEST_EQUAL(buflen, datalen);
 
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index c356142..697cdd7 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -4145,6 +4145,30 @@
 depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
 sign_hash_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":"52d92aac1fcc0fea3ecce01a9ed4bc9ac342f92470fd3f54d0d6d2fa5d2940405057a9d49a817c2b193322f05fc93ac1c7a055edac93bec0ade6814ab27b86b5295ac1ddb323818200f00c3d94d959f714f128b64a2e19628037ac009b14774f"
 
+PSA sign hash int (ops=inf): det ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int (ops=min): det ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":1
+
+PSA sign hash int (ops=inf) det ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
+sign_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":"cd40ba1b555ca5994d30ddffc4ad734b1f5c604675b0f249814aa5de3992ef3ddf4d5dc5d2aab1979ce210b560754df671363d99795475882894c048e3b986ca":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int (ops=min): det ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
+sign_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":"cd40ba1b555ca5994d30ddffc4ad734b1f5c604675b0f249814aa5de3992ef3ddf4d5dc5d2aab1979ce210b560754df671363d99795475882894c048e3b986ca":1
+
+PSA sign hash int (ops=inf): det ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":"52d92aac1fcc0fea3ecce01a9ed4bc9ac342f92470fd3f54d0d6d2fa5d2940405057a9d49a817c2b193322f05fc93ac1c7a055edac93bec0ade6814ab27b86b5295ac1ddb323818200f00c3d94d959f714f128b64a2e19628037ac009b14774f":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int (ops=min): det ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":"52d92aac1fcc0fea3ecce01a9ed4bc9ac342f92470fd3f54d0d6d2fa5d2940405057a9d49a817c2b193322f05fc93ac1c7a055edac93bec0ade6814ab27b86b5295ac1ddb323818200f00c3d94d959f714f128b64a2e19628037ac009b14774f":1
+
 PSA sign hash: RSA PKCS#1 v1.5 SHA-256, wrong hash size
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015":128:PSA_ERROR_INVALID_ARGUMENT
@@ -4206,9 +4230,53 @@
 sign_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
 
 PSA sign hash: deterministic ECDSA not supported
-depends_on:!PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+depends_on:!PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
 sign_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":96:PSA_ERROR_NOT_SUPPORTED
 
+PSA sign hash int (ops=inf): det ECDSA SECP256R1 SHA-256, out buf too small
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":63:PSA_SUCCESS:PSA_ERROR_BUFFER_TOO_SMALL:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int (ops=min): det ECDSA SECP256R1 SHA-256, out buf too small
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":63:PSA_SUCCESS:PSA_ERROR_BUFFER_TOO_SMALL:1
+
+PSA sign hash int (ops=inf): det ECDSA SECP256R1 SHA-256, empty out buf
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":0:PSA_SUCCESS:PSA_ERROR_BUFFER_TOO_SMALL:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int (ops=min): det ECDSA SECP256R1 SHA-256, empty out buf
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":0:PSA_SUCCESS:PSA_ERROR_BUFFER_TOO_SMALL:1
+
+PSA sign hash int (ops=inf): det ECDSA SECP256R1, invld hash alg (0)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( 0 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_SUCCESS:PSA_ERROR_INVALID_ARGUMENT:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int (ops=min): det ECDSA SECP256R1, invld hash alg (0)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( 0 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_SUCCESS:PSA_ERROR_INVALID_ARGUMENT:1
+
+PSA sign hash int: det ECDSA SECP256R1, invld hash alg (wildcard)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_ANY_HASH ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT:PSA_ERROR_BAD_STATE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int: invld alg for ECC key
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_C
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_NOT_SUPPORTED:PSA_ERROR_BAD_STATE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int: ECDSA not supported
+depends_on:!PSA_WANT_ALG_DETERMINISTIC_ECDSA:!PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":96:PSA_ERROR_NOT_SUPPORTED:PSA_ERROR_BAD_STATE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int (ops=inf): det ECDSA not supported
+depends_on:!PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":96:PSA_SUCCESS:PSA_ERROR_NOT_SUPPORTED:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign hash int (ops=min): det ECDSA not supported
+depends_on:!PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":96:PSA_SUCCESS:PSA_ERROR_NOT_SUPPORTED:1
+
 PSA sign/verify hash: RSA PKCS#1 v1.5, raw
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 sign_verify_hash:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263"
@@ -4249,6 +4317,54 @@
 depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
 sign_verify_hash:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
 
+PSA sign/vrfy hash int (ops=inf): rand ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign/vrfy hash int (ops=min): rand ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":1
+
+PSA sign/vrfy hash int (ops=inf): det ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign/vrfy hash int (ops=min): det ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":1
+
+PSA sign/vrfy hash int (ops=inf): rand ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_384):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign/vrfy hash int (ops=min): rand ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_384):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":1
+
+PSA sign/vrfy hash int (ops=inf): det ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign/vrfy hash int (ops=min): det ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":1
+
+PSA sign/vrfy hash int (ops=inf): rand ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign/vrfy hash int (ops=min): rand ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":1
+
+PSA sign/vrfy hash int (ops=inf): det ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign/vrfy hash int (ops=min): det ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":1
+
 PSA verify hash: RSA PKCS#1 v1.5 SHA-256, good signature
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C
 verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
@@ -4369,6 +4485,14 @@
 depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 verify_hash:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
 
+PSA vrfy hash int: ECDSA SECP256R1, good
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_interruptible:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA vrfy hash int w/keypair: ECDSA SECP256R1, good
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
 PSA verify hash: ECDSA SECP256R1, wrong signature size (correct but ASN1-encoded)
 depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 verify_hash_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE
@@ -4397,6 +4521,50 @@
 depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 verify_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"":"":PSA_ERROR_INVALID_ARGUMENT
 
+PSA vrfy hash int: ECDSA SECP256R1, wrong sig size (correct but ASN1-encoded)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail_interruptible:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE:PSA_ERROR_BAD_STATE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA vrfy hash int (ops=inf): ECDSA SECP256R1, wrong sig of correct size
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail_interruptible:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_SUCCESS:PSA_ERROR_INVALID_SIGNATURE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA vrfy hash int (ops=min): ECDSA SECP256R1, wrong sig of correct size
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail_interruptible:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_SUCCESS:PSA_ERROR_INVALID_SIGNATURE:1
+
+PSA vrfy hash int: ECDSA SECP256R1, wrong sig (empty)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail_interruptible:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"":PSA_ERROR_INVALID_SIGNATURE:PSA_ERROR_BAD_STATE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA vrfy hash int: ECDSA SECP256R1, wrong sig (truncated)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail_interruptible:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f5":PSA_ERROR_INVALID_SIGNATURE:PSA_ERROR_BAD_STATE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA vrfy hash int: ECDSA SECP256R1, wrong sig (trailing junk)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail_interruptible:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f21":PSA_ERROR_INVALID_SIGNATURE:PSA_ERROR_BAD_STATE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA vrfy hash int: ECDSA SECP256R1, wrong sig (leading junk)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail_interruptible:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"216a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE:PSA_ERROR_BAD_STATE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA vrfy hash int: invld alg for ECC key
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail_interruptible:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"":"":PSA_ERROR_NOT_SUPPORTED:PSA_ERROR_BAD_STATE:PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
+
+PSA sign/vrfy hash int state test: randomized ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+interruptible_signverify_hash_state_test:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+
+PSA sign/vrfy hash int neg tests: randomized ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+interruptible_signverify_hash_negative_tests:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+
+PSA sign/vrfy hash int max ops tests: randomized ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+interruptible_signverify_hash_maxops_tests:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+
 PSA sign message: RSA PKCS#1 v1.5 SHA-256
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 sign_message_deterministic:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index c414b65..20e43c6 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -1220,6 +1220,34 @@
     INJECT_ANTICIPATE_KEY_DERIVATION_2,
 } ecjpake_injected_failure_t;
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+static void interruptible_signverify_get_minmax_completes(uint32_t max_ops,
+                                                          psa_status_t expected_status,
+                                                          size_t *min_completes,
+                                                          size_t *max_completes)
+{
+
+    /* This is slightly contrived, but we only really know that with a minimum
+       value of max_ops that a successful operation should take more than one op
+       to complete, and likewise that with a max_ops of
+       PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, it should complete in one go. */
+    if (max_ops == 0 || max_ops == 1) {
+
+        if (expected_status == PSA_SUCCESS) {
+            *min_completes = 2;
+        } else {
+            *min_completes = 1;
+        }
+
+        *max_completes = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED;
+    } else {
+        *min_completes = 1;
+        *max_completes = 1;
+    }
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -6444,6 +6472,117 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void sign_hash_interruptible(int key_type_arg, data_t *key_data,
+                             int alg_arg, data_t *input_data,
+                             data_t *output_data, int max_ops_arg)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    unsigned char *signature = NULL;
+    size_t signature_size;
+    size_t signature_length = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_OPERATION_INCOMPLETE;
+    uint32_t num_ops = 0;
+    uint32_t max_ops = max_ops_arg;
+    size_t num_ops_prior = 0;
+    size_t num_completes = 0;
+    size_t min_completes = 0;
+    size_t max_completes = 0;
+
+    psa_sign_hash_interruptible_operation_t operation =
+        psa_sign_hash_interruptible_operation_init();
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    key_bits = psa_get_key_bits(&attributes);
+
+    /* Allocate a buffer which has the size advertised by the
+     * library. */
+    signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
+                                          key_bits, alg);
+    TEST_ASSERT(signature_size != 0);
+    TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
+    ASSERT_ALLOC(signature, signature_size);
+
+    psa_interruptible_set_max_ops(max_ops);
+
+    interruptible_signverify_get_minmax_completes(max_ops, PSA_SUCCESS,
+                                                  &min_completes, &max_completes);
+
+    num_ops_prior = psa_sign_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Start performing the signature. */
+    PSA_ASSERT(psa_sign_hash_start(&operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    num_ops_prior = psa_sign_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Continue performing the signature until complete. */
+    do {
+        status = psa_sign_hash_complete(&operation, signature, signature_size,
+                                        &signature_length);
+
+        num_completes++;
+
+        if (status == PSA_SUCCESS || status == PSA_OPERATION_INCOMPLETE) {
+            num_ops = psa_sign_hash_get_num_ops(&operation);
+            /* We are asserting here that every complete makes progress
+             * (completes some ops), which is true of the internal
+             * implementation and probably any implementation, however this is
+             * not mandated by the PSA specification. */
+            TEST_ASSERT(num_ops > num_ops_prior);
+
+            num_ops_prior = num_ops;
+
+            /* Ensure calling get_num_ops() twice still returns the same
+             * number of ops as previously reported. */
+            num_ops = psa_sign_hash_get_num_ops(&operation);
+
+            TEST_EQUAL(num_ops, num_ops_prior);
+        }
+    } while (status == PSA_OPERATION_INCOMPLETE);
+
+    TEST_ASSERT(status == PSA_SUCCESS);
+
+    TEST_LE_U(min_completes, num_completes);
+    TEST_LE_U(num_completes, max_completes);
+
+    /* Verify that the signature is what is expected. */
+    ASSERT_COMPARE(output_data->x, output_data->len,
+                   signature, signature_length);
+
+    PSA_ASSERT(psa_sign_hash_abort(&operation));
+
+    num_ops = psa_sign_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops == 0);
+
+exit:
+
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes(&attributes);
+
+    psa_destroy_key(key);
+    mbedtls_free(signature);
+    PSA_DONE();
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void sign_hash_fail(int key_type_arg, data_t *key_data,
                     int alg_arg, data_t *input_data,
@@ -6489,6 +6628,123 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void sign_hash_fail_interruptible(int key_type_arg, data_t *key_data,
+                                  int alg_arg, data_t *input_data,
+                                  int signature_size_arg,
+                                  int expected_start_status_arg,
+                                  int expected_complete_status_arg,
+                                  int max_ops_arg)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t signature_size = signature_size_arg;
+    psa_status_t actual_status;
+    psa_status_t expected_start_status = expected_start_status_arg;
+    psa_status_t expected_complete_status = expected_complete_status_arg;
+    unsigned char *signature = NULL;
+    size_t signature_length = 0xdeadbeef;
+    uint32_t num_ops = 0;
+    uint32_t max_ops = max_ops_arg;
+    size_t num_ops_prior = 0;
+    size_t num_completes = 0;
+    size_t min_completes = 0;
+    size_t max_completes = 0;
+
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_sign_hash_interruptible_operation_t operation =
+        psa_sign_hash_interruptible_operation_init();
+
+    ASSERT_ALLOC(signature, signature_size);
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+
+    psa_interruptible_set_max_ops(max_ops);
+
+    interruptible_signverify_get_minmax_completes(max_ops,
+                                                  expected_complete_status,
+                                                  &min_completes,
+                                                  &max_completes);
+
+    num_ops_prior = psa_sign_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Start performing the signature. */
+    actual_status = psa_sign_hash_start(&operation, key, alg,
+                                        input_data->x, input_data->len);
+
+    TEST_EQUAL(actual_status, expected_start_status);
+
+    if (expected_start_status != PSA_SUCCESS) {
+        actual_status = psa_sign_hash_start(&operation, key, alg,
+                                            input_data->x, input_data->len);
+
+        TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
+    }
+
+    num_ops_prior = psa_sign_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Continue performing the signature until complete. */
+    do {
+        actual_status = psa_sign_hash_complete(&operation, signature,
+                                               signature_size,
+                                               &signature_length);
+
+        num_completes++;
+
+        if (actual_status == PSA_SUCCESS ||
+            actual_status == PSA_OPERATION_INCOMPLETE) {
+            num_ops = psa_sign_hash_get_num_ops(&operation);
+            /* We are asserting here that every complete makes progress
+             * (completes some ops), which is true of the internal
+             * implementation and probably any implementation, however this is
+             * not mandated by the PSA specification. */
+            TEST_ASSERT(num_ops > num_ops_prior);
+
+            num_ops_prior = num_ops;
+        }
+    } while (actual_status == PSA_OPERATION_INCOMPLETE);
+
+    TEST_EQUAL(actual_status, expected_complete_status);
+
+    /* Check that another complete returns BAD_STATE. */
+    actual_status = psa_sign_hash_complete(&operation, signature,
+                                           signature_size,
+                                           &signature_length);
+
+    TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
+
+    PSA_ASSERT(psa_sign_hash_abort(&operation));
+
+    num_ops = psa_sign_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops == 0);
+
+    /* The value of *signature_length is unspecified on error, but
+     * whatever it is, it should be less than signature_size, so that
+     * if the caller tries to read *signature_length bytes without
+     * checking the error code then they don't overflow a buffer. */
+    TEST_LE_U(signature_length, signature_size);
+
+    TEST_LE_U(min_completes, num_completes);
+    TEST_LE_U(num_completes, max_completes);
+
+exit:
+    psa_reset_key_attributes(&attributes);
+    psa_destroy_key(key);
+    mbedtls_free(signature);
+    PSA_DONE();
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void sign_verify_hash(int key_type_arg, data_t *key_data,
                       int alg_arg, data_t *input_data)
@@ -6559,6 +6815,137 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void sign_verify_hash_interruptible(int key_type_arg, data_t *key_data,
+                                    int alg_arg, data_t *input_data,
+                                    int max_ops_arg)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    unsigned char *signature = NULL;
+    size_t signature_size;
+    size_t signature_length = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_OPERATION_INCOMPLETE;
+    uint32_t max_ops = max_ops_arg;
+    size_t num_completes = 0;
+    size_t min_completes = 0;
+    size_t max_completes = 0;
+
+    psa_sign_hash_interruptible_operation_t sign_operation =
+        psa_sign_hash_interruptible_operation_init();
+    psa_verify_hash_interruptible_operation_t verify_operation =
+        psa_verify_hash_interruptible_operation_init();
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH |
+                            PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    key_bits = psa_get_key_bits(&attributes);
+
+    /* Allocate a buffer which has the size advertised by the
+     * library. */
+    signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
+                                          key_bits, alg);
+    TEST_ASSERT(signature_size != 0);
+    TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
+    ASSERT_ALLOC(signature, signature_size);
+
+    psa_interruptible_set_max_ops(max_ops);
+
+    interruptible_signverify_get_minmax_completes(max_ops, PSA_SUCCESS,
+                                                  &min_completes, &max_completes);
+
+    /* Start performing the signature. */
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    /* Continue performing the signature until complete. */
+    do {
+
+        status = psa_sign_hash_complete(&sign_operation, signature,
+                                        signature_size,
+                                        &signature_length);
+
+        num_completes++;
+    } while (status == PSA_OPERATION_INCOMPLETE);
+
+    TEST_ASSERT(status == PSA_SUCCESS);
+
+    TEST_LE_U(min_completes, num_completes);
+    TEST_LE_U(num_completes, max_completes);
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    /* Check that the signature length looks sensible. */
+    TEST_LE_U(signature_length, signature_size);
+    TEST_ASSERT(signature_length > 0);
+
+    num_completes = 0;
+
+    /* Start verification. */
+    PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_data->x, input_data->len,
+                                     signature, signature_length));
+
+    /* Continue performing the signature until complete. */
+    do {
+        status = psa_verify_hash_complete(&verify_operation);
+
+        num_completes++;
+    } while (status == PSA_OPERATION_INCOMPLETE);
+
+    TEST_ASSERT(status == PSA_SUCCESS);
+
+    TEST_LE_U(min_completes, num_completes);
+    TEST_LE_U(num_completes, max_completes);
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+    verify_operation = psa_verify_hash_interruptible_operation_init();
+
+    if (input_data->len != 0) {
+        /* Flip a bit in the input and verify that the signature is now
+         * detected as invalid. Flip a bit at the beginning, not at the end,
+         * because ECDSA may ignore the last few bits of the input. */
+        input_data->x[0] ^= 1;
+
+        /* Start verification. */
+        PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                         input_data->x, input_data->len,
+                                         signature, signature_length));
+
+        /* Continue performing the signature until complete. */
+        do {
+            status = psa_verify_hash_complete(&verify_operation);
+        } while (status == PSA_OPERATION_INCOMPLETE);
+
+        TEST_ASSERT(status ==  PSA_ERROR_INVALID_SIGNATURE);
+    }
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes(&attributes);
+
+    psa_destroy_key(key);
+    mbedtls_free(signature);
+    PSA_DONE();
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void verify_hash(int key_type_arg, data_t *key_data,
                  int alg_arg, data_t *hash_data,
@@ -6591,6 +6978,97 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void verify_hash_interruptible(int key_type_arg, data_t *key_data,
+                               int alg_arg, data_t *hash_data,
+                               data_t *signature_data, int max_ops_arg)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_OPERATION_INCOMPLETE;
+    uint32_t num_ops = 0;
+    uint32_t max_ops = max_ops_arg;
+    size_t num_ops_prior = 0;
+    size_t num_completes = 0;
+    size_t min_completes = 0;
+    size_t max_completes = 0;
+
+    psa_verify_hash_interruptible_operation_t operation =
+        psa_verify_hash_interruptible_operation_init();
+
+    TEST_LE_U(signature_data->len, PSA_SIGNATURE_MAX_SIZE);
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+
+    psa_interruptible_set_max_ops(max_ops);
+
+    interruptible_signverify_get_minmax_completes(max_ops, PSA_SUCCESS,
+                                                  &min_completes, &max_completes);
+
+    num_ops_prior = psa_verify_hash_get_num_ops(&operation);
+
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Start verification. */
+    PSA_ASSERT(psa_verify_hash_start(&operation, key, alg,
+                                     hash_data->x, hash_data->len,
+                                     signature_data->x, signature_data->len)
+               );
+
+    num_ops_prior = psa_verify_hash_get_num_ops(&operation);
+
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Continue performing the signature until complete. */
+    do {
+        status = psa_verify_hash_complete(&operation);
+
+        num_completes++;
+
+        if (status == PSA_SUCCESS || status == PSA_OPERATION_INCOMPLETE) {
+            num_ops = psa_verify_hash_get_num_ops(&operation);
+            /* We are asserting here that every complete makes progress
+             * (completes some ops), which is true of the internal
+             * implementation and probably any implementation, however this is
+             * not mandated by the PSA specification. */
+            TEST_ASSERT(num_ops > num_ops_prior);
+
+            num_ops_prior = num_ops;
+
+            /* Ensure calling get_num_ops() twice still returns the same
+             * number of ops as previously reported. */
+            num_ops = psa_verify_hash_get_num_ops(&operation);
+
+            TEST_EQUAL(num_ops, num_ops_prior);
+        }
+    } while (status == PSA_OPERATION_INCOMPLETE);
+
+    TEST_ASSERT(status == PSA_SUCCESS);
+
+    TEST_LE_U(min_completes, num_completes);
+    TEST_LE_U(num_completes, max_completes);
+
+    PSA_ASSERT(psa_verify_hash_abort(&operation));
+
+    num_ops = psa_verify_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops == 0);
+
+exit:
+    psa_reset_key_attributes(&attributes);
+    psa_destroy_key(key);
+    PSA_DONE();
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void verify_hash_fail(int key_type_arg, data_t *key_data,
                       int alg_arg, data_t *hash_data,
@@ -6625,6 +7103,479 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void verify_hash_fail_interruptible(int key_type_arg, data_t *key_data,
+                                    int alg_arg, data_t *hash_data,
+                                    data_t *signature_data,
+                                    int expected_start_status_arg,
+                                    int expected_complete_status_arg,
+                                    int max_ops_arg)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t actual_status;
+    psa_status_t expected_start_status = expected_start_status_arg;
+    psa_status_t expected_complete_status = expected_complete_status_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    uint32_t num_ops = 0;
+    uint32_t max_ops = max_ops_arg;
+    size_t num_ops_prior = 0;
+    size_t num_completes = 0;
+    size_t min_completes = 0;
+    size_t max_completes = 0;
+    psa_verify_hash_interruptible_operation_t operation =
+        psa_verify_hash_interruptible_operation_init();
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+
+    psa_interruptible_set_max_ops(max_ops);
+
+    interruptible_signverify_get_minmax_completes(max_ops,
+                                                  expected_complete_status,
+                                                  &min_completes,
+                                                  &max_completes);
+
+    num_ops_prior = psa_verify_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Start verification. */
+    actual_status = psa_verify_hash_start(&operation, key, alg,
+                                          hash_data->x, hash_data->len,
+                                          signature_data->x,
+                                          signature_data->len);
+
+    TEST_EQUAL(actual_status, expected_start_status);
+
+    if (expected_start_status != PSA_SUCCESS) {
+        actual_status = psa_verify_hash_start(&operation, key, alg,
+                                              hash_data->x, hash_data->len,
+                                              signature_data->x,
+                                              signature_data->len);
+
+        TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
+    }
+
+    num_ops_prior = psa_verify_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
+    /* Continue performing the signature until complete. */
+    do {
+        actual_status = psa_verify_hash_complete(&operation);
+
+        num_completes++;
+
+        if (actual_status == PSA_SUCCESS ||
+            actual_status == PSA_OPERATION_INCOMPLETE) {
+            num_ops = psa_verify_hash_get_num_ops(&operation);
+            /* We are asserting here that every complete makes progress
+             * (completes some ops), which is true of the internal
+             * implementation and probably any implementation, however this is
+             * not mandated by the PSA specification. */
+            TEST_ASSERT(num_ops > num_ops_prior);
+
+            num_ops_prior = num_ops;
+        }
+    } while (actual_status == PSA_OPERATION_INCOMPLETE);
+
+    TEST_EQUAL(actual_status, expected_complete_status);
+
+    /* Check that another complete returns BAD_STATE. */
+    actual_status = psa_verify_hash_complete(&operation);
+    TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
+
+    TEST_LE_U(min_completes, num_completes);
+    TEST_LE_U(num_completes, max_completes);
+
+    PSA_ASSERT(psa_verify_hash_abort(&operation));
+
+    num_ops = psa_verify_hash_get_num_ops(&operation);
+    TEST_ASSERT(num_ops == 0);
+
+exit:
+    psa_reset_key_attributes(&attributes);
+    psa_destroy_key(key);
+    PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void interruptible_signverify_hash_state_test(int key_type_arg,
+                                              data_t *key_data, int alg_arg, data_t *input_data)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    unsigned char *signature = NULL;
+    size_t signature_size;
+    size_t signature_length = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_sign_hash_interruptible_operation_t sign_operation =
+        psa_sign_hash_interruptible_operation_init();
+    psa_verify_hash_interruptible_operation_t verify_operation =
+        psa_verify_hash_interruptible_operation_init();
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH |
+                            PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    key_bits = psa_get_key_bits(&attributes);
+
+    /* Allocate a buffer which has the size advertised by the
+     * library. */
+    signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
+                                          key_bits, alg);
+    TEST_ASSERT(signature_size != 0);
+    TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
+    ASSERT_ALLOC(signature, signature_size);
+
+    psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
+
+    /* --- Attempt completes prior to starts --- */
+    TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
+                                      signature_size,
+                                      &signature_length),
+               PSA_ERROR_BAD_STATE);
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    TEST_EQUAL(psa_verify_hash_complete(&verify_operation),
+               PSA_ERROR_BAD_STATE);
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+    /* --- Aborts in all other places. --- */
+    psa_sign_hash_abort(&sign_operation);
+
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    psa_interruptible_set_max_ops(1);
+
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
+                                      signature_size,
+                                      &signature_length),
+               PSA_OPERATION_INCOMPLETE);
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
+
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    PSA_ASSERT(psa_sign_hash_complete(&sign_operation, signature,
+                                      signature_size,
+                                      &signature_length));
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+    PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_data->x, input_data->len,
+                                     signature, signature_length));
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+    psa_interruptible_set_max_ops(1);
+
+    PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_data->x, input_data->len,
+                                     signature, signature_length));
+
+    TEST_EQUAL(psa_verify_hash_complete(&verify_operation),
+               PSA_OPERATION_INCOMPLETE);
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+    psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
+
+    PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_data->x, input_data->len,
+                                     signature, signature_length));
+
+    PSA_ASSERT(psa_verify_hash_complete(&verify_operation));
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+    /* --- Attempt double starts. --- */
+
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    TEST_EQUAL(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len),
+               PSA_ERROR_BAD_STATE);
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_data->x, input_data->len,
+                                     signature, signature_length));
+
+    TEST_EQUAL(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_data->x, input_data->len,
+                                     signature, signature_length),
+               PSA_ERROR_BAD_STATE);
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes(&attributes);
+
+    psa_destroy_key(key);
+    mbedtls_free(signature);
+    PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void interruptible_signverify_hash_negative_tests(int key_type_arg,
+                                                  data_t *key_data, int alg_arg, data_t *input_data)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    unsigned char *signature = NULL;
+    size_t signature_size;
+    size_t signature_length = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    uint8_t *input_buffer = NULL;
+    psa_sign_hash_interruptible_operation_t sign_operation =
+        psa_sign_hash_interruptible_operation_init();
+    psa_verify_hash_interruptible_operation_t verify_operation =
+        psa_verify_hash_interruptible_operation_init();
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH |
+                            PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
+                              &key));
+    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    key_bits = psa_get_key_bits(&attributes);
+
+    /* Allocate a buffer which has the size advertised by the
+     * library. */
+    signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
+                                          key_bits, alg);
+    TEST_ASSERT(signature_size != 0);
+    TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
+    ASSERT_ALLOC(signature, signature_size);
+
+    /* --- Ensure changing the max ops mid operation works (operation should
+     *     complete successfully after setting max ops to unlimited --- */
+    psa_interruptible_set_max_ops(1);
+
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
+                                      signature_size,
+                                      &signature_length),
+               PSA_OPERATION_INCOMPLETE);
+
+    psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
+
+    PSA_ASSERT(psa_sign_hash_complete(&sign_operation, signature,
+                                      signature_size,
+                                      &signature_length));
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    psa_interruptible_set_max_ops(1);
+
+    PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_data->x, input_data->len,
+                                     signature, signature_length));
+
+    TEST_EQUAL(psa_verify_hash_complete(&verify_operation),
+               PSA_OPERATION_INCOMPLETE);
+
+    psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
+
+    PSA_ASSERT(psa_verify_hash_complete(&verify_operation));
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+    /* --- Change function inputs mid run, to cause an error (sign only,
+     *     verify passes all inputs to start. --- */
+
+    psa_interruptible_set_max_ops(1);
+
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
+                                      signature_size,
+                                      &signature_length),
+               PSA_OPERATION_INCOMPLETE);
+
+    TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
+                                      0,
+                                      &signature_length),
+               PSA_ERROR_BUFFER_TOO_SMALL);
+
+    /* And test that this invalidates the operation. */
+    TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
+                                      0,
+                                      &signature_length),
+               PSA_ERROR_BAD_STATE);
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    /* Trash the hash buffer in between start and complete, to ensure
+     * no reliance on external buffers. */
+    psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
+
+    input_buffer = mbedtls_calloc(1, input_data->len);
+    TEST_ASSERT(input_buffer != NULL);
+
+    memcpy(input_buffer, input_data->x, input_data->len);
+
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_buffer, input_data->len));
+
+    memset(input_buffer, '!', input_data->len);
+    mbedtls_free(input_buffer);
+    input_buffer = NULL;
+
+    PSA_ASSERT(psa_sign_hash_complete(&sign_operation, signature,
+                                      signature_size,
+                                      &signature_length));
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    input_buffer = mbedtls_calloc(1, input_data->len);
+    TEST_ASSERT(input_buffer != NULL);
+
+    memcpy(input_buffer, input_data->x, input_data->len);
+
+    PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_buffer, input_data->len,
+                                     signature, signature_length));
+
+    memset(input_buffer, '!', input_data->len);
+    mbedtls_free(input_buffer);
+    input_buffer = NULL;
+
+    PSA_ASSERT(psa_verify_hash_complete(&verify_operation));
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes(&attributes);
+
+    psa_destroy_key(key);
+    mbedtls_free(signature);
+    PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void interruptible_signverify_hash_maxops_tests(int key_type_arg,
+                                                data_t *key_data, int alg_arg, data_t *input_data)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    size_t key_bits;
+    unsigned char *signature = NULL;
+    size_t signature_size;
+    psa_sign_hash_interruptible_operation_t sign_operation =
+        psa_sign_hash_interruptible_operation_init();
+    psa_verify_hash_interruptible_operation_t verify_operation =
+        psa_verify_hash_interruptible_operation_init();
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH |
+                            PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, key_type);
+
+    PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len, &key));
+    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    key_bits = psa_get_key_bits(&attributes);
+
+    /* Allocate a buffer which has the size advertised by the
+     * library. */
+    signature_size = PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg);
+
+    TEST_ASSERT(signature_size != 0);
+    TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
+    ASSERT_ALLOC(signature, signature_size);
+
+    /* Check that default max ops gets set if we don't set it. */
+    PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
+                                   input_data->x, input_data->len));
+
+    TEST_EQUAL(psa_interruptible_get_max_ops(),
+               PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
+                                     input_data->x, input_data->len,
+                                     signature, signature_size));
+
+    TEST_EQUAL(psa_interruptible_get_max_ops(),
+               PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
+    /* Check that max ops gets set properly. */
+
+    psa_interruptible_set_max_ops(0xbeef);
+
+    TEST_EQUAL(psa_interruptible_get_max_ops(), 0xbeef);
+
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes(&attributes);
+
+    psa_destroy_key(key);
+    mbedtls_free(signature);
+    PSA_DONE();
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void sign_message_deterministic(int key_type_arg,
                                 data_t *key_data,
diff --git a/tests/suites/test_suite_psa_crypto_op_fail.function b/tests/suites/test_suite_psa_crypto_op_fail.function
index 046e3c3..970be84 100644
--- a/tests/suites/test_suite_psa_crypto_op_fail.function
+++ b/tests/suites/test_suite_psa_crypto_op_fail.function
@@ -221,6 +221,13 @@
     uint8_t input[1] = { 'A' };
     uint8_t output[PSA_SIGNATURE_MAX_SIZE] = { 0 };
     size_t length = SIZE_MAX;
+    psa_sign_hash_interruptible_operation_t sign_operation =
+        psa_sign_hash_interruptible_operation_init();
+
+    psa_verify_hash_interruptible_operation_t verify_operation =
+        psa_verify_hash_interruptible_operation_init();
+
+
 
     PSA_INIT();
 
@@ -237,6 +244,15 @@
                 psa_sign_hash(key_id, alg,
                               input, sizeof(input),
                               output, sizeof(output), &length));
+
+    if (PSA_KEY_TYPE_IS_ECC(key_type)) {
+        TEST_STATUS(expected_status,
+                    psa_sign_hash_start(&sign_operation, key_id, alg,
+                                        input, sizeof(input)));
+
+        PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+    }
+
     if (!private_only) {
         /* Determine a plausible signature size to avoid an INVALID_SIGNATURE
          * error based on this. */
@@ -253,6 +269,15 @@
                     psa_verify_hash(key_id, alg,
                                     input, sizeof(input),
                                     output, output_length));
+
+        if (PSA_KEY_TYPE_IS_ECC(key_type)) {
+            TEST_STATUS(expected_status,
+                        psa_verify_hash_start(&verify_operation, key_id, alg,
+                                              input, sizeof(input),
+                                              output, output_length));
+
+            PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+        }
     }
 
 exit:
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index c6dbad7..54080a7 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -2562,7 +2562,7 @@
 x509_oid_numstr:"2a864886f70d":"1.2.840.113549":15:14
 
 X509 OID numstring #5 (arithmetic overflow)
-x509_oid_numstr:"2a8648f9f8f7f6f5f4f3f2f1f001":"":100:MBEDTLS_ERR_OID_BUF_TOO_SMALL
+x509_oid_numstr:"2a8648f9f8f7f6f5f4f3f2f1f001":"":100:MBEDTLS_ERR_ASN1_INVALID_DATA
 
 X509 CRT keyUsage #1 (no extension, expected KU)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA