Merge pull request #7188 from paul-elliott-arm/interruptible_sign_hash_complete_after_start_fail

Interruptible {sign|verify} hash - Call complete() after start() failure.
diff --git a/.travis.yml b/.travis.yml
index 54df776..cdb79d1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -52,8 +52,8 @@
         - programs/test/selftest
         - tests/scripts/test_psa_constant_names.py
         - tests/ssl-opt.sh
-        # Modern OpenSSL does not support fixed ECDH or null ciphers.
-        - tests/compat.sh -p OpenSSL -e 'NULL\|ECDH_'
+        # Modern OpenSSL does not support null ciphers.
+        - tests/compat.sh -p OpenSSL -e 'NULL'
         - tests/scripts/travis-log-failure.sh
         # GnuTLS supports CAMELLIA but compat.sh doesn't properly enable it.
         - tests/compat.sh -p GnuTLS -e 'CAMELLIA'
@@ -80,6 +80,58 @@
         - sleep 5
         - scripts/windows_msbuild.bat v141 # Visual Studio 2017
 
+    - name: full configuration on arm64
+      os: linux
+      dist: focal
+      arch: arm64
+      addons:
+        apt:
+          packages:
+          - gcc
+      script:
+        # Do a manual build+test sequence rather than using all.sh, because
+        # there's no all.sh component that does what we want. We should set
+        # CFLAGS for arm64 host CC.
+        - scripts/config.py full
+        - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
+        - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
+        - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
+        - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY
+        - make generated_files
+        - make CFLAGS='-march=armv8-a+crypto -O3 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all' LDFLAGS='-Werror -fsanitize=address,undefined -fno-sanitize-recover=all'
+        - make test
+        - programs/test/selftest
+        - tests/scripts/test_psa_constant_names.py
+        # Modern OpenSSL does not support fixed ECDH or null ciphers.
+        - tests/compat.sh -p OpenSSL -e 'NULL\|ECDH_'
+        - tests/scripts/travis-log-failure.sh
+        - tests/context-info.sh
+
+    - name: full configuration(GnuTLS compat tests) on arm64
+      os: linux
+      dist: focal
+      arch: arm64
+      addons:
+        apt:
+          packages:
+          - clang
+          - gnutls-bin
+      script:
+        # Do a manual build+test sequence rather than using all.sh, because
+        # there's no all.sh component that does what we want. We should set
+        # CFLAGS for arm64 host CC.
+        - scripts/config.py full
+        - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
+        - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
+        - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
+        - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY
+        - make generated_files
+        - make CC=clang CFLAGS='-march=armv8-a+crypto -O3 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all' LDFLAGS='-Werror -fsanitize=address,undefined -fno-sanitize-recover=all'
+        # GnuTLS supports CAMELLIA but compat.sh doesn't properly enable it.
+        - tests/compat.sh -p GnuTLS -e 'CAMELLIA'
+        - tests/scripts/travis-log-failure.sh
+        - tests/context-info.sh
+
 after_failure:
 - tests/scripts/travis-log-failure.sh
 
diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h
index bbfd5d4..b10b1ad 100644
--- a/include/mbedtls/build_info.h
+++ b/include/mbedtls/build_info.h
@@ -82,24 +82,13 @@
 
 /* The PK wrappers need pk_write functions to format RSA key objects
  * when they are dispatching to the PSA API. This happens under USE_PSA_CRYPTO,
- * and also even without USE_PSA_CRYPTO for mbedtls_pk_sign_ext().
- * PSA crypto also needs pk_write to export RSA keys (otherwise the build
- * goes through but psa_export_key() and psa_export_public_key() fail on
- * RSA keys), and pk_parse to work with RSA keys in almost any way.
- */
+ * and also even without USE_PSA_CRYPTO for mbedtls_pk_sign_ext(). */
 #if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_RSA_C)
 #define MBEDTLS_PK_C
 #define MBEDTLS_PK_WRITE_C
 #define MBEDTLS_PK_PARSE_C
 #endif
 
-/* Under MBEDTLS_USE_PSA_CRYPTO, the pk module needs pk_write functions
- * to pass ECC keys to PSA. */
-#if defined(MBEDTLS_PK_C) &&                                    \
-    defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECP_C)
-#define MBEDTLS_PK_WRITE_C
-#endif
-
 #if !defined(MBEDTLS_SSL_PROTO_TLS1_2)
 #undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
 #undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 1efabdc..ac374d2 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -70,6 +70,10 @@
 #error "MBEDTLS_AESNI_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_AESCE_C) && !defined(MBEDTLS_HAVE_ASM)
+#error "MBEDTLS_AESCE_C defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C)
 #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites"
 #endif
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index b874995..5aff9c5 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -2066,6 +2066,34 @@
 #define MBEDTLS_AESNI_C
 
 /**
+ * \def MBEDTLS_AESCE_C
+ *
+ * Enable AES crypto extension support on Arm64.
+ *
+ * Module:  library/aesce.c
+ * Caller:  library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM, MBEDTLS_AES_C
+ *
+ * \note The code uses Neon intrinsics, so \c CFLAGS must be set to a minimum
+ * of \c -march=armv8-a+crypto .
+ *
+ * \warning If the target architecture is set to something that includes the
+ *          SHA3 feature (e.g. `-march=armv8.2-a+sha3`), for example because
+ *          `MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT` is desired, compilers
+ *          generate code for `MBEDTLS_AESCE_C` that includes instructions
+ *          only present with the (optional) SHA3 feature. This will lead to an
+ *          undefined instruction exception if the code is run on a CPU without
+ *          that feature.
+ *
+ * \warning Runtime detection only works on linux. For non-linux operation
+ *          system, crypto extension MUST be supported by CPU.
+ *
+ * This module adds support for the AES crypto instructions on Arm64
+ */
+#define MBEDTLS_AESCE_C
+
+/**
  * \def MBEDTLS_AES_C
  *
  * Enable the AES block cipher.
diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h
index dc74ac6..f6070dc 100644
--- a/include/mbedtls/psa_util.h
+++ b/include/mbedtls/psa_util.h
@@ -257,6 +257,9 @@
 #define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH \
     PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
 
+#define MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH \
+    PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
+
 /* Expose whatever RNG the PSA subsystem uses to applications using the
  * mbedtls_xxx API. The declarations and definitions here need to be
  * consistent with the implementation in library/psa_crypto_random_impl.h.
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 8dd89fa..5b448a5 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -4217,6 +4217,9 @@
  *                              \c psa_sign_hash_interruptible_abort() on
  *                              the operation, a value of 0 will be returned.
  *
+ * \note                        This interface is guaranteed re-entrant and
+ *                              thus may be called from driver code.
+ *
  * \warning                     This is a beta API, and thus subject to change
  *                              at any point. It is not bound by the usual
  *                              interface stability promises.
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index c9714bb..bef2e1c 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -13,6 +13,7 @@
 set(src_crypto
     aes.c
     aesni.c
+    aesce.c
     aria.c
     asn1parse.c
     asn1write.c
diff --git a/library/Makefile b/library/Makefile
index dd16d06..ed5e1e1 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -78,6 +78,7 @@
 OBJS_CRYPTO= \
 	     aes.o \
 	     aesni.o \
+	     aesce.o \
 	     aria.o \
 	     asn1parse.o \
 	     asn1write.o \
diff --git a/library/aes.c b/library/aes.c
index 566e747..64392fc 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -39,6 +39,9 @@
 #if defined(MBEDTLS_AESNI_C)
 #include "aesni.h"
 #endif
+#if defined(MBEDTLS_AESCE_C)
+#include "aesce.h"
+#endif
 
 #include "mbedtls/platform.h"
 
@@ -544,6 +547,12 @@
     }
 #endif
 
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+    if (mbedtls_aesce_has_support()) {
+        return mbedtls_aesce_setkey_enc((unsigned char *) RK, key, keybits);
+    }
+#endif
+
     for (i = 0; i < (keybits >> 5); i++) {
         RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2);
     }
@@ -652,6 +661,16 @@
     }
 #endif
 
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+    if (mbedtls_aesce_has_support()) {
+        mbedtls_aesce_inverse_key(
+            (unsigned char *) RK,
+            (const unsigned char *) (cty.buf + cty.rk_offset),
+            ctx->nr);
+        goto exit;
+    }
+#endif
+
     SK = cty.buf + cty.rk_offset + cty.nr * 4;
 
     *RK++ = *SK++;
@@ -944,6 +963,12 @@
     }
 #endif
 
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+    if (mbedtls_aesce_has_support()) {
+        return mbedtls_aesce_crypt_ecb(ctx, mode, input, output);
+    }
+#endif
+
 #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
     if (aes_padlock_ace > 0) {
         if (mbedtls_padlock_xcryptecb(ctx, mode, input, output) == 0) {
diff --git a/library/aesce.c b/library/aesce.c
new file mode 100644
index 0000000..ee0c8e1
--- /dev/null
+++ b/library/aesce.c
@@ -0,0 +1,257 @@
+/*
+ *  Arm64 crypto extension support functions
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include <string.h>
+#include "common.h"
+
+#if defined(MBEDTLS_AESCE_C)
+
+#include "aesce.h"
+
+#if defined(MBEDTLS_HAVE_ARM64)
+
+#if defined(__clang__)
+#   if __clang_major__ < 4
+#       error "A more recent Clang is required for MBEDTLS_AESCE_C"
+#   endif
+#elif defined(__GNUC__)
+#   if __GNUC__ < 6
+#       error "A more recent GCC is required for MBEDTLS_AESCE_C"
+#   endif
+#else
+#    error "Only GCC and Clang supported for MBEDTLS_AESCE_C"
+#endif
+
+#if !defined(__ARM_FEATURE_CRYPTO)
+#   error "`crypto` feature moddifier MUST be enabled for MBEDTLS_AESCE_C."
+#   error "Typical option for GCC and Clang is `-march=armv8-a+crypto`."
+#endif /* !__ARM_FEATURE_CRYPTO */
+
+#include <arm_neon.h>
+
+#if defined(__linux__)
+#include <asm/hwcap.h>
+#include <sys/auxv.h>
+#endif
+
+/*
+ * AES instruction support detection routine
+ */
+int mbedtls_aesce_has_support(void)
+{
+#if defined(__linux__)
+    unsigned long auxval = getauxval(AT_HWCAP);
+    return (auxval & (HWCAP_ASIMD | HWCAP_AES)) ==
+           (HWCAP_ASIMD | HWCAP_AES);
+#else
+    /* Assume AES instructions are supported. */
+    return 1;
+#endif
+}
+
+static uint8x16_t aesce_encrypt_block(uint8x16_t block,
+                                      unsigned char *keys,
+                                      int rounds)
+{
+    for (int i = 0; i < rounds - 1; i++) {
+        /* AES AddRoundKey, SubBytes, ShiftRows (in this order).
+         * AddRoundKey adds the round key for the previous round. */
+        block = vaeseq_u8(block, vld1q_u8(keys + i * 16));
+        /* AES mix columns */
+        block = vaesmcq_u8(block);
+    }
+
+    /* AES AddRoundKey for the previous round.
+     * SubBytes, ShiftRows for the final round.  */
+    block = vaeseq_u8(block, vld1q_u8(keys + (rounds -1) * 16));
+
+    /* Final round: no MixColumns */
+
+    /* Final AddRoundKey */
+    block = veorq_u8(block, vld1q_u8(keys + rounds  * 16));
+
+    return block;
+}
+
+static uint8x16_t aesce_decrypt_block(uint8x16_t block,
+                                      unsigned char *keys,
+                                      int rounds)
+{
+
+    for (int i = 0; i < rounds - 1; i++) {
+        /* AES AddRoundKey, SubBytes, ShiftRows */
+        block = vaesdq_u8(block, vld1q_u8(keys + i * 16));
+        /* AES inverse MixColumns for the next round.
+         *
+         * This means that we switch the order of the inverse AddRoundKey and
+         * inverse MixColumns operations. We have to do this as AddRoundKey is
+         * done in an atomic instruction together with the inverses of SubBytes
+         * and ShiftRows.
+         *
+         * It works because MixColumns is a linear operation over GF(2^8) and
+         * AddRoundKey is an exclusive or, which is equivalent to addition over
+         * GF(2^8). (The inverse of MixColumns needs to be applied to the
+         * affected round keys separately which has been done when the
+         * decryption round keys were calculated.) */
+        block = vaesimcq_u8(block);
+    }
+
+    /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the
+     * last full round. */
+    block = vaesdq_u8(block, vld1q_u8(keys + (rounds - 1) * 16));
+
+    /* Inverse AddRoundKey for inverting the initial round key addition. */
+    block = veorq_u8(block, vld1q_u8(keys + rounds * 16));
+
+    return block;
+}
+
+/*
+ * AES-ECB block en(de)cryption
+ */
+int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,
+                            int mode,
+                            const unsigned char input[16],
+                            unsigned char output[16])
+{
+    uint8x16_t block = vld1q_u8(&input[0]);
+    unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset);
+
+    if (mode == MBEDTLS_AES_ENCRYPT) {
+        block = aesce_encrypt_block(block, keys, ctx->nr);
+    } else {
+        block = aesce_decrypt_block(block, keys, ctx->nr);
+    }
+    vst1q_u8(&output[0], block);
+
+    return 0;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void mbedtls_aesce_inverse_key(unsigned char *invkey,
+                               const unsigned char *fwdkey,
+                               int nr)
+{
+    int i, j;
+    j = nr;
+    vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16));
+    for (i = 1, j--; j > 0; i++, j--) {
+        vst1q_u8(invkey + i * 16,
+                 vaesimcq_u8(vld1q_u8(fwdkey + j * 16)));
+    }
+    vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16));
+
+}
+
+static inline uint32_t aes_rot_word(uint32_t word)
+{
+    return (word << (32 - 8)) | (word >> 8);
+}
+
+static inline uint32_t aes_sub_word(uint32_t in)
+{
+    uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in));
+    uint8x16_t zero = vdupq_n_u8(0);
+
+    /* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields
+     * the correct result as ShiftRows doesn't change the first row. */
+    v = vaeseq_u8(zero, v);
+    return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0);
+}
+
+/*
+ * Key expansion function
+ */
+static void aesce_setkey_enc(unsigned char *rk,
+                             const unsigned char *key,
+                             const size_t key_bit_length)
+{
+    static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10,
+                                    0x20, 0x40, 0x80, 0x1b, 0x36 };
+    /* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf
+     *   - Section 5, Nr = Nk + 6
+     *   - Section 5.2, the key expansion size is Nb*(Nr+1)
+     */
+    const uint32_t key_len_in_words = key_bit_length / 32;  /* Nk */
+    const size_t round_key_len_in_words = 4;                /* Nb */
+    const size_t round_keys_needed = key_len_in_words + 6;  /* Nr */
+    const size_t key_expansion_size_in_words =
+        round_key_len_in_words * (round_keys_needed + 1);   /* Nb*(Nr+1) */
+    const uint32_t *rko_end = (uint32_t *) rk + key_expansion_size_in_words;
+
+    memcpy(rk, key, key_len_in_words * 4);
+
+    for (uint32_t *rki = (uint32_t *) rk;
+         rki + key_len_in_words < rko_end;
+         rki += key_len_in_words) {
+
+        size_t iteration = (rki - (uint32_t *) rk) / key_len_in_words;
+        uint32_t *rko;
+        rko = rki + key_len_in_words;
+        rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1]));
+        rko[0] ^= rcon[iteration] ^ rki[0];
+        rko[1] = rko[0] ^ rki[1];
+        rko[2] = rko[1] ^ rki[2];
+        rko[3] = rko[2] ^ rki[3];
+        if (rko + key_len_in_words > rko_end) {
+            /* Do not write overflow words.*/
+            continue;
+        }
+        switch (key_bit_length) {
+            case 128:
+                break;
+            case 192:
+                rko[4] = rko[3] ^ rki[4];
+                rko[5] = rko[4] ^ rki[5];
+                break;
+            case 256:
+                rko[4] = aes_sub_word(rko[3]) ^ rki[4];
+                rko[5] = rko[4] ^ rki[5];
+                rko[6] = rko[5] ^ rki[6];
+                rko[7] = rko[6] ^ rki[7];
+                break;
+        }
+    }
+}
+
+/*
+ * Key expansion, wrapper
+ */
+int mbedtls_aesce_setkey_enc(unsigned char *rk,
+                             const unsigned char *key,
+                             size_t bits)
+{
+    switch (bits) {
+        case 128:
+        case 192:
+        case 256:
+            aesce_setkey_enc(rk, key, bits);
+            break;
+        default:
+            return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
+    }
+
+    return 0;
+}
+
+#endif /* MBEDTLS_HAVE_ARM64 */
+
+#endif /* MBEDTLS_AESCE_C */
diff --git a/library/aesce.h b/library/aesce.h
new file mode 100644
index 0000000..da42446
--- /dev/null
+++ b/library/aesce.h
@@ -0,0 +1,98 @@
+/**
+ * \file aesce.h
+ *
+ * \brief AES-CE for hardware AES acceleration on ARMv8 processors with crypto
+ *        extension.
+ *
+ * \warning These functions are only for internal use by other library
+ *          functions; you must not call them directly.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef MBEDTLS_AESCE_H
+#define MBEDTLS_AESCE_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/aes.h"
+
+
+#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
+    defined(__aarch64__) && !defined(MBEDTLS_HAVE_ARM64)
+#define MBEDTLS_HAVE_ARM64
+#endif
+
+#if defined(MBEDTLS_HAVE_ARM64)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Internal function to detect the crypto extension in CPUs.
+ *
+ * \return         1 if CPU has support for the feature, 0 otherwise
+ */
+int mbedtls_aesce_has_support(void);
+
+/**
+ * \brief          Internal AES-ECB block encryption and decryption
+ *
+ * \param ctx      AES context
+ * \param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 on success (cannot fail)
+ */
+int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,
+                            int mode,
+                            const unsigned char input[16],
+                            unsigned char output[16]);
+
+/**
+ * \brief           Internal round key inversion. This function computes
+ *                  decryption round keys from the encryption round keys.
+ *
+ * \param invkey    Round keys for the equivalent inverse cipher
+ * \param fwdkey    Original round keys (for encryption)
+ * \param nr        Number of rounds (that is, number of round keys minus one)
+ */
+void mbedtls_aesce_inverse_key(unsigned char *invkey,
+                               const unsigned char *fwdkey,
+                               int nr);
+
+/**
+ * \brief           Internal key expansion for encryption
+ *
+ * \param rk        Destination buffer where the round keys are written
+ * \param key       Encryption key
+ * \param bits      Key size in bits (must be 128, 192 or 256)
+ *
+ * \return          0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedtls_aesce_setkey_enc(unsigned char *rk,
+                             const unsigned char *key,
+                             size_t bits);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_HAVE_ARM64 */
+
+#endif /* MBEDTLS_AESCE_H */
diff --git a/library/alignment.h b/library/alignment.h
index aa09ff8..f7330c9 100644
--- a/library/alignment.h
+++ b/library/alignment.h
@@ -130,7 +130,7 @@
  * byte from x, where byte 0 is the least significant byte.
  */
 #define MBEDTLS_BYTE_0(x) ((uint8_t) ((x)         & 0xff))
-#define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff))
+#define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >>  8) & 0xff))
 #define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff))
 #define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff))
 #define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff))
@@ -155,13 +155,13 @@
  * Detect Clang built-in byteswap routines
  */
 #if defined(__clang__) && defined(__has_builtin)
-#if __has_builtin(__builtin_bswap16)
+#if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16)
 #define MBEDTLS_BSWAP16 __builtin_bswap16
 #endif /* __has_builtin(__builtin_bswap16) */
-#if __has_builtin(__builtin_bswap32)
+#if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32)
 #define MBEDTLS_BSWAP32 __builtin_bswap32
 #endif /* __has_builtin(__builtin_bswap32) */
-#if __has_builtin(__builtin_bswap64)
+#if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64)
 #define MBEDTLS_BSWAP64 __builtin_bswap64
 #endif /* __has_builtin(__builtin_bswap64) */
 #endif /* defined(__clang__) && defined(__has_builtin) */
@@ -170,13 +170,19 @@
  * Detect MSVC built-in byteswap routines
  */
 #if defined(_MSC_VER)
+#if !defined(MBEDTLS_BSWAP16)
 #define MBEDTLS_BSWAP16 _byteswap_ushort
+#endif
+#if !defined(MBEDTLS_BSWAP32)
 #define MBEDTLS_BSWAP32 _byteswap_ulong
+#endif
+#if !defined(MBEDTLS_BSWAP64)
 #define MBEDTLS_BSWAP64 _byteswap_uint64
+#endif
 #endif /* defined(_MSC_VER) */
 
 /* Detect armcc built-in byteswap routine */
-#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000)
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32)
 #define MBEDTLS_BSWAP32 __rev
 #endif
 
@@ -239,8 +245,8 @@
  *                  byte of the four bytes to build the 32 bits unsigned
  *                  integer from.
  */
-#define MBEDTLS_GET_UINT32_BE(data, offset)                              \
-    ((MBEDTLS_IS_BIG_ENDIAN)                                            \
+#define MBEDTLS_GET_UINT32_BE(data, offset)                                \
+    ((MBEDTLS_IS_BIG_ENDIAN)                                               \
         ? mbedtls_get_unaligned_uint32((data) + (offset))                  \
         : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
     )
@@ -254,11 +260,11 @@
  * \param   offset  Offset from \p data where to put the most significant
  *                  byte of the 32 bits unsigned integer \p n.
  */
-#define MBEDTLS_PUT_UINT32_BE(n, data, offset)                             \
+#define MBEDTLS_PUT_UINT32_BE(n, data, offset)                                   \
     {                                                                            \
-        if (MBEDTLS_IS_BIG_ENDIAN)                                             \
+        if (MBEDTLS_IS_BIG_ENDIAN)                                               \
         {                                                                        \
-            mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n));      \
+            mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n));     \
         }                                                                        \
         else                                                                     \
         {                                                                        \
@@ -275,8 +281,8 @@
  *                  byte of the four bytes to build the 32 bits unsigned
  *                  integer from.
  */
-#define MBEDTLS_GET_UINT32_LE(data, offset)                              \
-    ((MBEDTLS_IS_BIG_ENDIAN)                                            \
+#define MBEDTLS_GET_UINT32_LE(data, offset)                                \
+    ((MBEDTLS_IS_BIG_ENDIAN)                                               \
         ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
         : mbedtls_get_unaligned_uint32((data) + (offset))                  \
     )
@@ -291,15 +297,15 @@
  * \param   offset  Offset from \p data where to put the least significant
  *                  byte of the 32 bits unsigned integer \p n.
  */
-#define MBEDTLS_PUT_UINT32_LE(n, data, offset)                             \
+#define MBEDTLS_PUT_UINT32_LE(n, data, offset)                                   \
     {                                                                            \
-        if (MBEDTLS_IS_BIG_ENDIAN)                                             \
+        if (MBEDTLS_IS_BIG_ENDIAN)                                               \
         {                                                                        \
             mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
         }                                                                        \
         else                                                                     \
         {                                                                        \
-            mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n)));      \
+            mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n)));   \
         }                                                                        \
     }
 
@@ -312,8 +318,8 @@
  *                  byte of the two bytes to build the 16 bits unsigned
  *                  integer from.
  */
-#define MBEDTLS_GET_UINT16_LE(data, offset)                              \
-    ((MBEDTLS_IS_BIG_ENDIAN)                                            \
+#define MBEDTLS_GET_UINT16_LE(data, offset)                                \
+    ((MBEDTLS_IS_BIG_ENDIAN)                                               \
         ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
         : mbedtls_get_unaligned_uint16((data) + (offset))                  \
     )
@@ -327,15 +333,15 @@
  * \param   offset  Offset from \p data where to put the least significant
  *                  byte of the 16 bits unsigned integer \p n.
  */
-#define MBEDTLS_PUT_UINT16_LE(n, data, offset)                             \
+#define MBEDTLS_PUT_UINT16_LE(n, data, offset)                                   \
     {                                                                            \
-        if (MBEDTLS_IS_BIG_ENDIAN)                                             \
+        if (MBEDTLS_IS_BIG_ENDIAN)                                               \
         {                                                                        \
             mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
         }                                                                        \
         else                                                                     \
         {                                                                        \
-            mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n));      \
+            mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n));     \
         }                                                                        \
     }
 
@@ -348,8 +354,8 @@
  *                  byte of the two bytes to build the 16 bits unsigned
  *                  integer from.
  */
-#define MBEDTLS_GET_UINT16_BE(data, offset)                              \
-    ((MBEDTLS_IS_BIG_ENDIAN)                                            \
+#define MBEDTLS_GET_UINT16_BE(data, offset)                                \
+    ((MBEDTLS_IS_BIG_ENDIAN)                                               \
         ? mbedtls_get_unaligned_uint16((data) + (offset))                  \
         : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
     )
@@ -363,11 +369,11 @@
  * \param   offset  Offset from \p data where to put the most significant
  *                  byte of the 16 bits unsigned integer \p n.
  */
-#define MBEDTLS_PUT_UINT16_BE(n, data, offset)                             \
+#define MBEDTLS_PUT_UINT16_BE(n, data, offset)                                   \
     {                                                                            \
-        if (MBEDTLS_IS_BIG_ENDIAN)                                             \
+        if (MBEDTLS_IS_BIG_ENDIAN)                                               \
         {                                                                        \
-            mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n));      \
+            mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n));     \
         }                                                                        \
         else                                                                     \
         {                                                                        \
@@ -384,11 +390,11 @@
  *                  byte of the three bytes to build the 24 bits unsigned
  *                  integer from.
  */
-#define MBEDTLS_GET_UINT24_BE(data, offset)                  \
-    (                                                           \
-        ((uint32_t) (data)[(offset)] << 16)         \
-        | ((uint32_t) (data)[(offset) + 1] << 8)         \
-        | ((uint32_t) (data)[(offset) + 2])         \
+#define MBEDTLS_GET_UINT24_BE(data, offset)        \
+    (                                              \
+        ((uint32_t) (data)[(offset)] << 16)        \
+        | ((uint32_t) (data)[(offset) + 1] << 8)   \
+        | ((uint32_t) (data)[(offset) + 2])        \
     )
 
 /**
@@ -401,8 +407,8 @@
  *                  byte of the 24 bits unsigned integer \p n.
  */
 #define MBEDTLS_PUT_UINT24_BE(n, data, offset)                \
-    {                                                               \
-        (data)[(offset)] = MBEDTLS_BYTE_2(n);             \
+    {                                                         \
+        (data)[(offset)] = MBEDTLS_BYTE_2(n);                 \
         (data)[(offset) + 1] = MBEDTLS_BYTE_1(n);             \
         (data)[(offset) + 2] = MBEDTLS_BYTE_0(n);             \
     }
@@ -416,9 +422,9 @@
  *                  byte of the three bytes to build the 24 bits unsigned
  *                  integer from.
  */
-#define MBEDTLS_GET_UINT24_LE(data, offset)                   \
-    (                                                           \
-        ((uint32_t) (data)[(offset)])         \
+#define MBEDTLS_GET_UINT24_LE(data, offset)               \
+    (                                                     \
+        ((uint32_t) (data)[(offset)])                     \
         | ((uint32_t) (data)[(offset) + 1] <<  8)         \
         | ((uint32_t) (data)[(offset) + 2] << 16)         \
     )
@@ -433,8 +439,8 @@
  *                  byte of the 24 bits unsigned integer \p n.
  */
 #define MBEDTLS_PUT_UINT24_LE(n, data, offset)                \
-    {                                                               \
-        (data)[(offset)] = MBEDTLS_BYTE_0(n);             \
+    {                                                         \
+        (data)[(offset)] = MBEDTLS_BYTE_0(n);                 \
         (data)[(offset) + 1] = MBEDTLS_BYTE_1(n);             \
         (data)[(offset) + 2] = MBEDTLS_BYTE_2(n);             \
     }
@@ -448,8 +454,8 @@
  *                  byte of the eight bytes to build the 64 bits unsigned
  *                  integer from.
  */
-#define MBEDTLS_GET_UINT64_BE(data, offset)                              \
-    ((MBEDTLS_IS_BIG_ENDIAN)                                            \
+#define MBEDTLS_GET_UINT64_BE(data, offset)                                \
+    ((MBEDTLS_IS_BIG_ENDIAN)                                               \
         ? mbedtls_get_unaligned_uint64((data) + (offset))                  \
         : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
     )
@@ -463,11 +469,11 @@
  * \param   offset  Offset from \p data where to put the most significant
  *                  byte of the 64 bits unsigned integer \p n.
  */
-#define MBEDTLS_PUT_UINT64_BE(n, data, offset)                             \
+#define MBEDTLS_PUT_UINT64_BE(n, data, offset)                                   \
     {                                                                            \
-        if (MBEDTLS_IS_BIG_ENDIAN)                                             \
+        if (MBEDTLS_IS_BIG_ENDIAN)                                               \
         {                                                                        \
-            mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n));      \
+            mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n));     \
         }                                                                        \
         else                                                                     \
         {                                                                        \
@@ -484,8 +490,8 @@
  *                  byte of the eight bytes to build the 64 bits unsigned
  *                  integer from.
  */
-#define MBEDTLS_GET_UINT64_LE(data, offset)                              \
-    ((MBEDTLS_IS_BIG_ENDIAN)                                            \
+#define MBEDTLS_GET_UINT64_LE(data, offset)                                \
+    ((MBEDTLS_IS_BIG_ENDIAN)                                               \
         ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
         : mbedtls_get_unaligned_uint64((data) + (offset))                  \
     )
@@ -499,15 +505,15 @@
  * \param   offset  Offset from \p data where to put the least significant
  *                  byte of the 64 bits unsigned integer \p n.
  */
-#define MBEDTLS_PUT_UINT64_LE(n, data, offset)                             \
+#define MBEDTLS_PUT_UINT64_LE(n, data, offset)                                   \
     {                                                                            \
-        if (MBEDTLS_IS_BIG_ENDIAN)                                             \
+        if (MBEDTLS_IS_BIG_ENDIAN)                                               \
         {                                                                        \
             mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
         }                                                                        \
         else                                                                     \
         {                                                                        \
-            mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n));      \
+            mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n));     \
         }                                                                        \
     }
 
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index dc7a27f..45cf807 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -19,6 +19,8 @@
 
 #include "common.h"
 
+#include "mbedtls/platform_util.h"
+
 #if defined(MBEDTLS_PK_C)
 #include "pk_wrap.h"
 #include "mbedtls/error.h"
@@ -26,39 +28,34 @@
 /* Even if RSA not activated, for the sake of RSA-alt */
 #include "mbedtls/rsa.h"
 
-#include <string.h>
-
 #if defined(MBEDTLS_ECP_C)
 #include "mbedtls/ecp.h"
 #endif
 
-#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
-#include "pkwrite.h"
-#endif
-
 #if defined(MBEDTLS_ECDSA_C)
 #include "mbedtls/ecdsa.h"
 #endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "mbedtls/asn1write.h"
-#endif
-
-#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
-#include "mbedtls/platform_util.h"
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PSA_CRYPTO_C)
+#include "pkwrite.h"
 #endif
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
 #include "mbedtls/psa_util.h"
-#include "mbedtls/asn1.h"
 #include "hash_info.h"
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+#include "mbedtls/asn1write.h"
+#include "mbedtls/asn1.h"
 #endif
+#endif  /* MBEDTLS_USE_PSA_CRYPTO */
 
 #include "mbedtls/platform.h"
 
 #include <limits.h>
 #include <stdint.h>
+#include <string.h>
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
 int mbedtls_pk_error_from_psa(psa_status_t status)
@@ -685,11 +682,14 @@
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_status_t status;
-    mbedtls_pk_context key;
-    int key_len;
-    unsigned char buf[MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES];
+    size_t key_len;
+    /* This buffer will initially contain the public key and then the signature
+     * but at different points in time. For all curves except secp224k1, which
+     * is not currently supported in PSA, the public key is one byte longer
+     * (header byte + 2 numbers, while the signature is only 2 numbers),
+     * so use that as the buffer size. */
+    unsigned char buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
     unsigned char *p;
-    mbedtls_pk_info_t pk_info = mbedtls_eckey_info;
     psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;
     size_t curve_bits;
     psa_ecc_family_t curve =
@@ -701,22 +701,19 @@
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
-    /* mbedtls_pk_write_pubkey() expects a full PK context;
-     * re-construct one to make it happy */
-    key.pk_info = &pk_info;
-    key.pk_ctx = ctx;
-    p = buf + sizeof(buf);
-    key_len = mbedtls_pk_write_pubkey(&p, buf, &key);
-    if (key_len <= 0) {
-        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-    }
-
     psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve));
     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
     psa_set_key_algorithm(&attributes, psa_sig_md);
 
+    ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q,
+                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                         &key_len, buf, sizeof(buf));
+    if (ret != 0) {
+        goto cleanup;
+    }
+
     status = psa_import_key(&attributes,
-                            buf + sizeof(buf) - key_len, key_len,
+                            buf, key_len,
                             &key_id);
     if (status != PSA_SUCCESS) {
         ret = mbedtls_pk_error_from_psa(status);
@@ -864,54 +861,6 @@
     return 0;
 }
 
-/* Locate an ECDSA privateKey in a RFC 5915, or SEC1 Appendix C.4 ASN.1 buffer
- *
- * [in/out] buf: ASN.1 buffer start as input - ECDSA privateKey start as output
- * [in] end: ASN.1 buffer end
- * [out] key_len: the ECDSA privateKey length in bytes
- */
-static int find_ecdsa_private_key(unsigned char **buf, unsigned char *end,
-                                  size_t *key_len)
-{
-    size_t len;
-    int ret;
-
-    /*
-     * RFC 5915, or SEC1 Appendix C.4
-     *
-     * ECPrivateKey ::= SEQUENCE {
-     *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
-     *      privateKey     OCTET STRING,
-     *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
-     *      publicKey  [1] BIT STRING OPTIONAL
-     *    }
-     */
-
-    if ((ret = mbedtls_asn1_get_tag(buf, end, &len,
-                                    MBEDTLS_ASN1_CONSTRUCTED |
-                                    MBEDTLS_ASN1_SEQUENCE)) != 0) {
-        return ret;
-    }
-
-    /* version */
-    if ((ret = mbedtls_asn1_get_tag(buf, end, &len,
-                                    MBEDTLS_ASN1_INTEGER)) != 0) {
-        return ret;
-    }
-
-    *buf += len;
-
-    /* privateKey */
-    if ((ret = mbedtls_asn1_get_tag(buf, end, &len,
-                                    MBEDTLS_ASN1_OCTET_STRING)) != 0) {
-        return ret;
-    }
-
-    *key_len = len;
-
-    return 0;
-}
-
 static int ecdsa_sign_wrap(void *ctx_arg, mbedtls_md_type_t md_alg,
                            const unsigned char *hash, size_t hash_len,
                            unsigned char *sig, size_t sig_size, size_t *sig_len,
@@ -922,19 +871,18 @@
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_status_t status;
-    mbedtls_pk_context key;
-    size_t key_len;
-    unsigned char buf[MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES];
-    unsigned char *p;
-    psa_algorithm_t psa_hash = mbedtls_hash_info_psa_from_md(md_alg);
+    unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-    psa_algorithm_t psa_sig_md = PSA_ALG_DETERMINISTIC_ECDSA(psa_hash);
+    psa_algorithm_t psa_sig_md =
+        PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
 #else
-    psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA(psa_hash);
+    psa_algorithm_t psa_sig_md =
+        PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
 #endif
     size_t curve_bits;
     psa_ecc_family_t curve =
         mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);
+    size_t key_len = PSA_BITS_TO_BYTES(curve_bits);
 
     /* PSA has its own RNG */
     ((void) f_rng);
@@ -944,17 +892,10 @@
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
-    /* mbedtls_pk_write_key_der() expects a full PK context;
-     * re-construct one to make it happy */
-    key.pk_info = &mbedtls_eckey_info;
-    key.pk_ctx = ctx;
-    key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf));
-    if (key_len <= 0) {
-        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    if (key_len > sizeof(buf)) {
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     }
-
-    p = buf + sizeof(buf) - key_len;
-    ret = find_ecdsa_private_key(&p, buf + sizeof(buf), &key_len);
+    ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len);
     if (ret != 0) {
         goto cleanup;
     }
@@ -964,7 +905,7 @@
     psa_set_key_algorithm(&attributes, psa_sig_md);
 
     status = psa_import_key(&attributes,
-                            p, key_len,
+                            buf, key_len,
                             &key_id);
     if (status != PSA_SUCCESS) {
         ret = mbedtls_pk_error_from_psa(status);
@@ -1003,8 +944,7 @@
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
 
-#if defined(MBEDTLS_ECDSA_C)
-#if defined(MBEDTLS_ECP_RESTARTABLE)
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 /* Forward declarations */
 static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
                                 const unsigned char *hash, size_t hash_len,
@@ -1110,8 +1050,7 @@
 cleanup:
     return ret;
 }
-#endif /* MBEDTLS_ECP_RESTARTABLE */
-#endif /* MBEDTLS_ECDSA_C */
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
 static int eckey_check_pair(const void *pub, const void *prv,
                             int (*f_rng)(void *, unsigned char *, size_t),
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index b96c7b4..0efebb4 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -3156,17 +3156,18 @@
 /* Asymmetric interruptible cryptography                        */
 /****************************************************************/
 
+static uint32_t psa_interruptible_max_ops = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED;
+
 void psa_interruptible_set_max_ops(uint32_t max_ops)
 {
-    psa_driver_wrapper_interruptible_set_max_ops(max_ops);
+    psa_interruptible_max_ops = max_ops;
 }
 
 uint32_t psa_interruptible_get_max_ops(void)
 {
-    return psa_driver_wrapper_interruptible_get_max_ops();
+    return psa_interruptible_max_ops;
 }
 
-
 uint32_t psa_sign_hash_get_num_ops(
     const psa_sign_hash_interruptible_operation_t *operation)
 {
@@ -3461,12 +3462,8 @@
 /* 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)) && \
@@ -3479,16 +3476,13 @@
     }
 
     mbedtls_ecp_set_max_ops(max_ops);
+#else
+    (void) max_ops;
 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
         * defined( MBEDTLS_ECP_RESTARTABLE ) */
 }
 
-uint32_t mbedtls_psa_interruptible_get_max_ops(void)
-{
-    return mbedtls_psa_interruptible_max_ops;
-}
-
 uint32_t mbedtls_psa_sign_hash_get_num_ops(
     const mbedtls_psa_sign_hash_interruptible_operation_t *operation)
 {
@@ -3547,11 +3541,6 @@
     /* 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,
@@ -3616,6 +3605,9 @@
     mbedtls_mpi_init(&r);
     mbedtls_mpi_init(&s);
 
+    /* Ensure max_ops is set to the current value (or default). */
+    mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops());
+
     if (signature_size < 2 * operation->coordinate_bytes) {
         status = PSA_ERROR_BUFFER_TOO_SMALL;
         goto exit;
@@ -3767,11 +3759,6 @@
     /* 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,
@@ -3856,6 +3843,9 @@
 
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
+    /* Ensure max_ops is set to the current value (or default). */
+    mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops());
+
     status = mbedtls_to_psa_error(
         mbedtls_ecdsa_verify_restartable(&operation->ctx->grp,
                                          operation->hash,
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
index e3edec7..b167506 100644
--- a/library/psa_crypto_driver_wrappers.h
+++ b/library/psa_crypto_driver_wrappers.h
@@ -70,10 +70,6 @@
  * 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);
 
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 0f42b8c..aa11d4e 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,24 +433,6 @@
     }
 }
 
-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 )
 {
diff --git a/tests/compat.sh b/tests/compat.sh
index 8f7d72c..12613bf 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -534,6 +534,16 @@
     esac
 }
 
+# o_check_ciphersuite STANDARD_CIPHER_SUITE
+o_check_ciphersuite()
+{
+    if [ "${O_SUPPORT_ECDH}" = "NO" ]; then
+        case "$1" in
+            *ECDH_*) SKIP_NEXT="YES"
+        esac
+    fi
+}
+
 setup_arguments()
 {
     O_MODE=""
@@ -603,6 +613,11 @@
             ;;
     esac
 
+    case $($OPENSSL ciphers ALL) in
+        *ECDH-ECDSA*|*ECDH-RSA*) O_SUPPORT_ECDH="YES";;
+        *) O_SUPPORT_ECDH="NO";;
+    esac
+
     if [ "X$VERIFY" = "XYES" ];
     then
         M_SERVER_ARGS="$M_SERVER_ARGS ca_file=data_files/test-ca_cat12.crt auth_mode=required"
@@ -819,7 +834,7 @@
             if [ $EXIT -eq 0 ]; then
                 RESULT=0
             else
-                # If the cipher isn't supported...
+                # If it is NULL cipher ...
                 if grep 'Cipher is (NONE)' $CLI_OUT >/dev/null; then
                     RESULT=1
                 else
@@ -1033,6 +1048,7 @@
                         start_server "OpenSSL"
                         translate_ciphers m $M_CIPHERS
                         for i in $ciphers; do
+                            o_check_ciphersuite "${i%%=*}"
                             run_client mbedTLS ${i%%=*} ${i#*=}
                         done
                         stop_server
@@ -1042,6 +1058,7 @@
                         start_server "mbedTLS"
                         translate_ciphers o $O_CIPHERS
                         for i in $ciphers; do
+                            o_check_ciphersuite "${i%%=*}"
                             run_client OpenSSL ${i%%=*} ${i#*=}
                         done
                         stop_server
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index db16ab7..1b122ee 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -1275,7 +1275,7 @@
 pkcs7_test_file = pkcs7_data.bin
 
 $(pkcs7_test_file):
-	echo -e "Hello\xd" > $@
+	printf "Hello\15\n" > $@
 all_final += $(pkcs7_test_file)
 
 pkcs7_zerolendata.bin:
@@ -1283,7 +1283,7 @@
 all_final += pkcs7_zerolendata.bin
 
 pkcs7_data_1.bin:
-	echo -e "2\xd" > $@
+	printf "2\15\n" > $@
 all_final += pkcs7_data_1.bin
 
 # Generate signing cert
@@ -1363,19 +1363,31 @@
 # pkcs7 signature file with corrupted CERT
 pkcs7_data_signed_badcert.der: pkcs7_data_cert_signed_sha256.der
 	cp pkcs7_data_cert_signed_sha256.der $@
-	echo -en '\xa1' | dd of=$@ bs=1 seek=547 conv=notrunc
+	echo 'a1' | xxd -r -p | dd of=$@ bs=1 seek=547 conv=notrunc
 all_final += pkcs7_data_signed_badcert.der
 
 # pkcs7 signature file with corrupted signer info
 pkcs7_data_signed_badsigner.der: pkcs7_data_cert_signed_sha256.der
 	cp pkcs7_data_cert_signed_sha256.der $@
-	echo -en '\xa1' | dd of=$@ bs=1 seek=918 conv=notrunc
+	echo 'a1' | xxd -r -p | dd of=$@ bs=1 seek=918 conv=notrunc
 all_final += pkcs7_data_signed_badsigner.der
 
+# pkcs7 signature file with invalid tag in signerInfo[1].serial after long issuer name
+pkcs7_signerInfo_1_serial_invalid_tag_after_long_name.der: pkcs7_data_multiple_signed.der
+	cp $< $@
+	echo 'a1' | xxd -r -p | dd of=$@ bs=1 seek=498 conv=notrunc
+all_final += pkcs7_signerInfo_1_serial_invalid_tag_after_long_name.der
+
+# pkcs7 signature file with invalid tag in signerInfo[2]
+pkcs7_signerInfo_2_invalid_tag.der: pkcs7_data_3_signed.der
+	cp $< $@
+	echo 'a1' | xxd -r -p | dd of=$@ bs=1 seek=810 conv=notrunc
+all_final += pkcs7_signerInfo_2_invalid_tag.der
+
 # pkcs7 file with version 2
 pkcs7_data_cert_signed_v2.der: pkcs7_data_cert_signed_sha256.der
 	cp pkcs7_data_cert_signed_sha256.der $@
-	echo -en '\x02' | dd of=$@ bs=1 seek=25 conv=notrunc
+	echo '02' | xxd -r -p | dd of=$@ bs=1 seek=25 conv=notrunc
 all_final += pkcs7_data_cert_signed_v2.der
 
 pkcs7_data_cert_encrypted.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
@@ -1386,12 +1398,12 @@
 # For some interesting sizes, what happens if we make them off-by-one?
 pkcs7_signerInfo_issuer_invalid_size.der: pkcs7_data_cert_signed_sha256.der
 	cp $< $@
-	echo -en '\x35' | dd of=$@ seek=919 bs=1 conv=notrunc
+	echo '35' | xxd -r -p | dd of=$@ seek=919 bs=1 conv=notrunc
 all_final += pkcs7_signerInfo_issuer_invalid_size.der
 
 pkcs7_signerInfo_serial_invalid_size.der: pkcs7_data_cert_signed_sha256.der
 	cp $< $@
-	echo -en '\x15' | dd of=$@ seek=973 bs=1 conv=notrunc
+	echo '15' | xxd -r -p | dd of=$@ seek=973 bs=1 conv=notrunc
 all_final += pkcs7_signerInfo_serial_invalid_size.der
 
 # pkcs7 signature file just with signed data
diff --git a/tests/data_files/pkcs7_get_signers_info_set-leak-fuzz_pkcs7-4541044530479104.der b/tests/data_files/pkcs7_get_signers_info_set-leak-fuzz_pkcs7-4541044530479104.der
deleted file mode 100644
index 51aef0d..0000000
--- a/tests/data_files/pkcs7_get_signers_info_set-leak-fuzz_pkcs7-4541044530479104.der
+++ /dev/null
Binary files differ
diff --git a/tests/data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der b/tests/data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der
deleted file mode 100644
index ce4fb3b..0000000
--- a/tests/data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der
+++ /dev/null
Binary files differ
diff --git a/tests/data_files/pkcs7_signerInfo_1_serial_invalid_tag_after_long_name.der b/tests/data_files/pkcs7_signerInfo_1_serial_invalid_tag_after_long_name.der
new file mode 100644
index 0000000..fe55390
--- /dev/null
+++ b/tests/data_files/pkcs7_signerInfo_1_serial_invalid_tag_after_long_name.der
Binary files differ
diff --git a/tests/data_files/pkcs7_signerInfo_2_invalid_tag.der b/tests/data_files/pkcs7_signerInfo_2_invalid_tag.der
new file mode 100644
index 0000000..3a42874
--- /dev/null
+++ b/tests/data_files/pkcs7_signerInfo_2_invalid_tag.der
Binary files differ
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 7d91fa2..353ec69 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1972,6 +1972,7 @@
     # aesni.c and padlock.c reference mbedtls_aes_context fields directly.
     scripts/config.py unset MBEDTLS_AESNI_C
     scripts/config.py unset MBEDTLS_PADLOCK_C
+    scripts/config.py unset MBEDTLS_AESCE_C
     # MBEDTLS_ECP_RESTARTABLE is documented as incompatible.
     scripts/config.py unset MBEDTLS_ECP_RESTARTABLE
     # You can only have one threading implementation: alt or pthread, not both.
@@ -3341,6 +3342,7 @@
     scripts/config.py unset MBEDTLS_HAVE_ASM
     scripts/config.py unset MBEDTLS_AESNI_C
     scripts/config.py unset MBEDTLS_PADLOCK_C
+    scripts/config.py unset MBEDTLS_AESCE_C
     make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT32'
 
     msg "test: gcc, force 32-bit bignum limbs"
@@ -3352,6 +3354,7 @@
     scripts/config.py unset MBEDTLS_HAVE_ASM
     scripts/config.py unset MBEDTLS_AESNI_C
     scripts/config.py unset MBEDTLS_PADLOCK_C
+    scripts/config.py unset MBEDTLS_AESCE_C
     make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64'
 
     msg "test: gcc, force 64-bit bignum limbs"
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index 531a2f1..01d8d2d 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -618,7 +618,7 @@
 pk_psa_sign:MBEDTLS_ECP_DP_BP512R1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512
 
 PSA wrapped sign: RSA PKCS1 v1.5
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME:MBEDTLS_PK_WRITE_C
 pk_psa_sign:1024:PSA_KEY_TYPE_RSA_KEY_PAIR:1024
 
 PK Sign ext:RSA2048,PK_RSA,MD_SHA256
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index a99b6c0..8b4b675 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -1238,12 +1238,22 @@
     }
 
     /* Export underlying public key for re-importing in a legacy context. */
+#if defined(MBEDTLS_PK_WRITE_C)
     ret = mbedtls_pk_write_pubkey_der(&pk, pkey_legacy,
                                       sizeof(pkey_legacy));
     TEST_ASSERT(ret >= 0);
     klen_legacy = (size_t) ret;
     /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer. */
     pkey_legacy_start = pkey_legacy + sizeof(pkey_legacy) - klen_legacy;
+#else
+    ret = mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec(pk)->grp),
+                                         &(mbedtls_pk_ec(pk)->Q),
+                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                         &klen_legacy, pkey_legacy,
+                                         sizeof(pkey_legacy));
+    TEST_EQUAL(ret, 0);
+    pkey_legacy_start = pkey_legacy;
+#endif /* MBEDTLS_PK_WRITE_C */
 
     /* Turn PK context into an opaque one. */
     TEST_ASSERT(mbedtls_pk_wrap_as_opaque(&pk, &key_id, alg_psa,
@@ -1264,12 +1274,21 @@
                                 NULL, NULL) == 0);
 
     /* Export underlying public key for re-importing in a psa context. */
+#if defined(MBEDTLS_PK_WRITE_C)
     ret = mbedtls_pk_write_pubkey_der(&pk, pkey_psa,
                                       sizeof(pkey_psa));
     TEST_ASSERT(ret >= 0);
     klen_psa = (size_t) ret;
     /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer. */
     pkey_psa_start = pkey_psa + sizeof(pkey_psa) - klen_psa;
+#else
+    psa_status_t status;
+
+    status = psa_export_public_key(key_id, pkey_psa, sizeof(pkey_psa),
+                                   &klen_psa);
+    TEST_EQUAL(status, PSA_SUCCESS);
+    pkey_psa_start = pkey_psa;
+#endif /* MBEDTLS_PK_WRITE_C */
 
     TEST_ASSERT(klen_psa == klen_legacy);
     TEST_ASSERT(memcmp(pkey_psa_start, pkey_legacy_start, klen_psa) == 0);
@@ -1278,8 +1297,24 @@
     TEST_ASSERT(PSA_SUCCESS == psa_destroy_key(key_id));
 
     mbedtls_pk_init(&pk);
-    TEST_ASSERT(mbedtls_pk_parse_public_key(&pk, pkey_legacy_start,
-                                            klen_legacy) == 0);
+
+    /* If we used "pk_write" previously, then we go for a "pk_parse" here;
+     * otherwise if we went for "ecp_point_write_binary" then we'll go
+     * for a "ecp_point_read_binary" here. This allows to drop dependencies
+     * on "PK_WRITE" and "PK_PARSE" if required */
+#if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_PK_PARSE_C)
+    TEST_EQUAL(mbedtls_pk_parse_public_key(&pk, pkey_legacy_start,
+                                           klen_legacy), 0);
+#else
+    TEST_EQUAL(mbedtls_pk_setup(&pk,
+                                mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)), 0);
+    TEST_EQUAL(mbedtls_ecp_group_load(
+                   &(mbedtls_pk_ec(pk)->grp),
+                   (mbedtls_ecp_group_id) parameter_arg), 0);
+    TEST_EQUAL(mbedtls_ecp_point_read_binary(&(mbedtls_pk_ec(pk)->grp),
+                                             &(mbedtls_pk_ec(pk)->Q),
+                                             pkey_legacy_start, klen_legacy), 0);
+#endif
     TEST_ASSERT(mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA256,
                                   hash, sizeof(hash), sig, sig_len) == 0);
 
diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data
index 9948537..da8146b 100644
--- a/tests/suites/test_suite_pkcs7.data
+++ b/tests/suites/test_suite_pkcs7.data
@@ -78,13 +78,13 @@
 depends_on:MBEDTLS_SHA256_C
 pkcs7_parse:"data_files/pkcs7_signerInfo_serial_invalid_size.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO
 
-pkcs7_get_signers_info_set error handling (6213931373035520)
-depends_on:MBEDTLS_RIPEMD160_C
-pkcs7_parse:"data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
+PKCS7 Signed Data Parse Fail Corrupt signerInfos[2] (6213931373035520)
+depends_on:MBEDTLS_SHA256_C
+pkcs7_parse:"data_files/pkcs7_signerInfo_2_invalid_tag.der":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
 
-pkcs7_get_signers_info_set error handling (4541044530479104)
-depends_on:MBEDTLS_RIPEMD160_C
-pkcs7_parse:"data_files/pkcs7_get_signers_info_set-leak-fuzz_pkcs7-4541044530479104.der": MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
+PKCS7 Signed Data Parse Fail Corrupt signerInfos[1].issuerAndSerialNumber.serialNumber, after multi-element .name (4541044530479104)
+depends_on:MBEDTLS_SHA256_C
+pkcs7_parse:"data_files/pkcs7_signerInfo_1_serial_invalid_tag_after_long_name.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO
 
 PKCS7 Only Signed Data Parse Pass #15
 depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index f340a7f..cfcdac1 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -4561,9 +4561,9 @@
 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_edgecase_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
+PSA sign/vrfy hash int 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"
+interruptible_signverify_hash_ops_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
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 4113c97..182443a 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -6879,6 +6879,10 @@
  *
  * 3. Test the number of calls to psa_sign_hash_complete() required are as
  *    expected for different max_ops values.
+ *
+ * 4. Test that the number of ops done prior to starting signing and after abort
+ *    is zero and that each successful signing stage completes some ops (this is
+ *    not mandated by the PSA specification, but is currently the case).
  */
 void sign_verify_hash_interruptible(int key_type_arg, data_t *key_data,
                                     int alg_arg, data_t *input_data,
@@ -6894,6 +6898,8 @@
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t status = PSA_OPERATION_INCOMPLETE;
     uint32_t max_ops = max_ops_arg;
+    uint32_t num_ops = 0;
+    uint32_t num_ops_prior = 0;
     size_t num_completes = 0;
     size_t min_completes = 0;
     size_t max_completes = 0;
@@ -6928,10 +6934,16 @@
     interruptible_signverify_get_minmax_completes(max_ops, PSA_SUCCESS,
                                                   &min_completes, &max_completes);
 
+    num_ops_prior = psa_sign_hash_get_num_ops(&sign_operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
     /* Start performing the signature. */
     PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
                                    input_data->x, input_data->len));
 
+    num_ops_prior = psa_sign_hash_get_num_ops(&sign_operation);
+    TEST_ASSERT(num_ops_prior == 0);
+
     /* Continue performing the signature until complete. */
     do {
 
@@ -6940,6 +6952,17 @@
                                         &signature_length);
 
         num_completes++;
+
+        if (status == PSA_SUCCESS || status == PSA_OPERATION_INCOMPLETE) {
+            num_ops = psa_sign_hash_get_num_ops(&sign_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 (status == PSA_OPERATION_INCOMPLETE);
 
     TEST_ASSERT(status == PSA_SUCCESS);
@@ -6949,6 +6972,9 @@
 
     PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
 
+    num_ops = psa_sign_hash_get_num_ops(&sign_operation);
+    TEST_ASSERT(num_ops == 0);
+
     /* Check that the signature length looks sensible. */
     TEST_LE_U(signature_length, signature_size);
     TEST_ASSERT(signature_length > 0);
@@ -7057,6 +7083,12 @@
  * 3. Test that the number of ops done prior to start and after abort is zero
  *    and that each successful stage completes some ops (this is not mandated by
  *    the PSA specification, but is currently the case).
+ *
+ * 4. Test that calling psa_sign_hash_get_num_ops() multiple times between
+ *    complete() calls does not alter the number of ops returned.
+ *
+ * 5. Test that after corrupting the hash, the verification detects an invalid
+ *    signature.
  */
 void verify_hash_interruptible(int key_type_arg, data_t *key_data,
                                int alg_arg, data_t *hash_data,
@@ -7141,6 +7173,25 @@
     num_ops = psa_verify_hash_get_num_ops(&operation);
     TEST_ASSERT(num_ops == 0);
 
+    if (hash_data->len != 0) {
+        /* Flip a bit in the hash 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. */
+        hash_data->x[0] ^= 1;
+
+        /* Start verification. */
+        PSA_ASSERT(psa_verify_hash_start(&operation, key, alg,
+                                         hash_data->x, hash_data->len,
+                                         signature_data->x, signature_data->len));
+
+        /* Continue performing the signature until complete. */
+        do {
+            status = psa_verify_hash_complete(&operation);
+        } while (status == PSA_OPERATION_INCOMPLETE);
+
+        TEST_ASSERT(status ==  PSA_ERROR_INVALID_SIGNATURE);
+    }
+
 exit:
     psa_reset_key_attributes(&attributes);
     psa_destroy_key(key);
@@ -7515,41 +7566,6 @@
     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. --- */
 
@@ -7630,15 +7646,21 @@
 
 /* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
 /**
- * interruptible_signverify_hash_maxops_tests() test intentions:
+ * interruptible_signverify_hash_ops_tests() test intentions:
  *
  * Note: This test can currently only handle ECDSA.
  *
  * 1. Test that setting max ops is reflected in both interruptible sign and
  *    verify hash
+ * 2. Test that changing the value of max_ops to unlimited during an operation
+ *    causes that operation to complete in the next call.
+ *
+ * 3. Test that calling get_num_ops() between complete calls gives the same
+ *    result as calling get_num_ops() once at the end of the operation.
  */
-void interruptible_signverify_hash_maxops_tests(int key_type_arg,
-                                                data_t *key_data, int alg_arg, data_t *input_data)
+void interruptible_signverify_hash_ops_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;
@@ -7647,6 +7669,10 @@
     size_t key_bits;
     unsigned char *signature = NULL;
     size_t signature_size;
+    size_t signature_length = 0xdeadbeef;
+    uint32_t num_ops = 0;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
     psa_sign_hash_interruptible_operation_t sign_operation =
         psa_sign_hash_interruptible_operation_init();
     psa_verify_hash_interruptible_operation_t verify_operation =
@@ -7695,6 +7721,111 @@
 
     TEST_EQUAL(psa_interruptible_get_max_ops(), 0xbeef);
 
+    /* --- 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));
+
+    /* --- Test that not calling get_num_ops inbetween complete calls does not
+     *     result in lost ops. ---*/
+
+    psa_interruptible_set_max_ops(1);
+
+    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_ops = psa_sign_hash_get_num_ops(&sign_operation);
+
+    } while (status == PSA_OPERATION_INCOMPLETE);
+
+    PSA_ASSERT(status);
+
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
+
+    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);
+    } while (status == PSA_OPERATION_INCOMPLETE);
+
+    PSA_ASSERT(status);
+
+    TEST_EQUAL(num_ops, psa_sign_hash_get_num_ops(&sign_operation));
+
+    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));
+
+    /* Continue performing the verification until complete. */
+    do {
+        status = psa_verify_hash_complete(&verify_operation);
+
+        num_ops = psa_verify_hash_get_num_ops(&verify_operation);
+
+    } while (status == PSA_OPERATION_INCOMPLETE);
+
+    PSA_ASSERT(status);
+
+    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));
+
+    /* Continue performing the verification until complete. */
+    do {
+        status = psa_verify_hash_complete(&verify_operation);
+
+    } while (status == PSA_OPERATION_INCOMPLETE);
+
+    PSA_ASSERT(status);
+
+    TEST_EQUAL(num_ops, psa_verify_hash_get_num_ops(&verify_operation));
+
+    PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
+
 exit:
     /*
      * Key attributes may have been returned by psa_get_key_attributes()